1 |
#!/home/jsoc/bin/linux_x86_64/activepython |
2 |
|
3 |
# Run like this: |
4 |
# CM/tagRelease.py -t /home/jsoc/cvs/Development/waystation/JSOC_9.4.1_beta -v 9.41 |
5 |
# |
6 |
# -t is a HEAD check-out of the CVS tree; the file jsoc_version.h will be edited, and the tree will then be tagged with the release version specified in the `-v` argument |
7 |
# -v is a version string with a single '.' |
8 |
import sys, getopt |
9 |
import re |
10 |
import os |
11 |
import shutil |
12 |
from subprocess import call |
13 |
|
14 |
# Return values |
15 |
kRetSuccess = 0 |
16 |
kRetArgs = 1 |
17 |
kRetOS = 2 |
18 |
kRetRegexp = 3 |
19 |
|
20 |
# Constants |
21 |
kTagCmd = '/home/jsoc/dlsource.pl -o tag' |
22 |
kUntagCmd = '/home/jsoc/dlsource.pl -o untag' |
23 |
kTmpFile = '/tmp/.versfile.tmp' |
24 |
kVersFile = 'base/jsoc_version.h' |
25 |
|
26 |
# Classes |
27 |
|
28 |
# This class changes the current working directory, and restores the original working directory when |
29 |
# the context is left. |
30 |
class Chdir: |
31 |
"""Context manager for changing the current working directory""" |
32 |
def __init__(self, newPath): |
33 |
self.newPath = os.path.realpath(newPath) |
34 |
|
35 |
def __enter__(self): |
36 |
self.savedPath = os.path.realpath(os.getcwd()) |
37 |
os.chdir(self.newPath) |
38 |
cdir = os.path.realpath(os.getcwd()) |
39 |
if cdir == self.newPath: |
40 |
return 0 |
41 |
else: |
42 |
return 1 |
43 |
|
44 |
def __exit__(self, etype, value, traceback): |
45 |
os.chdir(self.savedPath) |
46 |
cdir = os.path.realpath(os.getcwd()) |
47 |
if cdir == self.savedPath: |
48 |
return 0 |
49 |
else: |
50 |
return 1 |
51 |
|
52 |
# Read arguments |
53 |
def GetArgs(args): |
54 |
rv = kRetSuccess |
55 |
optD = {} |
56 |
|
57 |
# tag by defuault |
58 |
optD['untag'] = 0 |
59 |
|
60 |
try: |
61 |
opts, remainder = getopt.getopt(args,"ht:uv:",["tree=", "version="]) |
62 |
except getopt.GetoptError: |
63 |
print('Usage:') |
64 |
print('tagRelease.py [-hu] -t <CVS tree with jsoc_version.h> -v <version string>') |
65 |
rv = kRetArgs |
66 |
|
67 |
if rv == kRetSuccess: |
68 |
for opt, arg in opts: |
69 |
if opt == '-h': |
70 |
print('tagRelease.py [-hu] -t <CVS tree with jsoc_version.h> -v <version string>') |
71 |
exit(0) |
72 |
elif opt in ("-t", "--tree"): |
73 |
regexp = re.compile(r"(\S+)/?") |
74 |
matchobj = regexp.match(arg) |
75 |
if matchobj is None: |
76 |
rv = kRetArgs |
77 |
else: |
78 |
optD['tree'] = matchobj.group(1) |
79 |
elif opt == '-u': |
80 |
optD['untag'] = 1 |
81 |
elif opt in ("-v", "--version"): |
82 |
regexp = re.compile(r"\d+(\.\d+)?") |
83 |
ret = regexp.match(arg) |
84 |
if ret is None: |
85 |
print('Invalid version string ' + arg) |
86 |
rv = kRetArgs |
87 |
optD['version'] = arg |
88 |
else: |
89 |
optD[opt] = arg |
90 |
|
91 |
if not rv == kRetSuccess: |
92 |
return {} |
93 |
|
94 |
return optD |
95 |
|
96 |
# Create version strings for jsoc_version.h and CVS, returns a tuple |
97 |
# containing either the two release strings (e.g., ("V8R1", "(801)", "8-1")), |
98 |
# or the two development strings (e.g., ("V8R1X", "(-801)", "8-1")). The |
99 |
# third member of the tuple is always "8-1". Which |
100 |
# tuple is returned is controlled by the 'dev' argument |
101 |
def CreateVersString(versin, dev): |
102 |
regexp = re.compile(r"(\d+)\.(\d+)") |
103 |
matchobj = regexp.match(versin) |
104 |
|
105 |
if not(matchobj is None): |
106 |
try: |
107 |
maj = matchobj.group(1) |
108 |
min = matchobj.group(2) |
109 |
except IndexError: |
110 |
print('Invalid regexp group number.') |
111 |
return None |
112 |
|
113 |
tagstring = maj + "-" + min |
114 |
|
115 |
if dev == 0: |
116 |
return ("V" + maj + "R" + min, "(" + maj + "{0:02d}".format(int(min)) + ")", tagstring) |
117 |
else: |
118 |
return ("V" + maj + "R" + min + "X", "(-" + maj + "{0:02d}".format(int(min)) + ")", tagstring) |
119 |
else: |
120 |
return None |
121 |
|
122 |
def EditVersionFile(versfile, verstuple): |
123 |
rv = kRetSuccess |
124 |
|
125 |
try: |
126 |
with open(versfile, 'r') as fin, open(kTmpFile, 'w') as fout: |
127 |
regexp1 = re.compile(r"#define\s+jsoc_version\s+\"\w+\"") |
128 |
regexp2 = re.compile(r"#define\s+jsoc_vers_num\s+\(\-?\d+\)") |
129 |
|
130 |
for line in fin: |
131 |
matchobj1 = regexp1.match(line) |
132 |
matchobj2 = regexp2.match(line) |
133 |
if not (matchobj1 is None): |
134 |
fbuf = "#define jsoc_version \"" + verstuple[0] + "\"\n" |
135 |
fout.write(fbuf) |
136 |
elif not (matchobj2 is None): |
137 |
fbuf = "#define jsoc_vers_num " + verstuple[1] + "\n" |
138 |
fout.write(fbuf) |
139 |
else: |
140 |
# Simply copy input to output |
141 |
fout.write(line) |
142 |
except OSError: |
143 |
print('Unable to read or write input or output file.') |
144 |
rv = kRetOS |
145 |
except re.error: |
146 |
print('Bad regular expression string.') |
147 |
rv = kRetRegexp |
148 |
|
149 |
if rv == kRetSuccess: |
150 |
# Rename tmp file |
151 |
try: |
152 |
shutil.move(kTmpFile, versfile) |
153 |
except OSError: |
154 |
print('Unable to rename file ', kTmpFile, 'to ', versfile) |
155 |
rv = kRetOS |
156 |
|
157 |
return rv |
158 |
|
159 |
|
160 |
rv = kRetSuccess |
161 |
optD = {} |
162 |
tree = '' |
163 |
version = '' |
164 |
untag = 0 |
165 |
cmd = '' |
166 |
ret = 0 |
167 |
|
168 |
if __name__ == "__main__": |
169 |
optD = GetArgs(sys.argv[1:]) |
170 |
|
171 |
if not(optD is None): |
172 |
if not(optD['version'] is None) and not(optD['untag'] is None): |
173 |
regexp = re.compile(r"(.+)/\s*$") |
174 |
matchobj = regexp.match(optD['tree']) |
175 |
if not (matchobj is None): |
176 |
tree = matchobj.group(1) |
177 |
else: |
178 |
tree = optD['tree'] |
179 |
|
180 |
# `tree` is used for editing jsoc_version.h only; the file in this tree is edited (twice - once for the release tag and once for the development tag) and then checked in; |
181 |
# `tree` should be a HEAD version CVS tree; the file is edited with the release-tag content, committed, tagged with the release tag, edited with the dev tag, and then checked in; |
182 |
version = optD['version'] |
183 |
untag = optD['untag'] |
184 |
versfile = tree + '/' + kVersFile |
185 |
verstuple = CreateVersString(version, 0) |
186 |
|
187 |
if verstuple is None: |
188 |
print('Invalid version string ' + version) |
189 |
rv = kRetArgs |
190 |
|
191 |
if rv == kRetSuccess: |
192 |
# Edit jsoc_version.h - set the release version of the version numbers. |
193 |
rv = EditVersionFile(versfile, verstuple) |
194 |
|
195 |
if rv == kRetSuccess: |
196 |
# Commit jsoc_version.h back to CVS |
197 |
try: |
198 |
with Chdir(tree) as ret: |
199 |
if ret == 0: |
200 |
cmd = 'cvs commit -m "Set the release versions of the version macros for the ' + version + ' release." ' + kVersFile |
201 |
ret = call(cmd, shell=True) |
202 |
else: |
203 |
print('Unable to cd to ' + tree + '.') |
204 |
rv = kRetOS |
205 |
except OSError: |
206 |
print('Unable to cd to ' + tree + '.') |
207 |
rv = kRetOS |
208 |
except ValueError: |
209 |
print('Unable to run cvs cmd: ' + cmd + '.') |
210 |
rv = kRetOS |
211 |
|
212 |
if not(ret == 0): |
213 |
print('cvs command ' + cmd + ' ran improperly.') |
214 |
rv = kRetOS |
215 |
|
216 |
if rv == kRetSuccess: |
217 |
print('Successfully edited ' + versfile + '; set release version.') |
218 |
# Create the tags |
219 |
try: |
220 |
# untag existing tags (if they exist); if the tag does not exist, then no error is returned; calling dlsource.pl is a bit inefficient since each time a new CVS tree is downloaded; dlsource.pl downloads the HEAD tree into a temp dir before untagging; |
221 |
|
222 |
# Full DRMS-release tags |
223 |
cmd = '/home/jsoc/dlsource.pl -o untag -f sdp -t Ver_' + verstuple[2] |
224 |
ret = call(cmd, shell=True) |
225 |
if not(ret == 0): |
226 |
print('ERROR: Unable to delete tag Ver_' + verstuple[2]) |
227 |
rv = kRetOS |
228 |
if rv == kRetSuccess: |
229 |
cmd = '/home/jsoc/dlsource.pl -o untag -f sdp -t Ver_LATEST' |
230 |
ret = call(cmd, shell=True) |
231 |
if not(ret == 0): |
232 |
print('ERROR: Unable to delete tag Ver_LATEST') |
233 |
rv = kRetOS |
234 |
|
235 |
# NetDRMS-release tags |
236 |
if rv == kRetSuccess: |
237 |
cmd = '/home/jsoc/dlsource.pl -o untag -f net -t NetDRMS_Ver_' + verstuple[2] |
238 |
ret = call(cmd, shell=True) |
239 |
if not(ret == 0): |
240 |
print('ERROR: Unable to delete tag NetDRMS_Ver_' + verstuple[2]) |
241 |
rv = kRetOS |
242 |
if rv == kRetSuccess: |
243 |
cmd = '/home/jsoc/dlsource.pl -o untag -f net -t NetDRMS_Ver_LATEST' |
244 |
ret = call(cmd, shell=True) |
245 |
if not(ret == 0): |
246 |
print('ERROR: Unable to delete tag NetDRMS_Ver_LATEST') |
247 |
rv = kRetOS |
248 |
|
249 |
# Create new tags |
250 |
# dlsource.pl downloads the HEAD tree into a temp dir before tagging |
251 |
|
252 |
# Full DRMS-release tags |
253 |
if rv == kRetSuccess: |
254 |
cmd = '/home/jsoc/dlsource.pl -o tag -f sdp -t Ver_' + verstuple[2] |
255 |
ret = call(cmd, shell=True) |
256 |
if not(ret == 0): |
257 |
print('ERROR: Unable to create tag Ver_' + verstuple[2]) |
258 |
rv = kRetOS |
259 |
if rv == kRetSuccess: |
260 |
cmd = '/home/jsoc/dlsource.pl -o tag -f sdp -t Ver_LATEST' |
261 |
ret = call(cmd, shell=True) |
262 |
if not(ret == 0): |
263 |
print('ERROR: Unable to create tag Ver_LATEST') |
264 |
rv = kRetOS |
265 |
|
266 |
# NetDRMS-release tags |
267 |
if rv == kRetSuccess: |
268 |
cmd = '/home/jsoc/dlsource.pl -o tag -f net -t NetDRMS_Ver_' + verstuple[2] |
269 |
ret = call(cmd, shell=True) |
270 |
if not(ret == 0): |
271 |
print('ERROR: Unable to create tag NetDRMS_Ver_' + verstuple[2]) |
272 |
rv = kRetOS |
273 |
if rv == kRetSuccess: |
274 |
cmd = '/home/jsoc/dlsource.pl -o tag -f net -t NetDRMS_Ver_LATEST' |
275 |
ret = call(cmd, shell=True) |
276 |
if not(ret == 0): |
277 |
print('ERROR: Unable to create tag NetDRMS_Ver_LATEST') |
278 |
rv = kRetOS |
279 |
except ValueError: |
280 |
print('Unable to run cvs cmd: ' + cmd + '.') |
281 |
rv = kRetOS |
282 |
|
283 |
if rv == kRetSuccess: |
284 |
print('Successfully created DRMS and NetDRMS release CVS tags.') |
285 |
# Edit jsoc_version.h - set the development version of the version number. |
286 |
verstuple = CreateVersString(version, 1) |
287 |
|
288 |
if verstuple is None: |
289 |
print('Invalid version string ' + version) |
290 |
rv = kRetArgs |
291 |
|
292 |
if rv == kRetSuccess: |
293 |
# Edit jsoc_version.h - set the development version of the version numbers. |
294 |
rv = EditVersionFile(versfile, verstuple) |
295 |
|
296 |
if rv == kRetSuccess: |
297 |
# Commit jsoc_version.h back to CVS |
298 |
try: |
299 |
with Chdir(tree) as ret: |
300 |
if ret == 0: |
301 |
cmd = 'cvs commit -m "Set the development version of the version macros for the ' + version + ' release." ' + kVersFile |
302 |
ret = call(cmd, shell=True) |
303 |
else: |
304 |
rv = kRetOS |
305 |
except OSError: |
306 |
print('Unable to cd to ' + tree + '.') |
307 |
rv = kRetOS |
308 |
except ValueError: |
309 |
print('Unable to run cvs cmd: ' + cmd + '.') |
310 |
rv = kRetOS |
311 |
|
312 |
if not(ret == 0): |
313 |
print('cvs command ' + cmd + ' ran improperly.') |
314 |
rv = kRetOS |
315 |
|
316 |
if rv == kRetSuccess: |
317 |
print('Successfully edited ' + versfile + '; set development version.') |
318 |
else: |
319 |
print('Invalid arguments.') |
320 |
rv = kRetArgs |
321 |
else: |
322 |
print('Invalid arguments.') |
323 |
rv = kRetArgs |
324 |
|
325 |
exit(rv) |