3 Script to prepare the release of Gaudi.
5 @author Marco Clemencic
13 from subprocess
import Popen, PIPE
17 Ensure we have a usable version of Git (>= 1.7.9.1).
20 * https://raw.githubusercontent.com/git/git/master/Documentation/RelNotes/1.7.9.1.txt
21 * https://github.com/git/git/commit/36ed1913e1d5de0930e59db6eeec3ccb2bd58bd9
23 proc = Popen([
'git',
'--version'], stdout=PIPE)
24 version = proc.communicate()[0].split()[-1]
26 raise RuntimeError(
'could not get git version')
28 raise RuntimeError(
'bad version of git found: %s (1.7.9.1 required)' % version)
30 _VK_RE = re.compile(
r'(\d+|\D+)')
33 Key function to be passes to list.sort() to sort strings
36 return [int(i)
if i[0]
in '0123456789' else i
37 for i
in _VK_RE.split(x)
42 Return the latest Gaudi tag (of the format "GAUDI/GAUDI_*").
44 logging.info(
'looking for latest tag')
46 logging.debug(
'using command %r', cmd)
47 proc = Popen(cmd, stdout=PIPE)
48 output = proc.communicate()[0]
50 for tag
in output.splitlines()
51 if tag.startswith(
'GAUDI/GAUDI_')]
53 tags.sort(key=versionKey)
54 logging.info(
'found %s', tags[-1])
56 logging.info(
'no valid tag found')
60 Return the release notes (in the old LHCb format) extracted from git
61 commits for a given path.
64 '--first-parent',
'--date=short',
65 '--pretty=format:! %ad - commit %h%n%n%w(80,1,3)- %s%n%n%b%n']
67 cmd.append(
'{0}..{1}'.
format(from_tag, branch
or ''))
72 logging.info(
'preparing release notes for %s%s', path,
73 ' since ' + from_tag
if from_tag
else '')
74 logging.debug(
'using command %r', cmd)
75 proc = Popen(cmd, stdout=PIPE)
76 return proc.communicate()[0]
80 Smartly prepend the content of notes to the release.notes file in path.
82 notes_filename = os.path.join(path,
'doc',
'release.notes')
83 logging.info(
'updating %s', notes_filename)
84 from itertools
import takewhile, dropwhile
85 def dropuntil(predicate, iterable):
86 return dropwhile(
lambda x:
not predicate(x), iterable)
87 with open(notes_filename)
as notes_file:
88 orig_data = iter(list(notes_file))
89 header = takewhile(str.strip, orig_data)
90 with open(notes_filename,
'w')
as notes_file:
91 notes_file.writelines(header)
92 notes_file.write(
'\n')
93 notes_file.writelines(l.rstrip() +
'\n' for l
in notes.splitlines())
94 notes_file.writelines(dropuntil(re.compile(
r'^!?============').match, orig_data))
97 _req_version_pattern = re.compile(
r"^\s*version\s*(v[0-9]+r[0-9]+(?:p[0-9]+)?)\s*$")
98 _cml_version_pattern = re.compile(
r"^\s*gaudi_subdir\s*\(\s*\S+\s+(v[0-9]+r[0-9]+(?:p[0-9]+)?)\)\s*$")
101 Find the version number of a subdirectory.
103 global _cml_version_pattern
104 for l
in open(os.path.join(path,
'CMakeLists.txt')):
105 m = _cml_version_pattern.match(l)
111 if os.path.exists(cml):
115 m = _cml_version_pattern.match(l)
116 if m
and m.group(1) != newversion:
117 logging.debug(
'%s: %s -> %s', cml, m.group(1), newversion)
118 l = l.replace(m.group(1), newversion)
122 open(cml,
"w").writelines(out)
126 Compare the version of the package with the new one and update the package if
129 Returns true if the package have been modified.
131 global _req_version_pattern
134 req = os.path.join(packagedir,
'cmt',
'requirements')
136 m = _req_version_pattern.match(l)
138 if m.group(1) != newversion:
139 logging.debug(
'%s: %s -> %s', packagedir, m.group(1), newversion)
140 l = l.replace(m.group(1),newversion)
144 open(req,
"w").writelines(out)
146 ver = os.path.join(packagedir,
"version.cmt")
147 if os.path.exists(ver):
148 current = open(ver).read().strip()
149 if current != newversion:
150 open(ver,
"w").write(newversion +
"\n")
152 cml = os.path.normpath(os.path.join(packagedir,
'CMakeLists.txt'))
154 if 'GaudiKernel' in packagedir:
155 cml = os.path.normpath(os.path.join(packagedir,
'src',
'Util',
'CMakeLists.txt'))
160 title =
' %s %s ' % (pkg, version)
161 letf_chars = (78 - len(title)) / 2
162 right_chars = 78 - letf_chars - len(title)
163 separator = (
'=' * letf_chars) + title + (
'=' * right_chars)
167 logging.basicConfig(level=logging.DEBUG)
169 for path
in [d
for d
in os.listdir(os.curdir)
170 if os.path.exists(os.path.join(d,
'doc',
'release.notes'))]:
172 (
tag_bar(path, new_versions[path]) +
'\n\n'
173 if path
in new_versions
179 logging.basicConfig(level=logging.DEBUG)
180 os.chdir(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
182 for l
in open(
'toolchain.cmake'):
183 m = re.match(
r'^\s*set\(\s*heptools_version\s+(\S*)\s*\)', l)
185 HEPToolsVers = m.group(1)
186 print "Using HEPTools", HEPToolsVers
189 logging.error(
'Cannot find HEPTools version')
194 for dirpath, dirnames, filenames
in os.walk(os.curdir):
195 if 'CMakeLists.txt' in filenames
and dirpath != os.curdir:
199 dirnames[:] = [dirname
for dirname
in dirnames
200 if not dirname.startswith(
'build.')
and
204 special_subdirs = [
"Gaudi",
"GaudiExamples",
"GaudiSys",
"GaudiRelease"]
209 old_version = latest_tag.split(
'_')[-1]
210 new_version = raw_input(
"The old version of the project is %s, which is the new one? " % old_version)
216 for pkgdir
in all_subdirs():
217 cmlfile = os.path.join(pkgdir,
'CMakeLists.txt')
218 reqfile = os.path.join(pkgdir,
'cmt',
'requirements')
220 pkg = os.path.basename(pkgdir)
224 if pkg
in special_subdirs:
227 git_log = Popen([
'git',
'log',
'-m',
'--first-parent',
228 '--stat', latest_tag +
'..master', pkgdir],
229 stdout=PIPE).communicate()[0].strip()
231 msg = (
'\nThe old version of {0} is {1}, these are the changes:\n'
233 'Which version you want (old is {1})? ').
format(pkg,
236 vers = raw_input(msg)
237 while not vers
or vers == old_vers:
238 vers = raw_input(
'give me a version, please. ')
244 new_versions[pkg] = vers
or old_vers
248 reqfile = os.path.join(
'GaudiRelease',
'cmt',
'requirements')
250 for l
in open(reqfile):
251 sl = l.strip().split()
252 if sl
and sl[0] ==
"use":
253 if sl[1]
in new_versions:
254 if sl[2] != new_versions[sl[1]]:
255 l = l.replace(sl[2], new_versions[sl[1]])
257 open(reqfile,
"w").writelines(out)
259 config = ConfigParser.ConfigParser()
260 config.optionxform = str
261 if os.path.exists(
'project.info'):
262 config.read(
'project.info')
263 if not config.has_section(
'Packages'):
264 config.add_section(
'Packages')
265 for pack_vers
in sorted(new_versions.items()):
266 config.set(
'Packages', *pack_vers)
267 config.write(open(
'project.info',
'wb'))
271 for l
in open(
'CMakeLists.txt'):
272 if l.strip().startswith(
'gaudi_project'):
273 l =
'gaudi_project(Gaudi %s)\n' % new_version
275 open(
'CMakeLists.txt',
"w").writelines(out)
278 if __name__ ==
'__main__':
def updateReleaseNotes(path, notes)
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
def change_cml_version(cml, newversion)
def extract_version(path)
def change_version(packagedir, newversion)