Statistics
| Branch: | Tag: | Revision:

root / devflow / utils.py @ 6da63769

History | View | Annotate | Download (6 kB)

1
# Copyright (C) 2013 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
import os
35
import git
36
from collections import namedtuple
37
from configobj import ConfigObj
38

    
39
from devflow import BRANCH_TYPES
40

    
41

    
42
def get_repository(path=None):
43
    """Load the repository from the current working dir."""
44
    if path is None:
45
        path = os.getcwd()
46
    try:
47
        return git.Repo(path)
48
    except git.InvalidGitRepositoryError:
49
        msg = "Cound not retrivie git information. Directory '%s'"\
50
              " is not a git repository!" % path
51
        raise RuntimeError(msg)
52

    
53

    
54
def get_config(path=None):
55
    """Load configuration file."""
56
    if path is None:
57
        toplevel = get_vcs_info().toplevel
58
        path = os.path.join(toplevel, "devflow.conf")
59

    
60
    config = ConfigObj(path)
61
    return config
62

    
63

    
64
def get_vcs_info():
65
    """Return current git HEAD commit information.
66

67
    Returns a tuple containing
68
        - branch name
69
        - commit id
70
        - commit count
71
        - git describe output
72
        - path of git toplevel directory
73

74
    """
75

    
76
    repo = get_repository()
77
    branch = repo.head.reference
78
    revid = get_commit_id(branch.commit, branch)
79
    revno = len(list(repo.iter_commits()))
80
    toplevel = repo.working_dir
81

    
82
    info = namedtuple("vcs_info", ["branch", "revid", "revno",
83
                                   "toplevel"])
84

    
85
    return info(branch=branch.name, revid=revid, revno=revno,
86
                toplevel=toplevel)
87

    
88

    
89
def get_commit_id(commit, current_branch):
90
    """Return the commit ID
91

92
    If the commit is a 'merge' commit, and one of the parents is a
93
    debian branch we return a compination of the parents commits.
94

95
    """
96
    def short_id(commit):
97
        return commit.hexsha[0:7]
98

    
99
    parents = commit.parents
100
    cur_br_name = current_branch.name
101
    if len(parents) == 1:
102
        return short_id(commit)
103
    elif len(parents) == 2:
104
        if cur_br_name.startswith("debian-") or cur_br_name == "debian":
105
            pr1, pr2 = parents
106
            return short_id(pr1) + "_" + short_id(pr2)
107
        else:
108
            return short_id(commit)
109
    else:
110
        raise RuntimeError("Commit %s has more than 2 parents!" % commit)
111

    
112

    
113
def get_debian_branch(branch):
114
    """Find the corresponding debian- branch"""
115
    if branch == "master":
116
        return "debian"
117
    deb_branch = "debian-" + branch
118
    # Check if debian-branch exists (local or origin)
119
    if _get_branch(deb_branch):
120
        return deb_branch
121
    branch_type = BRANCH_TYPES[get_branch_type(branch)]
122
    # If not try the default debian branch
123
    default_branch = branch_type.debian_branch
124
    if _get_branch(default_branch):
125
        repo = get_repository()
126
        repo.git.branch(deb_branch, default_branch)
127
        print "Created branch '%s' from '%s'" % (deb_branch, default_branch)
128
        return deb_branch
129
    # If not try the debian branch
130
    repo.git.branch(deb_branch, default_branch)
131
    print "Created branch '%s' from 'debian'" % deb_branch
132
    return "debian"
133

    
134

    
135
def _get_branch(branch):
136
    repo = get_repository()
137
    if branch in repo.branches:
138
        return branch
139
    origin_branch = "origin/" + branch
140
    if origin_branch in repo.refs:
141
        print "Creating branch '%s' to track '%s'" % (branch, origin_branch)
142
        repo.git.branch(branch, origin_branch)
143
        return branch
144
    else:
145
        return None
146

    
147

    
148
def get_build_mode():
149
    """Determine the build mode"""
150
    # Get it from environment if exists
151
    mode = os.environ.get("DEVFLOW_BUILD_MODE", None)
152
    if mode is None:
153
        branch = get_branch_type(get_vcs_info().branch)
154
        try:
155
            br_type = BRANCH_TYPES[get_branch_type(branch)]
156
        except KeyError:
157
            allowed_branches = ", ".join(x for x in BRANCH_TYPES.keys())
158
            raise ValueError("Malformed branch name '%s', cannot classify as"
159
                             " one of %s" % (branch, allowed_branches))
160
        mode = "snapshot" if br_type.builds_snapshot else "release"
161
    return mode
162

    
163

    
164
def normalize_branch_name(branch_name):
165
    """Normalize branch name by removing debian- if exists"""
166
    brnorm = branch_name
167
    if brnorm == "debian":
168
        brnorm = "debian-master"
169
    # If it's a debian branch, ignore starting "debian-"
170
    if brnorm.startswith("debian-"):
171
        brnorm = brnorm.replace("debian-", "", 1)
172
    return brnorm
173

    
174

    
175
def get_branch_type(branch_name):
176
    """Extract the type from a branch name"""
177
    branch_name = normalize_branch_name(branch_name)
178
    if "-" in branch_name:
179
        btypestr = branch_name.split("-")[0]
180
    else:
181
        btypestr = branch_name
182
    return btypestr
183

    
184

    
185
def version_to_tag(version):
186
    return version.replace("~", "")