1#
2#  This program is free software; you can redistribute it and/or modify
3#  it under the terms of the GNU General Public License version 2
4#  as published by the Free Software Foundation.
5#
6#  This program is distributed in the hope that it will be useful,
7#  but WITHOUT ANY WARRANTY; without even the implied warranty of
8#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9#  GNU General Public License for more details.
10#
11#  You should have received a copy of the GNU General Public License
12#  along with this program; if not, write to the Free Software
13#  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
14#
15
16#
17# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
18# Use is subject to license terms.
19#
20
21'''
22Deal with Mercurial versioning.
23
24At a basic level, code to verify that the version of Mercurial in use
25is suitable for use with Cadmium, and compare that version for the
26sake of adapting to Mercurial API changes.
27'''
28
29#
30# It is important that this module rely on as little of Mercurial as
31# is possible.
32#
33
34#
35# Mercurial >= 1.2 has util.version(), prior versions
36# version.get_version() We discover which to use this way, rather than
37# via ImportError to account for mercurial.demandimport delaying the
38# ImportError exception.
39#
40from mercurial import util
41if hasattr(util, 'version'):
42    hg_version = util.version
43else:
44    from mercurial import version
45    hg_version = version.get_version
46
47
48class VersionMismatch(Exception):
49    "Exception used to indicate a mismatch between SCM tools and Mercurial"
50    pass
51
52#
53# List of versions that are explicitly acceptable to us
54#
55GOOD_VERSIONS = ['1.1.2', '1.3.1']
56
57
58def check_version():
59    '''Check that we're running on a suitable version of Mercurial'''
60
61    def versionstring(versions):
62        '''return the list, versions, as a vaguely grammatical string'''
63        if len(versions) > 1:
64            return "%s or %s" % (', '.join(versions[0:-1]), versions[-1])
65        else:
66            return versions[0]
67
68    if hg_version() not in GOOD_VERSIONS:
69        raise VersionMismatch("Scm expects Mercurial version %s, "
70                              "actual version is %s." %
71                              (versionstring(GOOD_VERSIONS),
72                               hg_version()))
73
74
75def _split_version(ver):
76    '''Return the Mercurial version as a list [MAJOR, MINOR, MICRO],
77    if this is not a released Mercurial return None.'''
78
79    try:
80        l = map(int, ver.split('.'))
81        # If there's only one element, it's not really a tagged version
82        if len(l) <= 1:
83            return None
84        else:
85            return l
86    except ValueError:
87        return None
88
89
90def at_least(desired):
91    '''Return boolean indicating if the running version is greater
92    than or equal to, the version specified by major, minor, micro'''
93
94    hgver = _split_version(hg_version())
95    desired = map(int, desired.split('.'))
96
97    #
98    # If _split_version() returns None, we're running on a Mercurial that
99    # has not been tagged as a release.  We assume this to be newer
100    # than any released version.
101    #
102    if hgver == None:
103        return True
104
105    # Pad our versions to the same overall length, appending 0's
106    while len(hgver) < len(desired):
107        hgver.append(0)
108    while len(desired) < len(hgver):
109        desired.append(0)
110
111    for real, req in zip(hgver, desired):
112        if real != req:
113            return real > req
114
115    return True
116