Revision c9b113ac

b/COPYRIGHT
1
Copyright (C) 2010, 2011, 2012 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.
b/devtools/autopkg.sh
1 1
#!/bin/bash
2 2

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

  
3 36
parse_git_branch()
4 37
{
5 38
    git branch 2> /dev/null | grep '^*' | sed 's/^*\ //g'
......
98 131
mrgextra=-m
99 132
dchextra=-R
100 133
mrgmsg="Merge branch '$REMOTEUPSTREAM' into $REMOTEDEBIAN"
101
dialog --yesno "Create Snapshot?" 5 20 && snap=true && dchextra=-S && mrgextra= && mrgmsg=
134
dialog --yesno "Create Snapshot?" 5 20 && snap=true && GITFLOW_BUILD_MODE=snapshot && dchextra=-S && mrgextra= && mrgmsg=
102 135

  
103 136
# merge local branch into tmp branch with a nice commit message,
104 137
# so it can be pushed as is to upstream debian
......
107 140

  
108 141
# auto edit Debian changelog depending on Snapshot or Release mode
109 142
export EDITOR=/usr/bin/vim
110
git-dch --debian-branch=$TMPDEBIAN --git-author --ignore-regex=".*" --multimaint-merge --since=HEAD $dchextra
143

  
144
# use the devtools to determine Debian version
145
export GITFLOW_BUILD_MODE
146
version=$(devtools/version.py debian)
147
git-dch --debian-branch=$TMPDEBIAN --git-author --ignore-regex=".*" --multimaint-merge --since=HEAD -N $version
111 148
git add debian/changelog
112 149

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

  
38
"""Unit Tests for devtools.version
39

  
40
Provides unit tests for module devtools.version,
41
for automatic generation of version strings.
42

  
43
"""
44

  
45
import os
46
import unittest
47
from pkg_resources import parse_version
48
from version import debian_version_from_python_version
49

  
50

  
51
class DebianVersionObject(object):
52
    """Object representing a Debian Version."""
53
    def __init__(self, pyver):
54
        self.version = debian_version_from_python_version(pyver)
55

  
56
    def __str__(self):
57
        return self.version
58

  
59

  
60
def debian_compare_versions(a, op, b):
61
    i = os.system("dpkg --compare-versions %s %s %s" % (a, op, b))
62
    return i == 0
63

  
64
# Set ordering between DebianVersionObject objects, by adding
65
# debian_compare_versions
66
for op in ["lt", "le", "eq", "ne", "gt", "ge"]:
67
    def gen(op):
68
        def operator_func(self, other):
69
            return debian_compare_versions(self.version, op, other.version)
70
        return operator_func
71
    setattr(DebianVersionObject, "__%s__" % op, gen(op))
72

  
73

  
74
def _random_commit():
75
    import random
76
    import string
77
    return "".join(random.choice(string.hexdigits) for n in xrange(8)).lower()
78

  
79

  
80
# Add a random commit number at the end of snapshot versions
81
def version_with_commit(parse_func, v):
82
    if "_" in v:
83
        return parse_func(v + "_" + _random_commit())
84
    else:
85
        return parse_func(v)
86

  
87
V = lambda v: version_with_commit(parse_version, v)
88
D = lambda v: version_with_commit(DebianVersionObject, v)
89

  
90

  
91
class TestVersionFunctions(unittest.TestCase):
92
    def setUp(self):
93
        self.version_orderings = (
94
            ("0.14next", ">", "0.14"),
95
            ("0.14next", ">", "0.14rc7"),
96
            ("0.14next", "<", "0.14.1"),
97
            ("0.14rc6", "<", "0.14"),
98
            ("0.14.2rc6", ">", "0.14.1"),
99
            ("0.14next_150", "<", "0.14next"),
100
            ("0.14.1next_150", "<", "0.14.1next"),
101
            ("0.14.1_149", "<", "0.14.1"),
102
            ("0.14.1_149", "<", "0.14.1_150"),
103
            ("0.13next_102", "<", "0.13next"),
104
            ("0.13next", "<", "0.14rc5_120"),
105
            ("0.14rc3_120", "<", "0.14rc3"),
106
            # The following test fails, but version.python_version
107
            # will never try to produce such a version:
108
            # ("0.14rc3", "<", "0.14_1"),
109
            ("0.14_120", "<", "0.14"),
110
            ("0.14", "<", "0.14next_20"),
111
            ("0.14next_20", "<", "0.14next"),
112
        )
113

  
114
    def test_python_versions(self):
115
        for a, op, b in self.version_orderings:
116
            res = compare(V, a, op, b)
117
            self.assertTrue(res, "Python version: %s %s %s"
118
                                 " is not True" % (a, op, b))
119

  
120
    def test_debian_versions(self):
121
        for a, op, b in self.version_orderings:
122
            res = compare(D, a, op, b)
123
            self.assertTrue(res, "Debian version %s %s %s"
124
                                 " is not True" % (a, op, b))
125

  
126

  
127
def compare(function, a, op, b):
128
    import operator
129
    str_to_op = {"<": operator.lt,
130
            "<=": operator.le,
131
            "==": operator.eq,
132
            ">": operator.gt,
133
            ">=": operator.ge}
134
    try:
135
        return str_to_op[op](function(a), function(b))
136
    except KeyError:
137
        raise ValueError("Unknown operator '%s'" % op)
138

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

  
36

  
37
import os
38
import re
39
import sys
40
import pprint
41
import subprocess
42
from distutils import log
43
from collections import namedtuple
44

  
45

  
46
# Branch types:
47
# builds_snapshot: Whether the branch can produce snapshot builds
48
# builds_release: Whether the branch can produce release builds
49
# versioned: Whether the name of the branch defines a specific version
50
# allowed_version_re: A regular expression describing allowed values for
51
#                     base_version in this branch
52
branch_type = namedtuple("branch_type", ["builds_snapshot", "builds_release",
53
                                         "versioned", "allowed_version_re"])
54
VERSION_RE = "[0-9]+\.[0-9]+"
55
BRANCH_TYPES = {
56
    "feature": branch_type(True, False, False, "^%snext$" % VERSION_RE),
57
    "develop": branch_type(True, False, False, "^%snext$" % VERSION_RE),
58
    "release": branch_type(True, True, True,
59
                           "^(?P<bverstr>%s)rc[1-9][0-9]*$" % VERSION_RE),
60
    "master": branch_type(False, True, False,
61
                          "^%s$" % VERSION_RE),
62
    "hotfix": branch_type(True, True, True,
63
                          "^(?P<bverstr>^%s\.[1-9][0-9]*)$" % VERSION_RE)}
64
BASE_VERSION_FILE = "version"
65

  
66

  
67
def callgit(cmd):
68
    p = subprocess.Popen(["/bin/sh", "-c", cmd],
69
                          stdout=subprocess.PIPE,
70
                          stderr=subprocess.PIPE)
71
    output = p.communicate()[0].strip()
72
    if p.returncode != 0:
73
        log.error("Command '%s' failed with output:\n%s" % (cmd, output))
74
        raise subprocess.CalledProcessError(p.returncode, cmd, output)
75
    return output
76

  
77

  
78
def vcs_info():
79
    """
80
    Return current git HEAD commit information.
81

  
82
    Returns a tuple containing
83
        - branch name
84
        - commit id
85
        - commit count
86
        - git describe output
87
        - path of git toplevel directory
88

  
89
    """
90
    try:
91
        branch = callgit("git rev-parse --abbrev-ref HEAD")
92
        revid = callgit("git rev-parse --short HEAD")
93
        revno = int(callgit("git rev-list HEAD|wc -l"))
94
        desc = callgit("git describe --tags")
95
        toplevel = callgit("git rev-parse --show-toplevel")
96
    except subprocess.CalledProcessError:
97
        log.error("Could not retrieve git information. " +
98
                  "Current directory not a git repository?")
99
        raise
100

  
101
    info = namedtuple("vcs_info", ["branch", "revid", "revno",
102
                                   "desc", "toplevel"])
103

  
104
    return info(branch=branch, revid=revid, revno=revno, desc=desc,
105
                toplevel=toplevel)
106

  
107

  
108
def base_version(vcs_info):
109
    """Determine the base version from a file in the repository"""
110

  
111
    f = open(os.path.join(vcs_info.toplevel, BASE_VERSION_FILE))
112
    lines = [l.strip() for l in f.readlines()]
113
    l = [l for l in lines if not l.startswith("#")]
114
    if len(l) != 1:
115
        raise ValueError("File '%s' should contain a single non-comment line.")
116
    return l[0]
117

  
118

  
119
def build_mode():
120
    """Determine the build mode from the value of $GITFLOW_BUILD_MODE"""
121
    try:
122
        mode = os.environ["GITFLOW_BUILD_MODE"]
123
        assert mode == "release" or mode == "snapshot"
124
    except (KeyError, AssertionError):
125
        raise ValueError("GITFLOW_BUILD_MODE environment variable must be "
126
                         "'release' or 'snapshot'")
127
    return mode
128

  
129

  
130
def python_version(base_version, vcs_info, mode):
131
    """Generate a Python distribution version following devtools conventions.
132

  
133
    This helper generates a Python distribution version from a repository
134
    commit, following devtools conventions. The input data are:
135
        * base_version: a base version number, presumably stored in text file
136
          inside the repository, e.g., /version
137
        * vcs_info: vcs information: current branch name and revision no
138
        * mode: "snapshot", or "release"
139

  
140
    This helper assumes a git branching model following:
141
    http://nvie.com/posts/a-successful-git-branching-model/
142

  
143
    with 'master', 'develop', 'release-X', 'hotfix-X' and 'feature-X' branches.
144

  
145
    General rules:
146
    a) any repository commit can get as a Python version
147
    b) a version is generated either in 'release' or in 'snapshot' mode
148
    c) the choice of mode depends on the branch, see following table.
149

  
150
    A python version is of the form A_NNN,
151
    where A: X.Y.Z{,next,rcW} and NNN: a revision number for the commit,
152
    as returned by vcs_info().
153

  
154
    For every combination of branch and mode, releases are numbered as follows:
155

  
156
    BRANCH:  /  MODE: snapshot        release
157
    --------          ------------------------------
158
    feature           0.14next_150    N/A
159
    develop           0.14next_151    N/A
160
    release           0.14rc2_249     0.14rc2
161
    master            N/A             0.14
162
    hotfix            0.14.1rc6_121   0.14.1rc6
163
                      N/A             0.14.1
164

  
165
    The suffix 'next' in a version name is used to denote the upcoming version,
166
    the one being under development in the develop and release branches.
167
    Version '0.14next' is the version following 0.14, and only lives on the
168
    develop and feature branches.
169

  
170
    The suffix 'rc' is used to denote release candidates. 'rc' versions live
171
    only release and hotfix branches.
172

  
173
    Suffixes 'next' and 'rc' have been chosen to ensure proper ordering
174
    according to setuptools rules:
175

  
176
        http://www.python.org/dev/peps/pep-0386/#setuptools
177

  
178
    Every branch uses a value for A so that all releases are ordered based
179
    on the branch they came from, so:
180

  
181
    So
182
        0.13next < 0.14rcW < 0.14 < 0.14next < 0.14.1
183

  
184
    and
185

  
186
    >>> V("0.14next") > V("0.14")
187
    True
188
    >>> V("0.14next") > V("0.14rc7")
189
    True
190
    >>> V("0.14next") > V("0.14.1")
191
    False
192
    >>> V("0.14rc6") > V("0.14")
193
    False
194
    >>> V("0.14.2rc6") > V("0.14.1")
195
    True
196

  
197
    The value for _NNN is chosen based of the revision number of the specific
198
    commit. It is used to ensure ascending ordering of consecutive releases
199
    from the same branch. Every version of the form A_NNN comes *before*
200
    than A: All snapshots are ordered so they come before the corresponding
201
    release.
202

  
203
    So
204
        0.14next_* < 0.14
205
        0.14.1_* < 0.14.1
206
        etc
207

  
208
    and
209

  
210
    >>> V("0.14next_150") < V("0.14next")
211
    True
212
    >>> V("0.14.1next_150") < V("0.14.1next")
213
    True
214
    >>> V("0.14.1_149") < V("0.14.1")
215
    True
216
    >>> V("0.14.1_149") < V("0.14.1_150")
217
    True
218

  
219
    Combining both of the above, we get
220
       0.13next_* < 0.13next < 0.14rcW_* < 0.14rcW < 0.14_* < 0.14
221
       < 0.14next_* < 0.14next < 0.14.1_* < 0.14.1
222

  
223
    and
224

  
225
    >>> V("0.13next_102") < V("0.13next")
226
    True
227
    >>> V("0.13next") < V("0.14rc5_120")
228
    True
229
    >>> V("0.14rc3_120") < V("0.14rc3")
230
    True
231
    >>> V("0.14rc3") < V("0.14_1")
232
    True
233
    >>> V("0.14_120") < V("0.14")
234
    True
235
    >>> V("0.14") < V("0.14next_20")
236
    True
237
    >>> V("0.14next_20") < V("0.14next")
238
    True
239

  
240
    Note: one of the tests above fails because of constraints in the way
241
    setuptools parses version numbers. It does not affect us because the
242
    specific version format that triggers the problem is not contained in the
243
    table showing allowed branch / mode combinations, above.
244

  
245

  
246
    """
247

  
248
    branch = vcs_info.branch
249

  
250
    # If it's a debian branch, ignore starting "debian-"
251
    brnorm = branch
252
    if brnorm == "debian":
253
        brnorm = "debian-master"
254
    if brnorm.startswith("debian-"):
255
        brnorm = brnorm.split("debian-")[1]
256

  
257
    # Sanity checks
258
    if "-" in brnorm:
259
        btypestr = brnorm.split("-")[0]
260
        bverstr = brnorm.split("-")[1]
261
        if bverstr == "":
262
            raise ValueError("Malformed branch name '%s'" % branch)
263
        versioned = True
264
    else:
265
        btypestr = branch
266
        versioned = False
267
    try:
268
        btype = BRANCH_TYPES[btypestr]
269
    except KeyError:
270
        allowed_branches = ", ".join(x for x in BRANCH_TYPES.keys())
271
        raise ValueError("Malformed branch name '%s', cannot classify as one "
272
                         "of %s" % (btypestr, allowed_branches))
273

  
274
    if versioned != btype.versioned:
275
        raise ValueError(("Branch name '%s' should %s contain version" %
276
                          (branch, "not" if versioned else "")))
277
    if btype.versioned and not re.match(VERSION_RE, bverstr):
278
        raise ValueError(("Malformed version '%s' in branch name '%s'" %
279
                          (bverstr, branch)))
280

  
281
    m = re.match(btype.allowed_version_re, base_version)
282
    if not m or (btype.versioned and m.groupdict()["bverstr"] != bverstr):
283
        raise ValueError(("Base version '%s' unsuitable for branch name '%s'" %
284
                         (base_version, branch)))
285

  
286
    if mode not in ["snapshot", "release"]:
287
        raise ValueError(("Specified mode '%s' should be one of 'snapshot' or "
288
                          "'release'" % mode))
289
    snap = (mode == "snapshot")
290

  
291
    if ((snap and not btype.builds_snapshot) or
292
        (not snap and not btype.builds_release)):
293
        raise ValueError(("Invalid mode '%s' in branch type '%s'" %
294
                          (mode, btypestr)))
295

  
296
    if snap:
297
        v = "%s_%d_%s" % (base_version, vcs_info.revno, vcs_info.revid)
298
    else:
299
        v = base_version
300
    return v
301

  
302

  
303
def debian_version_from_python_version(pyver):
304
    """Generate a debian package version from a Python version.
305

  
306
    This helper generates a Debian package version from a Python version,
307
    following devtools conventions.
308

  
309
    Debian sorts version strings differently compared to setuptools:
310
    http://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version
311

  
312
    Initial tests:
313

  
314
    >>> debian_version("3") < debian_version("6")
315
    True
316
    >>> debian_version("3") < debian_version("2")
317
    False
318
    >>> debian_version("1") == debian_version("1")
319
    True
320
    >>> debian_version("1") != debian_version("1")
321
    False
322
    >>> debian_version("1") >= debian_version("1")
323
    True
324
    >>> debian_version("1") <= debian_version("1")
325
    True
326

  
327
    This helper defines a 1-1 mapping between Python and Debian versions,
328
    with the same ordering.
329

  
330
    Debian versions are ordered in the same way as Python versions:
331

  
332
    >>> D("0.14next") > D("0.14")
333
    True
334
    >>> D("0.14next") > D("0.14rc7")
335
    True
336
    >>> D("0.14next") > D("0.14.1")
337
    False
338
    >>> D("0.14rc6") > D("0.14")
339
    False
340
    >>> D("0.14.2rc6") > D("0.14.1")
341
    True
342

  
343
    and
344

  
345
    >>> D("0.14next_150") < D("0.14next")
346
    True
347
    >>> D("0.14.1next_150") < D("0.14.1next")
348
    True
349
    >>> D("0.14.1_149") < D("0.14.1")
350
    True
351
    >>> D("0.14.1_149") < D("0.14.1_150")
352
    True
353

  
354
    and
355

  
356
    >>> D("0.13next_102") < D("0.13next")
357
    True
358
    >>> D("0.13next") < D("0.14rc5_120")
359
    True
360
    >>> D("0.14rc3_120") < D("0.14rc3")
361
    True
362
    >>> D("0.14rc3") < D("0.14_1")
363
    True
364
    >>> D("0.14_120") < D("0.14")
365
    True
366
    >>> D("0.14") < D("0.14next_20")
367
    True
368
    >>> D("0.14next_20") < D("0.14next")
369
    True
370

  
371
    """
372
    return pyver.replace("_", "~").replace("rc", "~rc")
373

  
374

  
375
def debian_version(base_version, vcs_info, mode):
376
    p = python_version(base_version, vcs_info, mode)
377
    return debian_version_from_python_version(p)
378

  
379

  
380
def update_version(module, name="version", root="."):
381
    """
382
    Generate or replace version.py as a submodule of `module`.
383

  
384
    This is a helper to generate/replace a version.py file containing version
385
    information as a submodule of passed `module`.
386

  
387
    """
388

  
389
    # FIXME: exit or fail if not in development environment?
390
    v = vcs_info()
391
    b = base_version(v)
392
    mode = build_mode()
393
    paths = [root] + module.split(".") + ["%s.py" % name]
394
    module_filename = os.path.join(*paths)
395
    content = """
396
__version__ = "%(version)s"
397
__version_info__ = __version__.split(".")
398
__version_vcs_info__ = %(vcs_info)s
399
    """ % dict(version=python_version(b, v, mode),
400
            vcs_info=pprint.PrettyPrinter().pformat(dict(v._asdict())))
401

  
402
    module_file = file(module_filename, "w+")
403
    module_file.write(content)
404
    module_file.close()
405

  
406

  
407
if __name__ == "__main__":
408
    v = vcs_info()
409
    b = base_version(v)
410
    mode = build_mode()
411

  
412
    try:
413
        arg = sys.argv[1]
414
        assert arg == "python" or arg == "debian"
415
    except IndexError:
416
        raise ValueError("A single argument, 'python' or 'debian is required")
417

  
418
    if arg == "python":
419
        print python_version(b, v, mode)
420
    elif arg == "debian":
421
        print debian_version(b, v, mode)
b/snf-astakos-app/setup.py
47 47

  
48 48
HERE = os.path.abspath(os.path.normpath(os.path.dirname(__file__)))
49 49
try:
50
    # try to update the version file
51
    from synnefo.util import version
52
    version.update_version('astakos', 'version', HERE)
50
    # use devtools to update the version file
51
    from devtools.version import update_version
52
    update_version('astakos', 'common', HERE)
53 53
except ImportError:
54
    pass
54
    raise RuntimeError("devtools is a build dependency")
55 55

  
56 56
from astakos.version import __version__
57 57

  
b/snf-common/setup.py
44 44
HERE = os.path.abspath(os.path.normpath(os.path.dirname(__file__)))
45 45

  
46 46
try:
47
    # try to update the version file
48
    from synnefo.util.version import update_version
47
    # use devtools to update the version file
48
    from devtools.version import update_version
49 49
    update_version('synnefo.versions', 'common', HERE)
50 50
except ImportError:
51
    pass
51
    raise RuntimeError("devtools is a build dependency")
52 52

  
53 53
from synnefo.versions.common import __version__
54 54

  
b/snf-cyclades-app/setup.py
44 44
HERE = os.path.abspath(os.path.normpath(os.path.dirname(__file__)))
45 45

  
46 46
try:
47
    # try to update the version file
48
    from synnefo.util.version import update_version
47
    # use devtools to update the version file
48
    from devtools.version import update_version
49 49
    update_version('synnefo.versions', 'app', HERE)
50 50
except ImportError:
51
    pass
51
    raise RuntimeError("devtools is a build dependency")
52 52

  
53 53
from synnefo.versions.app import __version__
54 54

  
b/snf-cyclades-gtools/setup.py
40 40
HERE = os.path.abspath(os.path.normpath(os.path.dirname(__file__)))
41 41

  
42 42
try:
43
    # try to update the version file
44
    from synnefo.util.version import update_version
43
    # use devtools to update the version file
44
    from devtools.version import update_version
45 45
    update_version('synnefo.versions', 'ganeti', HERE)
46 46
except ImportError:
47
    pass
47
    raise RuntimeError("devtools is a build dependency")
48 48

  
49 49
from synnefo.versions.ganeti import __version__
50 50

  
b/snf-pithos-app/setup.py
42 42
from setuptools import setup, find_packages
43 43

  
44 44
HERE = os.path.abspath(os.path.normpath(os.path.dirname(__file__)))
45

  
45 46
try:
46
    # try to update the version file
47
    from synnefo.util import version
48
    version.update_version('pithos.api', 'version', HERE)
47
    # use devtools to update the version file
48
    from devtools.version import update_version
49
    update_version('pithos.api', 'version', HERE)
49 50
except ImportError:
50
    pass
51
    raise RuntimeError("devtools is a build dependency")
51 52

  
52 53
from pithos.api.version import __version__
53 54

  
b/snf-pithos-backend/setup.py
42 42
from setuptools import setup, find_packages
43 43

  
44 44
HERE = os.path.abspath(os.path.normpath(os.path.dirname(__file__)))
45

  
45 46
try:
46
    # try to update the version file
47
    from synnefo.util import version
48
    version.update_version('pithos.backends', 'version', HERE)
47
    # use devtools to update the version file
48
    from devtools.version import update_version
49
    update_version('pithos.backends', 'version', HERE)
49 50
except ImportError:
50
    pass
51
    raise RuntimeError("devtools is a build dependency")
51 52

  
52 53
from pithos.backends.version import __version__
53 54

  
b/snf-pithos-tools/setup.py
44 44
from setuptools import setup, find_packages
45 45

  
46 46
HERE = os.path.abspath(os.path.normpath(os.path.dirname(__file__)))
47

  
47 48
try:
48
    # try to update the version file
49
    from synnefo.util import version
50
    version.update_version('pithos.tools', 'version', HERE)
49
    # use devtools to update the version file
50
    from devtools.version import update_version
51
    update_version('pithos.tools', 'version', HERE)
51 52
except ImportError:
52
    pass
53
    raise RuntimeError("devtools is a build dependency")
53 54

  
54 55
from pithos.tools.version import __version__
55 56

  
b/snf-tools/setup.py
44 44
HERE = os.path.abspath(os.path.normpath(os.path.dirname(__file__)))
45 45

  
46 46
try:
47
    # try to update the version file
48
    from synnefo.util.version import update_version
47
    # use devtools to update the version file
48
    from devtools.version import update_version
49 49
    update_version('synnefo_tools', 'version', HERE)
50 50
except ImportError:
51
    pass
51
    raise RuntimeError("devtools is a build dependency")
52 52

  
53 53
from synnefo_tools.version import __version__
54 54

  
b/snf-webproject/setup.py
44 44
HERE = os.path.abspath(os.path.normpath(os.path.dirname(__file__)))
45 45

  
46 46
try:
47
    # try to update the version file
48
    from synnefo.util.version import update_version
47
    # use devtools to update the version file
48
    from devtools.version import update_version
49 49
    update_version('synnefo.versions', 'webproject', HERE)
50 50
except ImportError:
51
    pass
51
    raise RuntimeError("devtools is a build dependency")
52 52

  
53 53
from synnefo.versions.webproject import __version__
54 54

  
b/version
1
# This is a comment!
2
0.14next

Also available in: Unified diff