Statistics
| Branch: | Tag: | Revision:

root / devflow / utils.py @ 06edfd12

History | View | Annotate | Download (7.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 382414fe 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 6b88d711 Christos Stavrakakis
    config = repo.config_reader()
84 88d15d7e Christos Stavrakakis
    try:
85 88d15d7e Christos Stavrakakis
        name = config.get_value("user", "name")
86 88d15d7e Christos Stavrakakis
        email = config.get_value("user", "email")
87 88d15d7e Christos Stavrakakis
    except Exception as e:
88 88d15d7e Christos Stavrakakis
        raise ValueError("Can not read name/email from .gitconfig"
89 88d15d7e Christos Stavrakakis
                         " file.: %s" % e)
90 9fe1ecd8 Christos Stavrakakis
91 9fe1ecd8 Christos Stavrakakis
    info = namedtuple("vcs_info", ["branch", "revid", "revno",
92 6b88d711 Christos Stavrakakis
                                   "toplevel", "name", "email"])
93 9fe1ecd8 Christos Stavrakakis
94 9fe1ecd8 Christos Stavrakakis
    return info(branch=branch.name, revid=revid, revno=revno,
95 6b88d711 Christos Stavrakakis
                toplevel=toplevel, name=name, email=email)
96 9fe1ecd8 Christos Stavrakakis
97 9fe1ecd8 Christos Stavrakakis
98 9fe1ecd8 Christos Stavrakakis
def get_commit_id(commit, current_branch):
99 9fe1ecd8 Christos Stavrakakis
    """Return the commit ID
100 9fe1ecd8 Christos Stavrakakis

101 9fe1ecd8 Christos Stavrakakis
    If the commit is a 'merge' commit, and one of the parents is a
102 9fe1ecd8 Christos Stavrakakis
    debian branch we return a compination of the parents commits.
103 9fe1ecd8 Christos Stavrakakis

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