Statistics
| Branch: | Tag: | Revision:

root / devflow / utils.py @ 18a2af6d

History | View | Annotate | Download (6.9 kB)

1 9fe1ecd8 Christos Stavrakakis
# Copyright (C) 2013 GRNET S.A. All rights reserved.
2 9fe1ecd8 Christos Stavrakakis
#
3 9fe1ecd8 Christos Stavrakakis
# Redistribution and use in source and binary forms, with or
4 9fe1ecd8 Christos Stavrakakis
# without modification, are permitted provided that the following
5 9fe1ecd8 Christos Stavrakakis
# conditions are met:
6 9fe1ecd8 Christos Stavrakakis
#
7 9fe1ecd8 Christos Stavrakakis
#   1. Redistributions of source code must retain the above
8 9fe1ecd8 Christos Stavrakakis
#      copyright notice, this list of conditions and the following
9 9fe1ecd8 Christos Stavrakakis
#      disclaimer.
10 9fe1ecd8 Christos Stavrakakis
#
11 9fe1ecd8 Christos Stavrakakis
#   2. Redistributions in binary form must reproduce the above
12 9fe1ecd8 Christos Stavrakakis
#      copyright notice, this list of conditions and the following
13 9fe1ecd8 Christos Stavrakakis
#      disclaimer in the documentation and/or other materials
14 9fe1ecd8 Christos Stavrakakis
#      provided with the distribution.
15 9fe1ecd8 Christos Stavrakakis
#
16 9fe1ecd8 Christos Stavrakakis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 9fe1ecd8 Christos Stavrakakis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 9fe1ecd8 Christos Stavrakakis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 9fe1ecd8 Christos Stavrakakis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 9fe1ecd8 Christos Stavrakakis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 9fe1ecd8 Christos Stavrakakis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 9fe1ecd8 Christos Stavrakakis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 9fe1ecd8 Christos Stavrakakis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 9fe1ecd8 Christos Stavrakakis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 9fe1ecd8 Christos Stavrakakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 9fe1ecd8 Christos Stavrakakis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 9fe1ecd8 Christos Stavrakakis
# POSSIBILITY OF SUCH DAMAGE.
28 9fe1ecd8 Christos Stavrakakis
#
29 9fe1ecd8 Christos Stavrakakis
# The views and conclusions contained in the software and
30 9fe1ecd8 Christos Stavrakakis
# documentation are those of the authors and should not be
31 9fe1ecd8 Christos Stavrakakis
# interpreted as representing official policies, either expressed
32 9fe1ecd8 Christos Stavrakakis
# or implied, of GRNET S.A.
33 9fe1ecd8 Christos Stavrakakis
34 9fe1ecd8 Christos Stavrakakis
import os
35 9fe1ecd8 Christos Stavrakakis
import git
36 42868817 Christos Stavrakakis
import sh
37 18a2af6d Ilias Tsitsimpis
import re
38 9fe1ecd8 Christos Stavrakakis
from collections import namedtuple
39 ffcbf2bb Christos Stavrakakis
from configobj import ConfigObj
40 ffcbf2bb Christos Stavrakakis
41 c181882a Christos Stavrakakis
from devflow import BRANCH_TYPES
42 9fe1ecd8 Christos Stavrakakis
43 9fe1ecd8 Christos Stavrakakis
44 ffcbf2bb Christos Stavrakakis
def get_repository(path=None):
45 9fe1ecd8 Christos Stavrakakis
    """Load the repository from the current working dir."""
46 ffcbf2bb Christos Stavrakakis
    if path is None:
47 ffcbf2bb Christos Stavrakakis
        path = os.getcwd()
48 9fe1ecd8 Christos Stavrakakis
    try:
49 ffcbf2bb Christos Stavrakakis
        return git.Repo(path)
50 9fe1ecd8 Christos Stavrakakis
    except git.InvalidGitRepositoryError:
51 9fe1ecd8 Christos Stavrakakis
        msg = "Cound not retrivie git information. Directory '%s'"\
52 ffcbf2bb Christos Stavrakakis
              " is not a git repository!" % path
53 9fe1ecd8 Christos Stavrakakis
        raise RuntimeError(msg)
54 9fe1ecd8 Christos Stavrakakis
55 9fe1ecd8 Christos Stavrakakis
56 ffcbf2bb Christos Stavrakakis
def get_config(path=None):
57 ffcbf2bb Christos Stavrakakis
    """Load configuration file."""
58 ffcbf2bb Christos Stavrakakis
    if path is None:
59 ffcbf2bb Christos Stavrakakis
        toplevel = get_vcs_info().toplevel
60 ffcbf2bb Christos Stavrakakis
        path = os.path.join(toplevel, "devflow.conf")
61 ffcbf2bb Christos Stavrakakis
62 ffcbf2bb Christos Stavrakakis
    config = ConfigObj(path)
63 ffcbf2bb Christos Stavrakakis
    return config
64 ffcbf2bb Christos Stavrakakis
65 ffcbf2bb Christos Stavrakakis
66 9fe1ecd8 Christos Stavrakakis
def get_vcs_info():
67 9fe1ecd8 Christos Stavrakakis
    """Return current git HEAD commit information.
68 9fe1ecd8 Christos Stavrakakis

69 9fe1ecd8 Christos Stavrakakis
    Returns a tuple containing
70 9fe1ecd8 Christos Stavrakakis
        - branch name
71 9fe1ecd8 Christos Stavrakakis
        - commit id
72 9fe1ecd8 Christos Stavrakakis
        - commit count
73 9fe1ecd8 Christos Stavrakakis
        - git describe output
74 9fe1ecd8 Christos Stavrakakis
        - path of git toplevel directory
75 9fe1ecd8 Christos Stavrakakis

76 9fe1ecd8 Christos Stavrakakis
    """
77 9fe1ecd8 Christos Stavrakakis
78 9fe1ecd8 Christos Stavrakakis
    repo = get_repository()
79 9fe1ecd8 Christos Stavrakakis
    branch = repo.head.reference
80 9fe1ecd8 Christos Stavrakakis
    revid = get_commit_id(branch.commit, branch)
81 9fe1ecd8 Christos Stavrakakis
    revno = len(list(repo.iter_commits()))
82 9fe1ecd8 Christos Stavrakakis
    toplevel = repo.working_dir
83 9fe1ecd8 Christos Stavrakakis
84 9fe1ecd8 Christos Stavrakakis
    info = namedtuple("vcs_info", ["branch", "revid", "revno",
85 9fe1ecd8 Christos Stavrakakis
                                   "toplevel"])
86 9fe1ecd8 Christos Stavrakakis
87 9fe1ecd8 Christos Stavrakakis
    return info(branch=branch.name, revid=revid, revno=revno,
88 9fe1ecd8 Christos Stavrakakis
                toplevel=toplevel)
89 9fe1ecd8 Christos Stavrakakis
90 9fe1ecd8 Christos Stavrakakis
91 9fe1ecd8 Christos Stavrakakis
def get_commit_id(commit, current_branch):
92 9fe1ecd8 Christos Stavrakakis
    """Return the commit ID
93 9fe1ecd8 Christos Stavrakakis

94 9fe1ecd8 Christos Stavrakakis
    If the commit is a 'merge' commit, and one of the parents is a
95 9fe1ecd8 Christos Stavrakakis
    debian branch we return a compination of the parents commits.
96 9fe1ecd8 Christos Stavrakakis

97 9fe1ecd8 Christos Stavrakakis
    """
98 9fe1ecd8 Christos Stavrakakis
    def short_id(commit):
99 9fe1ecd8 Christos Stavrakakis
        return commit.hexsha[0:7]
100 9fe1ecd8 Christos Stavrakakis
101 9fe1ecd8 Christos Stavrakakis
    parents = commit.parents
102 9fe1ecd8 Christos Stavrakakis
    cur_br_name = current_branch.name
103 9fe1ecd8 Christos Stavrakakis
    if len(parents) == 1:
104 9fe1ecd8 Christos Stavrakakis
        return short_id(commit)
105 9fe1ecd8 Christos Stavrakakis
    elif len(parents) == 2:
106 9fe1ecd8 Christos Stavrakakis
        if cur_br_name.startswith("debian-") or cur_br_name == "debian":
107 9fe1ecd8 Christos Stavrakakis
            pr1, pr2 = parents
108 9fe1ecd8 Christos Stavrakakis
            return short_id(pr1) + "_" + short_id(pr2)
109 9fe1ecd8 Christos Stavrakakis
        else:
110 9fe1ecd8 Christos Stavrakakis
            return short_id(commit)
111 9fe1ecd8 Christos Stavrakakis
    else:
112 9fe1ecd8 Christos Stavrakakis
        raise RuntimeError("Commit %s has more than 2 parents!" % commit)
113 d0c4fc17 Christos Stavrakakis
114 d0c4fc17 Christos Stavrakakis
115 d0c4fc17 Christos Stavrakakis
def get_debian_branch(branch):
116 d0c4fc17 Christos Stavrakakis
    """Find the corresponding debian- branch"""
117 b8f857f8 Christos Stavrakakis
    distribution = get_distribution_codename()
118 b8f857f8 Christos Stavrakakis
    repo = get_repository()
119 d0c4fc17 Christos Stavrakakis
    if branch == "master":
120 b8f857f8 Christos Stavrakakis
        deb_branch = "debian-" + distribution
121 b8f857f8 Christos Stavrakakis
    else:
122 b8f857f8 Christos Stavrakakis
        deb_branch = "-".join(["debian", branch, distribution])
123 6da63769 Christos Stavrakakis
    # Check if debian-branch exists (local or origin)
124 6da63769 Christos Stavrakakis
    if _get_branch(deb_branch):
125 d0c4fc17 Christos Stavrakakis
        return deb_branch
126 b8f857f8 Christos Stavrakakis
    # Check without distribution
127 18a2af6d Ilias Tsitsimpis
    deb_branch = re.sub("-" + distribution + "$", "", deb_branch)
128 b8f857f8 Christos Stavrakakis
    if _get_branch(deb_branch):
129 b8f857f8 Christos Stavrakakis
        return deb_branch
130 05e156a6 Christos Stavrakakis
    branch_type = BRANCH_TYPES[get_branch_type(branch)]
131 b8f857f8 Christos Stavrakakis
    # If not try the default debian branch with distribution
132 b8f857f8 Christos Stavrakakis
    default_branch = branch_type.debian_branch + "-" + distribution
133 b8f857f8 Christos Stavrakakis
    if _get_branch(default_branch):
134 b8f857f8 Christos Stavrakakis
        repo.git.branch(deb_branch, default_branch)
135 b8f857f8 Christos Stavrakakis
        print "Created branch '%s' from '%s'" % (deb_branch, default_branch)
136 b8f857f8 Christos Stavrakakis
        return deb_branch
137 b8f857f8 Christos Stavrakakis
    # And without distribution
138 6da63769 Christos Stavrakakis
    default_branch = branch_type.debian_branch
139 6da63769 Christos Stavrakakis
    if _get_branch(default_branch):
140 6da63769 Christos Stavrakakis
        repo.git.branch(deb_branch, default_branch)
141 6da63769 Christos Stavrakakis
        print "Created branch '%s' from '%s'" % (deb_branch, default_branch)
142 05e156a6 Christos Stavrakakis
        return deb_branch
143 6da63769 Christos Stavrakakis
    # If not try the debian branch
144 6da63769 Christos Stavrakakis
    repo.git.branch(deb_branch, default_branch)
145 6da63769 Christos Stavrakakis
    print "Created branch '%s' from 'debian'" % deb_branch
146 d0c4fc17 Christos Stavrakakis
    return "debian"
147 d0c4fc17 Christos Stavrakakis
148 d0c4fc17 Christos Stavrakakis
149 d0c4fc17 Christos Stavrakakis
def _get_branch(branch):
150 d0c4fc17 Christos Stavrakakis
    repo = get_repository()
151 d0c4fc17 Christos Stavrakakis
    if branch in repo.branches:
152 d0c4fc17 Christos Stavrakakis
        return branch
153 d0c4fc17 Christos Stavrakakis
    origin_branch = "origin/" + branch
154 d0c4fc17 Christos Stavrakakis
    if origin_branch in repo.refs:
155 1b3aeefd Christos Stavrakakis
        print "Creating branch '%s' to track '%s'" % (branch, origin_branch)
156 d0c4fc17 Christos Stavrakakis
        repo.git.branch(branch, origin_branch)
157 d0c4fc17 Christos Stavrakakis
        return branch
158 d0c4fc17 Christos Stavrakakis
    else:
159 d0c4fc17 Christos Stavrakakis
        return None
160 c181882a Christos Stavrakakis
161 c181882a Christos Stavrakakis
162 c181882a Christos Stavrakakis
def get_build_mode():
163 c181882a Christos Stavrakakis
    """Determine the build mode"""
164 c181882a Christos Stavrakakis
    # Get it from environment if exists
165 c181882a Christos Stavrakakis
    mode = os.environ.get("DEVFLOW_BUILD_MODE", None)
166 c181882a Christos Stavrakakis
    if mode is None:
167 4f36685f Christos Stavrakakis
        branch = get_branch_type(get_vcs_info().branch)
168 c181882a Christos Stavrakakis
        try:
169 4f36685f Christos Stavrakakis
            br_type = BRANCH_TYPES[get_branch_type(branch)]
170 c181882a Christos Stavrakakis
        except KeyError:
171 c181882a Christos Stavrakakis
            allowed_branches = ", ".join(x for x in BRANCH_TYPES.keys())
172 c181882a Christos Stavrakakis
            raise ValueError("Malformed branch name '%s', cannot classify as"
173 c181882a Christos Stavrakakis
                             " one of %s" % (branch, allowed_branches))
174 c181882a Christos Stavrakakis
        mode = "snapshot" if br_type.builds_snapshot else "release"
175 c181882a Christos Stavrakakis
    return mode
176 4f36685f Christos Stavrakakis
177 4f36685f Christos Stavrakakis
178 4f36685f Christos Stavrakakis
def normalize_branch_name(branch_name):
179 4f36685f Christos Stavrakakis
    """Normalize branch name by removing debian- if exists"""
180 4f36685f Christos Stavrakakis
    brnorm = branch_name
181 4f36685f Christos Stavrakakis
    if brnorm == "debian":
182 4f36685f Christos Stavrakakis
        brnorm = "debian-master"
183 4f36685f Christos Stavrakakis
    # If it's a debian branch, ignore starting "debian-"
184 4f36685f Christos Stavrakakis
    if brnorm.startswith("debian-"):
185 4f36685f Christos Stavrakakis
        brnorm = brnorm.replace("debian-", "", 1)
186 4f36685f Christos Stavrakakis
    return brnorm
187 4f36685f Christos Stavrakakis
188 4f36685f Christos Stavrakakis
189 4f36685f Christos Stavrakakis
def get_branch_type(branch_name):
190 4f36685f Christos Stavrakakis
    """Extract the type from a branch name"""
191 4f36685f Christos Stavrakakis
    branch_name = normalize_branch_name(branch_name)
192 4f36685f Christos Stavrakakis
    if "-" in branch_name:
193 4f36685f Christos Stavrakakis
        btypestr = branch_name.split("-")[0]
194 4f36685f Christos Stavrakakis
    else:
195 4f36685f Christos Stavrakakis
        btypestr = branch_name
196 4f36685f Christos Stavrakakis
    return btypestr
197 84a40792 Christos Stavrakakis
198 84a40792 Christos Stavrakakis
199 84a40792 Christos Stavrakakis
def version_to_tag(version):
200 84a40792 Christos Stavrakakis
    return version.replace("~", "")
201 b78d6238 Christos Stavrakakis
202 5c58523e Christos Stavrakakis
203 b78d6238 Christos Stavrakakis
def undebianize(branch):
204 b78d6238 Christos Stavrakakis
    if branch == "debian":
205 b78d6238 Christos Stavrakakis
        return "master"
206 b78d6238 Christos Stavrakakis
    elif branch.startswith("debian-"):
207 b78d6238 Christos Stavrakakis
        return branch.replace("debian-", "")
208 b78d6238 Christos Stavrakakis
    else:
209 b78d6238 Christos Stavrakakis
        return branch
210 42868817 Christos Stavrakakis
211 42868817 Christos Stavrakakis
212 42868817 Christos Stavrakakis
def get_distribution_codename():
213 42868817 Christos Stavrakakis
    output = sh.lsb_release("-c")
214 42868817 Christos Stavrakakis
    _, codename = output.split("\t")
215 42868817 Christos Stavrakakis
    codename = codename.strip()
216 42868817 Christos Stavrakakis
    return codename