22
22
current Git commit.
23
23
"""
24
24
25
+
25
26
# XXX NOTE XXX NOTE XXX NOTE XXX
26
27
# After modifying this script it is advisable to execute the self-test.
27
28
#
34
35
# of each command is desired, then add the -x option to the bash invocation.
35
36
# XXX NOTE XXX NOTE XXX NOTE XXX
36
37
38
+ from __future__ import annotations
39
+
37
40
import datetime
38
41
import re
39
42
import subprocess
40
43
import sys
44
+ import argparse
41
45
42
46
try :
43
47
# Prefer newer `packaging` over deprecated packages.
46
50
except ImportError :
47
51
# Fallback to deprecated pkg_resources.
48
52
try :
49
- from pkg_resources .extern .packaging .version import Version
53
+ from pkg_resources .extern .packaging .version import Version # type: ignore
50
54
from pkg_resources import parse_version
51
55
except ImportError :
52
56
# Fallback to deprecated distutils.
53
57
from distutils .version import LooseVersion as Version
54
58
from distutils .version import LooseVersion as parse_version
55
59
56
- DEBUG = len (sys .argv ) > 1 and '-d' in sys .argv
57
- if DEBUG :
58
- print ('Debugging output enabled.' )
60
+ parser = argparse .ArgumentParser ()
61
+ parser .add_argument ("--debug" , "-d" , action = "store_true" , help = "Enable debug output" )
62
+ parser .add_argument ("--previous" , "-p" , action = "store_true" , help = "Calculate the previous version, not the current" )
63
+ parser .add_argument ("--next-minor" , action = "store_true" , help = "Calculate the next minor release instead of the current" )
64
+ args = parser .parse_args ()
65
+
66
+ _DEBUG : bool = args .debug
67
+
68
+
69
+ def debug (msg : str ) -> None :
70
+ if _DEBUG :
71
+ print (msg , file = sys .stderr , flush = True )
72
+
73
+
74
+ debug ("Debugging output enabled." )
75
+
76
+ # fmt: off
59
77
60
78
# This option indicates we are to determine the previous release version
61
- PREVIOUS = len ( sys . argv ) > 1 and '-p' in sys . argv
79
+ PREVIOUS : bool = args . previous
62
80
# This options indicates to output the next minor release version
63
- NEXT_MINOR = len ( sys . argv ) > 1 and '--next-minor' in sys . argv
81
+ NEXT_MINOR : bool = args . next_minor
64
82
65
83
PREVIOUS_TAG_RE = re .compile ('(?P<ver>(?P<vermaj>[0-9]+)\\ .(?P<vermin>[0-9]+)'
66
84
'\\ .(?P<verpatch>[0-9]+)(?:-(?P<verpre>.*))?)' )
69
87
RELEASE_BRANCH_RE = re .compile ('(?:(?:refs/remotes/)?origin/)?(?P<brname>r'
70
88
'(?P<vermaj>[0-9]+)\\ .(?P<vermin>[0-9]+))' )
71
89
72
- def check_output (args ) :
90
+ def check_output (args : list [ str ]) -> str :
73
91
"""
74
92
Delegates to subprocess.check_output() if it is available, otherwise
75
93
provides a reasonable facsimile.
76
94
"""
95
+ debug (f'Run command: { args } ' )
77
96
if 'check_output' in dir (subprocess ):
78
97
out = subprocess .check_output (args )
79
98
else :
80
99
proc = subprocess .Popen (args , stdout = subprocess .PIPE )
81
100
out , err = proc .communicate ()
82
101
ret = proc .poll ()
83
102
if ret :
84
- raise subprocess .CalledProcessError (ret , args [0 ], output = out )
103
+ raise subprocess .CalledProcessError (ret , args [0 ], output = out , stderr = err )
85
104
86
- if type (out ) is bytes :
87
- # git isn't guaranteed to always return UTF-8, but for our purposes
88
- # this should be fine as tags and hashes should be ASCII only.
89
- out = out .decode ('utf-8' )
105
+ # git isn't guaranteed to always return UTF-8, but for our purposes
106
+ # this should be fine as tags and hashes should be ASCII only.
107
+ out = out .decode ('utf-8' )
90
108
91
109
return out
92
110
93
111
94
- def check_head_tag ():
112
+ def check_head_tag () -> str | None :
95
113
"""
96
114
Checks the current HEAD to see if it has been tagged with a tag that matches
97
115
the pattern for a release tag. Returns release version calculated from the
@@ -115,21 +133,19 @@ def check_head_tag():
115
133
if release_tag_match :
116
134
new_version_str = release_tag_match .group ('ver' )
117
135
new_version_parsed = parse_version (new_version_str )
118
- if new_version_parsed > version_parsed :
119
- if DEBUG :
120
- print ('HEAD release tag: ' + new_version_str )
136
+ if new_version_parsed > version_parsed : # type: ignore
137
+ debug ('HEAD release tag: ' + new_version_str )
121
138
version_str = new_version_str
122
139
version_parsed = new_version_parsed
123
140
found_tag = True
124
141
125
142
if found_tag :
126
- if DEBUG :
127
- print ('Calculated version: ' + version_str )
143
+ debug ('Calculated version: ' + version_str )
128
144
return version_str
129
145
130
146
return None
131
147
132
- def get_next_minor (prerelease_marker ):
148
+ def get_next_minor (prerelease_marker : str ):
133
149
"""
134
150
get_next_minor does the following:
135
151
- Inspect the branches that fit the convention for a release branch.
@@ -157,16 +173,15 @@ def get_next_minor(prerelease_marker):
157
173
str (version_new ['patch' ]) + '-' + \
158
174
version_new ['prerelease' ]
159
175
new_version_parsed = parse_version (new_version_str )
160
- if new_version_parsed > version_parsed :
176
+ if new_version_parsed > version_parsed : # type: ignore
161
177
version_str = new_version_str
162
178
version_parsed = new_version_parsed
163
- if DEBUG :
164
- print ('Found new best version "' + version_str \
179
+ debug ('Found new best version "' + version_str \
165
180
+ '" based on branch "' \
166
181
+ release_branch_match .group ('brname' ) + '"' )
167
182
return version_str
168
183
169
- def get_branch_tags (active_branch_name ):
184
+ def get_branch_tags (active_branch_name : str ):
170
185
"""
171
186
Returns the tag or tags (as a single string with newlines between tags)
172
187
corresponding to the current branch, which must not be master. If the
@@ -199,7 +214,7 @@ def get_branch_tags(active_branch_name):
199
214
200
215
return tags
201
216
202
- def process_and_sort_tags (tags ):
217
+ def process_and_sort_tags (tags : str ):
203
218
"""
204
219
Given a string (as returned from get_branch_tags), return a sorted list of
205
220
zero or more tags (sorted based on the Version comparison) which meet
@@ -209,7 +224,7 @@ def process_and_sort_tags(tags):
209
224
1.x.y-preX iff 1.x.y does not already exist)
210
225
"""
211
226
212
- processed_and_sorted_tags = []
227
+ processed_and_sorted_tags : list [ str ] = []
213
228
if not tags or len (tags ) == 0 :
214
229
return processed_and_sorted_tags
215
230
@@ -225,7 +240,7 @@ def process_and_sort_tags(tags):
225
240
tag_parts = tag .split ('-' )
226
241
if len (tag_parts ) >= 2 and tag_parts [0 ] not in processed_and_sorted_tags :
227
242
processed_and_sorted_tags .append (tag )
228
- processed_and_sorted_tags .sort (key = Version )
243
+ processed_and_sorted_tags .sort (key = Version ) # type: ignore
229
244
230
245
return processed_and_sorted_tags
231
246
@@ -254,8 +269,7 @@ def main():
254
269
+ '+git' + head_commit_short
255
270
256
271
if NEXT_MINOR :
257
- if DEBUG :
258
- print ('Calculating next minor release' )
272
+ debug ('Calculating next minor release' )
259
273
return get_next_minor (prerelease_marker )
260
274
261
275
head_tag_ver = check_head_tag ()
@@ -264,8 +278,7 @@ def main():
264
278
265
279
active_branch_name = check_output (['git' , 'rev-parse' ,
266
280
'--abbrev-ref' , 'HEAD' ]).strip ()
267
- if DEBUG :
268
- print ('Calculating release version for branch: ' + active_branch_name )
281
+ debug ('Calculating release version for branch: ' + active_branch_name )
269
282
if active_branch_name == 'master' :
270
283
return get_next_minor (prerelease_marker )
271
284
@@ -287,22 +300,20 @@ def main():
287
300
str (version_new ['patch' ]) + '-' + \
288
301
version_new ['prerelease' ]
289
302
new_version_parsed = parse_version (new_version_str )
290
- if new_version_parsed > version_parsed :
303
+ if new_version_parsed > version_parsed : # type: ignore
291
304
version_str = new_version_str
292
305
version_parsed = new_version_parsed
293
- if DEBUG :
294
- print ('Found new best version "' + version_str \
306
+ debug ('Found new best version "' + version_str \
295
307
+ '" from tag "' + release_tag_match .group ('ver' ) + '"' )
296
308
297
309
return version_str
298
310
299
- def previous (rel_ver ):
311
+ def previous (rel_ver : str ):
300
312
"""
301
313
Given a release version, find the previous version based on the latest Git
302
314
tag that is strictly a lower version than the given release version.
303
315
"""
304
- if DEBUG :
305
- print ('Calculating previous release version (option -p was specified).' )
316
+ debug ('Calculating previous release version (option -p was specified).' )
306
317
version_str = '0.0.0'
307
318
version_parsed = parse_version (version_str )
308
319
rel_ver_str = rel_ver
@@ -323,17 +334,15 @@ def previous(rel_ver):
323
334
if version_new ['prerelease' ] is not None :
324
335
new_version_str += '-' + version_new ['prerelease' ]
325
336
new_version_parsed = parse_version (new_version_str )
326
- if new_version_parsed < rel_ver_parsed and new_version_parsed > version_parsed :
337
+ if new_version_parsed < rel_ver_parsed and new_version_parsed > version_parsed : # type: ignore
327
338
version_str = new_version_str
328
339
version_parsed = new_version_parsed
329
- if DEBUG :
330
- print ('Found new best version "' + version_str \
340
+ debug ('Found new best version "' + version_str \
331
341
+ '" from tag "' + tag + '"' )
332
342
333
343
return version_str
334
344
335
345
RELEASE_VER = previous (main ()) if PREVIOUS else main ()
336
346
337
- if DEBUG :
338
- print ('Final calculated release version:' )
347
+ debug ('Final calculated release version:' )
339
348
print (RELEASE_VER )
0 commit comments