annotate contrib/genosxversion.py @ 33594:283a7da602ae stable

osx: new script for generating OS X package versions If you're shipping prerelease or rc packages using Munki, you'll eventually discover that Munki's version comparison logic is not as good as pip's. In theory we should be able to fix Munki, but it seems entirely reasonable to produce version strings that sort reasonably under these conditions. Since the requried logic not brief, add a new script and some tests of that logic. A followup change will wire this into the Makefile.
author Augie Fackler <augie@google.com>
date Mon, 24 Jul 2017 20:38:09 -0400
parents
children 25880ddf9a86
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
33594
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
1 #!/usr/bin/env python2
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
2 from __future__ import absolute_import, print_function
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
3
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
4 import argparse
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
5 import json
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
6 import os
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
7 import subprocess
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
8 import sys
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
9
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
10 # Always load hg libraries from the hg we can find on $PATH.
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
11 hglib = json.loads(subprocess.check_output(
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
12 ['hg', 'debuginstall', '-Tjson']))[0]['hgmodules']
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
13 sys.path.insert(0, os.path.dirname(hglib))
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
14
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
15 from mercurial import util
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
16
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
17 ap = argparse.ArgumentParser()
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
18 ap.add_argument('--paranoid',
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
19 action='store_true',
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
20 help=("Be paranoid about how version numbers compare and "
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
21 "produce something that's more likely to sort "
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
22 "reasonably."))
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
23 ap.add_argument('--selftest', action='store_true', help='Run self-tests.')
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
24 ap.add_argument('versionfile', help='Path to a valid mercurial __version__.py')
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
25
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
26 def paranoidver(ver):
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
27 """Given an hg version produce something that distutils can sort.
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
28
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
29 Some Mac package management systems use distutils code in order to
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
30 figure out upgrades, which makes life difficult. The test case is
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
31 a reduced version of code in the Munki tool used by some large
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
32 organizations to centrally manage OS X packages, which is what
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
33 inspired this kludge.
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
34
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
35 >>> paranoidver('3.4')
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
36 '3.4.0'
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
37 >>> paranoidver('3.4.2')
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
38 '3.4.2'
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
39 >>> paranoidver('3.0-rc+10')
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
40 '2.9.9999-rc+10'
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
41 >>> paranoidver('4.2+483-5d44d7d4076e')
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
42 '4.2.0+483-5d44d7d4076e'
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
43 >>> paranoidver('4.2.1+598-48d1e1214d8c')
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
44 '4.2.1+598-48d1e1214d8c'
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
45 >>> paranoidver('4.3-rc')
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
46 '4.2.9999-rc'
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
47 >>> paranoidver('4.3')
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
48 '4.3.0'
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
49 >>> from distutils import version
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
50 >>> class LossyPaddedVersion(version.LooseVersion):
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
51 ... '''Subclass version.LooseVersion to compare things like
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
52 ... "10.6" and "10.6.0" as equal'''
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
53 ... def __init__(self, s):
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
54 ... self.parse(s)
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
55 ...
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
56 ... def _pad(self, version_list, max_length):
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
57 ... 'Pad a version list by adding extra 0 components to the end'
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
58 ... # copy the version_list so we don't modify it
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
59 ... cmp_list = list(version_list)
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
60 ... while len(cmp_list) < max_length:
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
61 ... cmp_list.append(0)
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
62 ... return cmp_list
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
63 ...
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
64 ... def __cmp__(self, other):
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
65 ... if isinstance(other, str):
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
66 ... other = MunkiLooseVersion(other)
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
67 ... max_length = max(len(self.version), len(other.version))
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
68 ... self_cmp_version = self._pad(self.version, max_length)
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
69 ... other_cmp_version = self._pad(other.version, max_length)
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
70 ... return cmp(self_cmp_version, other_cmp_version)
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
71 >>> def testver(older, newer):
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
72 ... o = LossyPaddedVersion(paranoidver(older))
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
73 ... n = LossyPaddedVersion(paranoidver(newer))
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
74 ... return o < n
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
75 >>> testver('3.4', '3.5')
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
76 True
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
77 >>> testver('3.4.0', '3.5-rc')
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
78 True
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
79 >>> testver('3.4-rc', '3.5')
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
80 True
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
81 >>> testver('3.4-rc+10-deadbeef', '3.5')
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
82 True
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
83 >>> testver('3.4.2', '3.5-rc')
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
84 True
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
85 >>> testver('3.4.2', '3.5-rc+10-deadbeef')
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
86 True
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
87 >>> testver('4.2+483-5d44d7d4076e', '4.2.1+598-48d1e1214d8c')
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
88 True
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
89 >>> testver('4.3-rc', '4.3')
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
90 True
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
91 >>> testver('4.3', '4.3-rc')
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
92 False
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
93 """
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
94 major, minor, micro, extra = util.versiontuple(ver, n=4)
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
95 if micro is None:
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
96 micro = 0
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
97 if extra:
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
98 if extra.startswith('rc'):
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
99 if minor == 0:
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
100 major -= 1
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
101 minor = 9
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
102 else:
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
103 minor -= 1
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
104 micro = 9999
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
105 extra = '-' + extra
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
106 else:
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
107 extra = '+' + extra
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
108 else:
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
109 extra = ''
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
110 return '%d.%d.%d%s' % (major, minor, micro, extra)
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
111
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
112 def main(argv):
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
113 opts = ap.parse_args(argv[1:])
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
114 if opts.selftest:
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
115 import doctest
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
116 doctest.testmod()
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
117 return
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
118 with open(opts.versionfile) as f:
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
119 for l in f:
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
120 if l.startswith('version = '):
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
121 # version number is entire line minus the quotes
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
122 ver = l[len('version = ') + 1:-2]
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
123 break
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
124 if opts.paranoid:
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
125 print(paranoidver(ver))
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
126 else:
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
127 print(ver)
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
128
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
129 if __name__ == '__main__':
283a7da602ae osx: new script for generating OS X package versions
Augie Fackler <augie@google.com>
parents:
diff changeset
130 main(sys.argv)