~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to tools/generate_release_notes.py

  • Committer: John Arbash Meinel
  • Date: 2009-06-12 18:05:15 UTC
  • mto: (4371.4.5 vila-better-heads)
  • mto: This revision was merged to the branch mainline in revision 4449.
  • Revision ID: john@arbash-meinel.com-20090612180515-t0cwbjsnve094oik
Add a failing test for handling nodes that are in the same linear chain.

It fails because the ancestry skipping causes us to miss the fact that the two nodes
are actually directly related. We could check at the beginning, as the 
code used to do, but I think that will be incomplete for the more-than-two
heads cases.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/python
2
 
 
3
 
# Copyright 2009-2010 Canonical Ltd.
4
 
#
5
 
# This program is free software; you can redistribute it and/or modify
6
 
# it under the terms of the GNU General Public License as published by
7
 
# the Free Software Foundation; either version 2 of the License, or
8
 
# (at your option) any later version.
9
 
#
10
 
# This program is distributed in the hope that it will be useful,
11
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
# GNU General Public License for more details.
14
 
#
15
 
# You should have received a copy of the GNU General Public License
16
 
# along with this program; if not, write to the Free Software
17
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
 
 
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/bzr-2.3.txt
23
 
"""
24
 
 
25
 
# XXX: add test_source test that latest doc/en/release-notes/bzr-*.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
32
 
import sys
33
 
from optparse import OptionParser
34
 
 
35
 
 
36
 
preamble_plain = """\
37
 
####################
38
 
Bazaar Release Notes
39
 
####################
40
 
 
41
 
 
42
 
.. contents:: List of Releases
43
 
   :depth: 2
44
 
 
45
 
"""
46
 
 
47
 
preamble_sphinx = """\
48
 
####################
49
 
Bazaar 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('bzr-1.10b1.txt') > natural_sort_key('bzr-1.2.txt')
65
 
        True
66
 
    """
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
 
    f = open(news_file_name, 'rb')
90
 
    try:
91
 
        lines = f.readlines()
92
 
    finally:
93
 
        f.close()
94
 
    title = os.path.basename(news_file_name)[len('bzr-'):-len('.txt')]
95
 
    for line in lines:
96
 
        if line == '####################\n':
97
 
            line = '#' * len(title) + '\n'
98
 
        elif line == 'Bazaar Release Notes\n':
99
 
            line = title + '\n'
100
 
        elif line == '.. toctree::\n':
101
 
            continue
102
 
        elif line == '   :maxdepth: 1\n':
103
 
            continue
104
 
        out_file.write(line)
105
 
    out_file.write('\n\n')
106
 
 
107
 
 
108
 
def main(argv):
109
 
    # Check usage
110
 
    parser = OptionParser(usage="%prog OUTPUT_FILE NEWS_FILE [NEWS_FILE ...]")
111
 
    (options, args) = parser.parse_args(argv)
112
 
    if len(args) < 2:
113
 
        parser.print_help()
114
 
        sys.exit(1)
115
 
 
116
 
    # Open the files and do the work
117
 
    out_file_name = args[0]
118
 
    news_file_names = sorted(args[1:], key=natural_sort_key, reverse=True)
119
 
 
120
 
    if os.path.basename(out_file_name) == 'index.txt':
121
 
        preamble = preamble_sphinx
122
 
        output_news_file = output_news_file_sphinx
123
 
    else:
124
 
        preamble = preamble_plain
125
 
        output_news_file = output_news_file_plain
126
 
 
127
 
    out_file = open(out_file_name, 'w')
128
 
    try:
129
 
        out_file.write(preamble)
130
 
        for news_file_name in news_file_names:
131
 
            output_news_file(out_file, news_file_name)
132
 
    finally:
133
 
        out_file.close()
134
 
 
135
 
 
136
 
if __name__ == '__main__':
137
 
    main(sys.argv[1:])