/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to tools/generate_release_notes.py

  • Committer: Jelmer Vernooij
  • Date: 2020-04-05 19:11:34 UTC
  • mto: (7490.7.16 work)
  • mto: This revision was merged to the branch mainline in revision 7501.
  • Revision ID: jelmer@jelmer.uk-20200405191134-0aebh8ikiwygxma5
Populate the .gitignore file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/python
 
1
#!/usr/bin/python3
2
2
 
3
 
# Copyright 2009 Canonical Ltd.
 
3
# Copyright 2009-2010 Canonical Ltd.
4
4
#
5
5
# This program is free software; you can redistribute it and/or modify
6
6
# it under the terms of the GNU General Public License as published by
16
16
# along with this program; if not, write to the Free Software
17
17
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
 
19
 
import os
 
19
"""Generate doc/en/release-notes/index.txt from the per-series NEWS files.
 
20
 
 
21
NEWS files are kept in doc/en/release-notes/, one file per series, e.g.
 
22
doc/en/release-notes/brz-2.3.txt
 
23
"""
 
24
 
 
25
# XXX: add test_source test that latest doc/en/release-notes/brz-*.txt has the
 
26
# NEWS file-id (so that merges of new work will tend to always land new NEWS
 
27
# entries in the latest series).
 
28
 
 
29
 
 
30
import os.path
 
31
import re
20
32
import sys
21
33
from optparse import OptionParser
22
34
 
23
 
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
24
 
 
25
 
 
26
 
def split_into_topics(lines, out_file, out_dir):
27
 
    """Split a large NEWS file into topics, one per release.
28
 
 
29
 
    Releases are detected by matching headings that look like
30
 
    release names. Topics are created with matching names
31
 
    replacing spaces with dashes.
 
35
 
 
36
preamble_plain = """\
 
37
####################
 
38
Breezy Release Notes
 
39
####################
 
40
 
 
41
 
 
42
.. contents:: List of Releases
 
43
   :depth: 2
 
44
 
 
45
"""
 
46
 
 
47
preamble_sphinx = """\
 
48
####################
 
49
Breezy Release Notes
 
50
####################
 
51
 
 
52
 
 
53
.. toctree::
 
54
   :maxdepth: 2
 
55
 
 
56
"""
 
57
 
 
58
 
 
59
def natural_sort_key(file_name):
 
60
    """Split 'aaa-N.MMbbb' into ('aaa-', N, '.' MM, 'bbb')
 
61
 
 
62
    e.g. 1.10b1 will sort as greater than 1.2::
 
63
 
 
64
        >>> natural_sort_key('brz-1.10b1.txt') > natural_sort_key('brz-1.2.txt')
 
65
        True
32
66
    """
33
 
    topic_file = None
34
 
    for index, line in enumerate(lines):
35
 
        maybe_new_topic = line[:4] in ['bzr ', 'bzr-0',]
36
 
        if maybe_new_topic and lines[index + 1].startswith('####'):
37
 
            release = line.strip()
38
 
            if topic_file is None:
39
 
                # First topic found
40
 
                out_file.write(".. toctree::\n   :maxdepth: 1\n\n")
41
 
            else:
42
 
                # close the current topic
43
 
                topic_file.close()
44
 
            topic_file = open_topic_file(out_file, out_dir, release)
45
 
        elif topic_file:
46
 
            topic_file.write(line)
47
 
        else:
48
 
            # Still in the header - dump content straight to output
49
 
            out_file.write(line)
50
 
 
51
 
 
52
 
def open_topic_file(out_file, out_dir, release):
53
 
    topic_name = release.replace(' ', '-')
54
 
    out_file.write("   %s\n" % (topic_name,))
55
 
    topic_path = os.path.join(out_dir, "%s.txt" % (topic_name,))
56
 
    result = open(topic_path, 'w')
57
 
    result.write("%s\n" % (release,))
58
 
    return result
 
67
    file_name = os.path.basename(file_name)
 
68
    parts = re.findall(r'(?:[0-9]+|[^0-9]+)', file_name)
 
69
    result = []
 
70
    for part in parts:
 
71
        if re.match('^[0-9]+$', part) is not None:
 
72
            part = int(part)
 
73
        result.append(part)
 
74
    return tuple(result)
 
75
 
 
76
 
 
77
def output_news_file_sphinx(out_file, news_file_name):
 
78
    news_file_name = os.path.basename(news_file_name)
 
79
    if not news_file_name.endswith('.txt'):
 
80
        raise AssertionError(
 
81
            'NEWS file %s does not have .txt extension.'
 
82
            % (news_file_name,))
 
83
    doc_name = news_file_name[:-4]
 
84
    link_text = doc_name.replace('-', ' ')
 
85
    out_file.write('   %s <%s>\n' % (link_text, doc_name))
 
86
 
 
87
 
 
88
def output_news_file_plain(out_file, news_file_name):
 
89
    with open(news_file_name, 'r') as f:
 
90
        lines = f.readlines()
 
91
    title = os.path.basename(news_file_name)[len('brz-'):-len('.txt')]
 
92
    for line in lines:
 
93
        if line == '####################\n':
 
94
            line = '#' * len(title) + '\n'
 
95
        elif line == 'Breezy Release Notes\n':
 
96
            line = title + '\n'
 
97
        elif line == '.. toctree::\n':
 
98
            continue
 
99
        elif line == '   :maxdepth: 1\n':
 
100
            continue
 
101
        out_file.write(line)
 
102
    out_file.write('\n\n')
59
103
 
60
104
 
61
105
def main(argv):
62
106
    # Check usage
63
 
    parser = OptionParser(usage="%prog SOURCE DESTINATION")
 
107
    parser = OptionParser(usage="%prog OUTPUT_FILE NEWS_FILE [NEWS_FILE ...]")
64
108
    (options, args) = parser.parse_args(argv)
65
 
    if len(args) != 2:
 
109
    if len(args) < 2:
66
110
        parser.print_help()
67
111
        sys.exit(1)
68
112
 
69
113
    # Open the files and do the work
70
 
    infile_name = args[0]
71
 
    outfile_name = args[1]
72
 
    outdir = os.path.dirname(outfile_name)
73
 
    infile = open(infile_name, 'r')
74
 
    try:
75
 
        lines = infile.readlines()
76
 
    finally:
77
 
        infile.close()
78
 
    outfile = open(outfile_name, 'w')
79
 
    try:
80
 
        split_into_topics(lines, outfile, outdir)
81
 
    finally:
82
 
        outfile.close()
 
114
    out_file_name = args[0]
 
115
    news_file_names = sorted(args[1:], key=natural_sort_key, reverse=True)
 
116
 
 
117
    if os.path.basename(out_file_name) == 'index.txt':
 
118
        preamble = preamble_sphinx
 
119
        output_news_file = output_news_file_sphinx
 
120
    else:
 
121
        preamble = preamble_plain
 
122
        output_news_file = output_news_file_plain
 
123
 
 
124
    with open(out_file_name, 'w') as out_file:
 
125
        out_file.write(preamble)
 
126
        for news_file_name in news_file_names:
 
127
            output_news_file(out_file, news_file_name)
83
128
 
84
129
 
85
130
if __name__ == '__main__':