diff options
Diffstat (limited to 'tools/generate_release_notes.py')
-rw-r--r-- | tools/generate_release_notes.py | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/tools/generate_release_notes.py b/tools/generate_release_notes.py new file mode 100644 index 0000000..934dd0b --- /dev/null +++ b/tools/generate_release_notes.py @@ -0,0 +1,137 @@ +#!/usr/bin/python + +# Copyright 2009-2010 Canonical Ltd. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +"""Generate doc/en/release-notes/index.txt from the per-series NEWS files. + +NEWS files are kept in doc/en/release-notes/, one file per series, e.g. +doc/en/release-notes/bzr-2.3.txt +""" + +# XXX: add test_source test that latest doc/en/release-notes/bzr-*.txt has the +# NEWS file-id (so that merges of new work will tend to always land new NEWS +# entries in the latest series). + + +import os.path +import re +import sys +from optparse import OptionParser + + +preamble_plain = """\ +#################### +Bazaar Release Notes +#################### + + +.. contents:: List of Releases + :depth: 2 + +""" + +preamble_sphinx = """\ +#################### +Bazaar Release Notes +#################### + + +.. toctree:: + :maxdepth: 2 + +""" + + +def natural_sort_key(file_name): + """Split 'aaa-N.MMbbb' into ('aaa-', N, '.' MM, 'bbb') + + e.g. 1.10b1 will sort as greater than 1.2:: + + >>> natural_sort_key('bzr-1.10b1.txt') > natural_sort_key('bzr-1.2.txt') + True + """ + file_name = os.path.basename(file_name) + parts = re.findall(r'(?:[0-9]+|[^0-9]+)', file_name) + result = [] + for part in parts: + if re.match('^[0-9]+$', part) is not None: + part = int(part) + result.append(part) + return tuple(result) + + +def output_news_file_sphinx(out_file, news_file_name): + news_file_name = os.path.basename(news_file_name) + if not news_file_name.endswith('.txt'): + raise AssertionError( + 'NEWS file %s does not have .txt extension.' + % (news_file_name,)) + doc_name = news_file_name[:-4] + link_text = doc_name.replace('-', ' ') + out_file.write(' %s <%s>\n' % (link_text, doc_name)) + + +def output_news_file_plain(out_file, news_file_name): + f = open(news_file_name, 'rb') + try: + lines = f.readlines() + finally: + f.close() + title = os.path.basename(news_file_name)[len('bzr-'):-len('.txt')] + for line in lines: + if line == '####################\n': + line = '#' * len(title) + '\n' + elif line == 'Bazaar Release Notes\n': + line = title + '\n' + elif line == '.. toctree::\n': + continue + elif line == ' :maxdepth: 1\n': + continue + out_file.write(line) + out_file.write('\n\n') + + +def main(argv): + # Check usage + parser = OptionParser(usage="%prog OUTPUT_FILE NEWS_FILE [NEWS_FILE ...]") + (options, args) = parser.parse_args(argv) + if len(args) < 2: + parser.print_help() + sys.exit(1) + + # Open the files and do the work + out_file_name = args[0] + news_file_names = sorted(args[1:], key=natural_sort_key, reverse=True) + + if os.path.basename(out_file_name) == 'index.txt': + preamble = preamble_sphinx + output_news_file = output_news_file_sphinx + else: + preamble = preamble_plain + output_news_file = output_news_file_plain + + out_file = open(out_file_name, 'w') + try: + out_file.write(preamble) + for news_file_name in news_file_names: + output_news_file(out_file, news_file_name) + finally: + out_file.close() + + +if __name__ == '__main__': + main(sys.argv[1:]) |