~launchpad-pqm/launchpad/devel

9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
1
#!/usr/bin/python
2
# -*- coding: utf-8 -*-
3
#
4
# Copyright 2009 Canonical Ltd.  This software is licensed under the
5
# GNU Affero General Public License version 3 (see the file LICENSE).
6
9373.1.3 by Karl Fogel
* utilities/community-contributions.py: Update doc string to start
7
"""Show what Launchpad community contributors have done.
8
9
Trawl a Launchpad branch's history to detect contributions by non-Canonical
10
developers, then update https://dev.launchpad.net/Contributions accordingly.
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
11
10456.1.10 by William Grant
Take devel and db-devel paths as options instead of arguments, to make ordering more obvious.
12
Usage: community-contributions.py [options] --devel=PATH --db-devel=DB_PATH
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
13
14
Requirements:
10456.1.4 by William Grant
Fully support multiple branches -- they will now be linked properly, and their revisions will be labeled.
15
       You need both the 'devel' and 'db-devel' branches of Launchpad
16
       available locally (see https://dev.launchpad.net/Getting),
17
       your ~/.moin_ids file must be set up correctly, and you need
18
       editmoin.py (if you don't have it, the error message will tell
19
       you where to get it).
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
20
21
Options:
10456.1.10 by William Grant
Take devel and db-devel paths as options instead of arguments, to make ordering more obvious.
22
  -q               Print no non-essential messages.
23
  -h, --help       Print this help.
24
  --dry-run        Don't update the wiki, just print the new page to stdout.
25
  --draft-run      Update the wiki "/Draft" page instead of the real page.
26
  --devel=PATH     Specify the filesystem path to the 'devel' branch.
27
  --db-devel=PATH  Specify the filesystem path to the 'db-devel' branch.
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
28
"""
29
30
# General notes:
31
#
32
# The Right Way to do this would probably be to output some kind of
33
# XML format, and then have a separate converter script transform that
34
# to wiki syntax and update the wiki page.  But as the wiki is our
35
# only consumer right now, we just output wiki syntax and update the
36
# wiki page directly, premature generalization being the root of all
37
# evil.
38
#
39
# For understanding the code, you may find it helpful to see
40
# bzrlib/log.py and http://bazaar-vcs.org/Integrating_with_Bazaar.
41
9373.1.16 by Karl Fogel
* utilities/community-contributions.py: Sort imports, as per jml's review.
42
import getopt
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
43
import re
44
import sys
9373.1.16 by Karl Fogel
* utilities/community-contributions.py: Sort imports, as per jml's review.
45
46
from bzrlib import log
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
47
from bzrlib.branch import Branch
48
from bzrlib.osutils import format_date
49
50
try:
51
    from editmoin import editshortcut
52
except:
10281.1.2 by Jamal Fanaian
Fixed lint messages regardling line length
53
    sys.stderr.write("""ERROR: Unable to import from 'editmoin'. How to solve:
9521.1.1 by Karl Fogel
In utilities/community-contributions.py, update error message to give
54
Get editmoin.py from launchpadlib's "contrib/" directory:
55
56
  http://bazaar.launchpad.net/~lazr-developers/launchpadlib/trunk/annotate/head%3A/contrib/editmoin.py
57
58
(Put it in the same directory as this script and everything should work.)
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
59
""")
60
    sys.exit(1)
61
62
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
63
def wiki_encode(x):
64
    """Encode a Unicode string for display on the wiki."""
65
    return x.encode('utf-8', 'xmlcharrefreplace')
66
67
68
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
69
# The output contains two classes of contributors: people who don't
70
# work for Canonical at all, and people who do work for Canonical but
71
# not on the Launchpad team.
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
72
#
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
73
# People who used to work for Canonical on the Launchpad team are not
74
# shown in the output, since they don't help us from a "contributions
75
# from outside the team" perspective, so they are listed as known
76
# Canonical Launchpad developers even though they aren't actually on
77
# the team anymore.  There may be a few former Canonicalites who
78
# didn't work on the Launchpad team but who still contributed to
79
# Launchpad; most of them would have done so before Launchpad was open
80
# sourced in July 2009, though, and since this script is really about
81
# showing things that have happened since Launchpad was open sourced,
82
# they may be listed as Launchpad team members anyway just to ensure
83
# they don't appear in the output.
84
#
85
# (As time goes on, that assumption will be less and less correct, of
86
# course, and eventually we may wish to do something about it.  Also,
87
# there are some people, e.g. Jelmer Vernooij, who made contributions
88
# to Launchpad before working at Canonical, but who now work on the
89
# Launchpad team at Canonical.  Ideally, each potentially listable
90
# contributor could have a set of roles, and a date range associated
91
# with each role... but that would be overkill for this script.  That
92
# last 2% of correctness would cost way too much to achieve.)
93
#
10224.15.1 by Karl Fogel
* utilities/community-contributions.py
94
# XXX: Karl Fogel 2009-09-10 bug=513608: We should use launchpadlib
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
95
# to consult Launchpad itself to find out who's a Canonical developer,
96
# and within that who's a Launchpad developer.
97
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
98
99
# If a contributor's address contains this, then they are or were a
100
# Canonical developer -- maybe on the Launchpad team, maybe not.
101
CANONICAL_ADDR = wiki_encode(u" {_AT_} canonical.com")
102
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
103
# People on the Canonical Launchpad team.
104
known_canonical_lp_devs = \
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
105
    [wiki_encode(x) for x in (u'Aaron Bentley',
106
                              u'Abel Deuring',
107
                              u'Andrew Bennetts',
108
                              u'Barry Warsaw',
11728.1.1 by William Grant
Update community-contributions.py's list Launchpad and Canonical developers, and add some more email merges.
109
                              u'Benji York',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
110
                              u'Bjorn Tillenius',
111
                              u'Björn Tillenius',
10456.1.12 by William Grant
Start at revision 1 of both branches, and update the name maps for the older revisions.
112
                              u'Brad Bollenbach',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
113
                              u'Brad Crittenden',
114
                              u'Brian Fromme',
10456.1.12 by William Grant
Start at revision 1 of both branches, and update the name maps for the older revisions.
115
                              u'Canonical.com Patch Queue Manager',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
116
                              u'Carlos Perello Marin',
117
                              u'Carlos Perelló Marín',
10456.1.12 by William Grant
Start at revision 1 of both branches, and update the name maps for the older revisions.
118
                              u'carlos.perello {_AT_} canonical.com',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
119
                              u'Celso Providelo',
120
                              u'Christian Reis',
10456.1.12 by William Grant
Start at revision 1 of both branches, and update the name maps for the older revisions.
121
                              u'Christian Robottom Reis',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
122
                              u'kiko {_AT_} beetle',
123
                              u'Curtis Hovey',
124
                              u'Dafydd Harries',
125
                              u'Danilo Šegan',
11728.1.1 by William Grant
Update community-contributions.py's list Launchpad and Canonical developers, and add some more email merges.
126
                              u'Danilo Segan',
10456.1.12 by William Grant
Start at revision 1 of both branches, and update the name maps for the older revisions.
127
                              u'david <david {_AT_} marvin>',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
128
                              u'Данило Шеган',
129
                              u'данило шеган',
130
                              u'Daniel Silverstone',
131
                              u'David Allouche',
132
                              u'Deryck Hodge',
133
                              u'Diogo Matsubara',
134
                              u'Edwin Grubbs',
10456.1.12 by William Grant
Start at revision 1 of both branches, and update the name maps for the older revisions.
135
                              u'Elliot Murphy',
136
                              u'Firstname Lastname',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
137
                              u'Francis Lacoste',
138
                              u'Francis J. Lacoste',
139
                              u'Gary Poster',
140
                              u'Gavin Panella',
141
                              u'Graham Binns',
142
                              u'Guilherme Salgado',
143
                              u'Henning Eggers',
10456.1.12 by William Grant
Start at revision 1 of both branches, and update the name maps for the older revisions.
144
                              u'Herb McNew',
11728.1.1 by William Grant
Update community-contributions.py's list Launchpad and Canonical developers, and add some more email merges.
145
                              u'Ian Booth',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
146
                              u'James Henstridge',
11728.1.1 by William Grant
Update community-contributions.py's list Launchpad and Canonical developers, and add some more email merges.
147
                              u'j.c.sackett',
148
                              u'jc',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
149
                              u'Jelmer Vernooij',
150
                              u'Jeroen Vermeulen',
151
                              u'Jeroen T. Vermeulen',
152
                              u'Joey Stanford',
11728.1.1 by William Grant
Update community-contributions.py's list Launchpad and Canonical developers, and add some more email merges.
153
                              u'Jon Sackett',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
154
                              u'Jonathan Lange',
11702.2.2 by Brian Murray
j.c.sackett works on Launchpad
155
                              u'j.c.sackett',
156
                              u'jonathan.sackett {_AT_} canonical.com',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
157
                              u'jml {_AT_} canonical.com',
158
                              u'jml {_AT_} mumak.net',
159
                              u'Jonathan Knowles',
10456.1.12 by William Grant
Start at revision 1 of both branches, and update the name maps for the older revisions.
160
                              u'jonathan.knowles {_AT_} canonical.com',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
161
                              u'Julian Edwards',
162
                              u'Karl Fogel',
10456.1.12 by William Grant
Start at revision 1 of both branches, and update the name maps for the older revisions.
163
                              u'Launch Pad',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
164
                              u'Launchpad APA',
10456.1.12 by William Grant
Start at revision 1 of both branches, and update the name maps for the older revisions.
165
                              u'Launchpad Developers',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
166
                              u'Launchpad Patch Queue Manager',
167
                              u'Launchpad PQM Bot',
168
                              u'Leonard Richardson',
169
                              u'Malcolm Cleaton',
170
                              u'Maris Fogels',
171
                              u'Mark Shuttleworth',
172
                              u'Martin Albisetti',
173
                              u'Matt Zimmerman',
174
                              u'Matthew Paul Thomas',
10456.1.12 by William Grant
Start at revision 1 of both branches, and update the name maps for the older revisions.
175
                              u'Matthew Thomas',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
176
                              u'Matthew Revell',
177
                              u'matthew.revell {_AT_} canonical.com',
178
                              u'Michael Hudson',
10456.1.12 by William Grant
Start at revision 1 of both branches, and update the name maps for the older revisions.
179
                              u'michael.hudson {_AT_} canonical.com',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
180
                              u'Michael Nelson',
181
                              u'Muharem Hrnjadovic',
182
                              u'muharem {_AT_} canonical.com',
10456.1.12 by William Grant
Start at revision 1 of both branches, and update the name maps for the older revisions.
183
                              u'Patch Queue Manager',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
184
                              u'Paul Hummer',
185
                              u'Robert Collins',
11728.1.1 by William Grant
Update community-contributions.py's list Launchpad and Canonical developers, and add some more email merges.
186
                              u'root <root {_AT_} ubuntu>',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
187
                              u'Stuart Bishop',
10456.1.12 by William Grant
Start at revision 1 of both branches, and update the name maps for the older revisions.
188
                              u'Steve Alexander',
11057.1.1 by Jonathan Lange
Correct some bugs with the Launchpad data
189
                              u'Steve Kowalik',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
190
                              u'Steve McInerney',
191
                              u'<steve {_AT_} stedee.id.au>',
10456.1.12 by William Grant
Start at revision 1 of both branches, and update the name maps for the older revisions.
192
                              u'test {_AT_} canonical.com',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
193
                              u'Tom Haddon',
194
                              u'Tim Penhey',
195
                              u'Tom Berger',
10456.1.12 by William Grant
Start at revision 1 of both branches, and update the name maps for the older revisions.
196
                              u'ubuntu <ubuntu {_AT_} lp-dev>',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
197
                              u'Ursula Junque',
198
                              )]
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
199
200
# People known to work for Canonical but not on the Launchpad team.
201
# Anyone with "@canonical.com" in their email address is considered to
202
# work for Canonical, but some people occasionally submit changes from
203
# their personal email addresses; this list contains people known to
204
# do that, so we can treat them appropriately in the output.
205
known_canonical_non_lp_devs = \
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
206
    [wiki_encode(x) for x in (u'Adam Conrad',
207
                              u'Andrew Bennetts',
208
                              u'Anthony Lenton',
209
                              u'Cody Somerville',
210
                              u'Cody A.W. Somerville',
211
                              u'David Murphy',
11057.1.1 by Jonathan Lange
Correct some bugs with the Launchpad data
212
                              u'Didier Roche',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
213
                              u'Elliot Murphy',
214
                              u'Gabriel Neuman gneuman {_AT_} async.com',
215
                              u'Gustavo Niemeyer',
216
                              u'James Henstridge',
11057.1.1 by Jonathan Lange
Correct some bugs with the Launchpad data
217
                              u'James Westby',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
218
                              u'John Lenton',
219
                              u'Kees Cook',
220
                              u'LaMont Jones',
11057.1.1 by Jonathan Lange
Correct some bugs with the Launchpad data
221
                              u'Martin Pitt',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
222
                              u'Martin Pool',
223
                              u'Matt Zimmerman',
224
                              u'Michael Casadevall',
225
                              u'Michael Vogt',
226
                              u'Sidnei da Silva',
10667.1.1 by Karl Fogel
* utilities/community-contributions.py
227
                              u'Dustin Kirkland',
11728.1.1 by William Grant
Update community-contributions.py's list Launchpad and Canonical developers, and add some more email merges.
228
                              u'John Arbash Meinel',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
229
                              )]
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
230
11057.1.2 by Jonathan Lange
Flakes, space
231
# Some people have made commits using various names and/or email
10281.1.1 by Jamal Fanaian
Created name map for community-contributions to merge people using different names/email addresses.
232
# addresses, so this map will be used to merge them accordingly.
10301.1.8 by Karl Fogel
Clean up the way we do string encoding. No functional change.
233
# The map is initialized from this list of pairs, where each pair is
234
# of the form (CONTRIBUTOR_AS_SEEN, UNIFYING_IDENTITY_FOR_CONTRIBUTOR).
235
merge_names_pairs = (
236
    (u'Jamal Fanaian <jfanaian {_AT_} gmail.com>',
237
     u'Jamal Fanaian <jamal.fanaian {_AT_} gmail.com>'),
238
    (u'Jamal Fanaian <jamal {_AT_} jfvm1>',
239
     u'Jamal Fanaian <jamal.fanaian {_AT_} gmail.com>'),
240
    (u'LaMont Jones <lamont {_AT_} rover3>',
241
     u'LaMont Jones <lamont {_AT_} debian.org>'),
10456.1.12 by William Grant
Start at revision 1 of both branches, and update the name maps for the older revisions.
242
    (u'Sidnei <sidnei {_AT_} ubuntu>',
243
     u'Sidnei da Silva <sidnei.da.silva {_AT_} canonical.com>'),
244
    (u'Sidnei da Silva <sidnei.da.silva {_AT_} gmail.com>',
245
     u'Sidnei da Silva <sidnei.da.silva {_AT_} canonical.com>'),
246
    (u'Sidnei da Silva <sidnei {_AT_} canonical.com>',
247
     u'Sidnei da Silva <sidnei.da.silva {_AT_} canonical.com>'),
248
    (u'Adam Conrad <adconrad {_AT_} ziggup>',
249
     u'Adam Conrad <adconrad {_AT_} 0c3.net>'),
250
    (u'Elliot Murphy <elliot {_AT_} elliotmurphy.com>',
251
     u'Elliot Murphy <elliot {_AT_} canonical.com>'),
252
    (u'Elliot Murphy <elliot.murphy {_AT_} canonical.com>',
253
     u'Elliot Murphy <elliot {_AT_} canonical.com>'),
254
    (u'Cody Somerville <cody-somerville {_AT_} mercurial>',
255
     u'Cody A.W. Somerville <cody.somerville {_AT_} canonical.com>'),
256
    (u'Adam Conrad <adconrad {_AT_} chinstrap>',
257
     u'Adam Conrad <adconrad {_AT_} 0c3.net>'),
258
    (u'Adam Conrad <adconrad {_AT_} cthulhu>',
259
     u'Adam Conrad <adconrad {_AT_} 0c3.net>'),
11728.1.1 by William Grant
Update community-contributions.py's list Launchpad and Canonical developers, and add some more email merges.
260
    (u'James Westby <james.westby {_AT_} linaro.org>',
261
     u'James Westby <james.westby {_AT_} canonical.com'),
262
    (u'Bryce Harrington <bryce {_AT_} canonical.com>',
263
     u'Bryce Harrington <bryce.harrington {_AT_} canonical.com>'),
264
    (u'Dustin Kirkland <kirkland {_AT_} x200>',
265
     u'Dustin Kirkland <kirkland {_AT_} canonical.com>'),
266
    (u'Anthony Lenton <antoniolenton {_AT_} gmail.com>',
267
     u'Anthony Lenton <anthony.lenton {_AT_} canonical.com>'),
268
    (u'Steve Kowalik <steven {_AT_} quelled>',
269
     u'Steve Kowalik <steve.kowalik {_AT_} canonical.com>'),
270
    (u'Steve Kowalik <stevenk {_AT_} ubuntu.com>',
271
     u'Steve Kowalik <steve.kowalik {_AT_} canonical.com>'),
272
    (u'jc <jc {_AT_} launchpad>',
273
     u'j.c.sackett <jonathan.sackett {_AT_} canonical.com>'),
274
    (u'Jon Sackett <jc {_AT_} jabberwocky>',
275
     u'j.c.sackett <jonathan.sackett {_AT_} canonical.com>'),
276
    (u'John Arbash Meinel <jameinel {_AT_} falco-lucid>',
277
     u'John Arbash Meinel <john {_AT_} arbash-meinel.com>'),
278
    (u'Martin Pool <mbp {_AT_} sourcefrog.net>',
279
     u'Martin Pool <mbp {_AT_} canonical.com>'),
11728.1.2 by William Grant
Add another email mapping.
280
    (u'Andrea Corbellini <corbellini.andrea {_AT_} gmail.com>',
281
     u'Andrea Corbellini <andrea.corbellini {_AT_} beeseek.org>'),
10301.1.8 by Karl Fogel
Clean up the way we do string encoding. No functional change.
282
    )
283
# Then put it in dictionary form with the correct encodings.
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
284
merge_names_map = dict((wiki_encode(a), wiki_encode(b))
285
                       for a, b in merge_names_pairs)
10301.1.8 by Karl Fogel
Clean up the way we do string encoding. No functional change.
286
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
287
288
class ContainerRevision():
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
289
    """A wrapper for a top-level LogRevision containing child LogRevisions."""
290
10456.1.4 by William Grant
Fully support multiple branches -- they will now be linked properly, and their revisions will be labeled.
291
    def __init__(self, top_lr, branch_info):
10456.1.7 by William Grant
Address review comments.
292
        """Create a new ContainerRevision.
293
294
        :param top_lr: The top-level LogRevision.
295
        :param branch_info: The BranchInfo for the containing branch.
296
        """
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
297
        self.top_rev = top_lr       # e.g. LogRevision for r9371.
9373.1.12 by Karl Fogel
* utilities/community-contributions.py: More formatting and
298
        self.contained_revs = []    # e.g. [ {9369.1.1}, {9206.4.4}, ... ],
299
                                    # where "{X}" means "LogRevision for X"
10456.1.4 by William Grant
Fully support multiple branches -- they will now be linked properly, and their revisions will be labeled.
300
        self.branch_info = branch_info
301
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
302
    def add_subrev(self, lr):
303
        """Add a descendant child of this container revision."""
304
        self.contained_revs.append(lr)
305
306
    def __str__(self):
9373.1.12 by Karl Fogel
* utilities/community-contributions.py: More formatting and
307
        timestamp = self.top_rev.rev.timestamp
308
        timezone = self.top_rev.rev.timezone
309
        message = self.top_rev.rev.message or "(NO LOG MESSAGE)"
310
        rev_id = self.top_rev.rev.revision_id or "(NO REVISION ID)"
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
311
        if timestamp:
312
            date_str = format_date(timestamp, timezone or 0, 'original')
313
        else:
314
            date_str = "(NO DATE)"
315
10456.1.4 by William Grant
Fully support multiple branches -- they will now be linked properly, and their revisions will be labeled.
316
        rev_url_base = "http://bazaar.launchpad.net/%s/revision/" % (
10456.1.7 by William Grant
Address review comments.
317
            self.branch_info.loggerhead_path)
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
318
319
        # In loggerhead, you can use either a revision number or a
320
        # revision ID.  In other words, these would reach the same page:
321
        #
322
        # http://bazaar.launchpad.net/~launchpad-pqm/launchpad/devel/\
323
        # revision/9202
324
        #
325
        #   -and-
326
        #
10281.1.2 by Jamal Fanaian
Fixed lint messages regardling line length
327
        # http://bazaar.launchpad.net/~launchpad-pqm/launchpad/devel/\
328
        # revision/launchpad@pqm.canonical.com-20090821221206-\
329
        # ritpv21q8w61gbpt
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
330
        #
331
        # In our links, even when the link text is a revnum, we still
332
        # use a rev-id for the target.  This is both so that the URL will
333
        # still work if you manually tweak it (say to "db-devel" from
334
        # "devel") and so that hovering over a revnum on the wiki page
335
        # will give you some information about it before you click
336
        # (because a rev id often identifies the committer).
337
        rev_id_url = rev_url_base + rev_id
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
338
339
        if len(self.contained_revs) <= 10:
340
            commits_block = "\n ".join(
341
                ["[[%s|%s]]" % (rev_url_base + lr.rev.revision_id, lr.revno)
342
                 for lr in self.contained_revs])
343
        else:
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
344
            commits_block = ("''see the [[%s|full revision]] for details "
345
                             "(it contains %d commits)''"
346
                             % (rev_id_url, len(self.contained_revs)))
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
347
10456.1.7 by William Grant
Address review comments.
348
        name = self.branch_info.name
349
9373.1.13 by Karl Fogel
* utilities/community-contributions.py:
350
        text = [
10456.1.4 by William Grant
Fully support multiple branches -- they will now be linked properly, and their revisions will be labeled.
351
            " * [[%s|r%s%s]] -- %s\n" % (
352
                rev_id_url, self.top_rev.revno,
10456.1.7 by William Grant
Address review comments.
353
                ' (%s)' % name if name else '',
10456.1.4 by William Grant
Fully support multiple branches -- they will now be linked properly, and their revisions will be labeled.
354
                date_str),
9373.1.13 by Karl Fogel
* utilities/community-contributions.py:
355
            " {{{\n%s\n}}}\n" % message,
356
            " '''Commits:'''\n ",
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
357
            commits_block,
9373.1.13 by Karl Fogel
* utilities/community-contributions.py:
358
            "\n",
359
            ]
360
        return ''.join(text)
11057.1.2 by Jonathan Lange
Flakes, space
361
362
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
363
# "ExternalContributor" is too much to type, so I guess we'll just use this.
364
class ExCon():
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
365
    """A contributor to Launchpad from outside Canonical's Launchpad team."""
9373.1.9 by Karl Fogel
* utilities/community-contributions.py: Blank line after class docstrings.
366
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
367
    def __init__(self, name, is_canonical=False):
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
368
        """Create a new external contributor named 'name'.
369
370
        If 'is_canonical' is True, then this is a contributor from
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
371
        within Canonical, but not on the Launchpad team at Canonical.
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
372
        'name' is something like "Veronica Random <vr {_AT_} example.com>".
373
        """
10301.1.3 by Karl Fogel
Disguise email addresses in the source code.
374
        self.name = name
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
375
        self.is_canonical = is_canonical
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
376
        # If name is "Veronica Random <veronica {_AT_} example.com>",
377
        # then name_as_anchor will be "veronica_random".
378
        self.name_as_anchor = \
379
            re.compile("\\s+").sub("_", name.split("<")[0].strip()).lower()
380
        # All the top-level revisions this contributor is associated with
381
        # (key == value == ContainerRevision).  We use a dictionary
382
        # instead of list to get set semantics; set() would be overkill.
9373.1.12 by Karl Fogel
* utilities/community-contributions.py: More formatting and
383
        self._landings = {}
10456.1.6 by William Grant
Comment on the purpose and usage of seen_revs.
384
        # A map of revision IDs authored by this contributor (probably
385
        # not top-level) to a (LogRevision, ContainerRevision) pair. The
386
        # pair contains details of the shallowest found instance of this
387
        # revision.
10456.1.3 by William Grant
Collect the shallowest authored revisions across all branches for each ExCon, only adding their top-level revs once we've seen everything. This gives sane results by ignoring merges from devel->db-devel and db-devel->devel. The main problem now is that db-devel links will point to devel instead.
388
        self.seen_revs = {}
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
389
390
    def num_landings(self):
391
        """Return the number of top-level landings that include revisions
392
        by this contributor."""
393
        return len(self._landings)
394
395
    def add_top_level_revision(self, cr):
9373.1.11 by Karl Fogel
* utilities/community-contributions.py: Stay within 80 columns.
396
        "Record ContainableRevision CR as associated with this contributor."
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
397
        self._landings[cr] = cr
398
399
    def show_contributions(self):
9373.1.11 by Karl Fogel
* utilities/community-contributions.py: Stay within 80 columns.
400
        "Return a wikified string showing this contributor's contributions."
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
401
        plural = "s"
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
402
        name = self.name
403
        if self.is_canonical:
404
            name = name + " (Canonical developer)"
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
405
        if self.num_landings() == 1:
406
            plural = ""
9373.1.13 by Karl Fogel
* utilities/community-contributions.py:
407
        text = [
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
408
            "=== %s ===\n\n" % name,
9373.1.13 by Karl Fogel
* utilities/community-contributions.py:
409
            "''%d top-level landing%s:''\n\n" % (self.num_landings(), plural),
410
            ''.join(map(str, sorted(self._landings,
10456.1.1 by William Grant
Order top-level revs by timestamp, not revno string (this broke when we reached r10000).
411
                                    key=lambda x: x.top_rev.rev.timestamp,
9373.1.13 by Karl Fogel
* utilities/community-contributions.py:
412
                                    reverse=True))),
413
            "\n",
414
            ]
415
        return ''.join(text)
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
416
417
418
def get_ex_cons(authors, all_ex_cons):
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
419
    """Return a list of ExCon objects corresponding to AUTHORS (a list
420
    of strings).  If there are no external contributors in authors,
421
    return an empty list.
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
422
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
423
    ALL_EX_CONS is a dictionary mapping author names (as received from
424
    the bzr logs, i.e., with email address undisguised) to ExCon objects.
425
    """
9373.1.12 by Karl Fogel
* utilities/community-contributions.py: More formatting and
426
    ex_cons_this_rev = []
10301.1.2 by Karl Fogel
* community-contributions.py
427
    for author in authors:
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
428
        known_canonical_lp_dev = False
429
        known_canonical_non_lp_dev = False
10301.1.3 by Karl Fogel
Disguise email addresses in the source code.
430
        # The authors we list in the source code have their addresses
431
        # disguised (since this source code is public).  We must
432
        # disguise the ones coming from the Bazaar logs in the same way,
433
        # so string matches will work.
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
434
        author = wiki_encode(author)
10301.1.3 by Karl Fogel
Disguise email addresses in the source code.
435
        author = author.replace("@", " {_AT_} ")
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
436
437
        # If someone works/worked for Canonical on the Launchpad team,
438
        # then skip them -- we don't want to show them in the output.
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
439
        for name_fragment in known_canonical_lp_devs:
440
            if name_fragment in author:
441
                known_canonical_lp_dev = True
9373.1.12 by Karl Fogel
* utilities/community-contributions.py: More formatting and
442
                break
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
443
        if known_canonical_lp_dev:
444
            continue
445
446
        # Use the merge names map to merge contributions from the same
447
        # person using alternate names and/or emails.
10301.1.5 by Karl Fogel
* community-contributions.py
448
        author = merge_names_map.get(author, author)
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
449
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
450
        if CANONICAL_ADDR in author:
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
451
            known_canonical_non_lp_dev = True
452
        else:
453
            for name_fragment in known_canonical_non_lp_devs:
454
                if name_fragment in author:
455
                    known_canonical_non_lp_dev = True
456
                    break
457
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
458
        # There's a variant of the Singleton pattern that could be
459
        # used for this, whereby instantiating an ExCon object would
460
        # just get back an existing object if such has already been
461
        # instantiated for this name.  But that would make this code
462
        # non-reentrant, and that's just not cool.
463
        ec = all_ex_cons.get(author, None)
464
        if ec is None:
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
465
            ec = ExCon(author, is_canonical=known_canonical_non_lp_dev)
466
            all_ex_cons[author] = ec
467
        ex_cons_this_rev.append(ec)
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
468
    return ex_cons_this_rev
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
469
470
471
# The LogFormatter abstract class should really be called LogReceiver
472
# or something -- subclasses don't have to be about display.
473
class LogExCons(log.LogFormatter):
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
474
    """Log all the external contributions, by Contributor."""
9373.1.9 by Karl Fogel
* utilities/community-contributions.py: Blank line after class docstrings.
475
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
476
    # See log.LogFormatter documentation.
477
    supports_merge_revisions = True
478
479
    def __init__(self):
480
        super(LogExCons, self).__init__(to_file=None)
481
        # Dictionary mapping author names (with undisguised email
482
        # addresses) to ExCon objects.
9373.1.12 by Karl Fogel
* utilities/community-contributions.py: More formatting and
483
        self.all_ex_cons = {}
9373.1.11 by Karl Fogel
* utilities/community-contributions.py: Stay within 80 columns.
484
        # ContainerRevision object representing most-recently-seen
485
        # top-level rev.
10456.1.4 by William Grant
Fully support multiple branches -- they will now be linked properly, and their revisions will be labeled.
486
        self.current_top_level_rev = None
487
        self.branch_info = None
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
488
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
489
    def _toc(self, contributors):
490
        toc_text = []
491
        for val in contributors:
492
            plural = "s"
493
            if val.num_landings() == 1:
494
                plural = ""
495
            toc_text.extend(" 1. [[#%s|%s]] ''(%d top-level landing%s)''\n"
496
                            % (val.name_as_anchor, val.name,
497
                               val.num_landings(), plural))
498
        return toc_text
10456.1.4 by William Grant
Fully support multiple branches -- they will now be linked properly, and their revisions will be labeled.
499
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
500
    def result(self):
9373.1.11 by Karl Fogel
* utilities/community-contributions.py: Stay within 80 columns.
501
        "Return a moin-wiki-syntax string with TOC followed by contributions."
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
502
10456.1.6 by William Grant
Comment on the purpose and usage of seen_revs.
503
        # Go through the shallowest authored revisions and add their
504
        # top level revisions.
10456.1.3 by William Grant
Collect the shallowest authored revisions across all branches for each ExCon, only adding their top-level revs once we've seen everything. This gives sane results by ignoring merges from devel->db-devel and db-devel->devel. The main problem now is that db-devel links will point to devel instead.
505
        for excon in self.all_ex_cons.values():
506
            for rev, top_level_rev in excon.seen_revs.values():
507
                excon.add_top_level_revision(top_level_rev)
508
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
509
        # Divide contributors into non-Canonical and Canonical.
510
        non_canonical_contributors = [x for x in self.all_ex_cons.values()
511
                                      if not x.is_canonical]
512
        canonical_contributors = [x for x in self.all_ex_cons.values()
513
                                      if x.is_canonical]
514
        # Sort them.
515
        non_canonical_contributors = sorted(non_canonical_contributors,
516
                                            key=lambda x: x.num_landings(),
517
                                            reverse=True)
518
        canonical_contributors = sorted(canonical_contributors,
519
                                        key=lambda x: x.num_landings(),
520
                                        reverse=True)
521
9373.1.13 by Karl Fogel
* utilities/community-contributions.py:
522
        text = [
523
            "-----\n\n",
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
524
            "= Who =\n\n"
525
            "== Contributors (from outside Canonical) ==\n\n",
9373.1.13 by Karl Fogel
* utilities/community-contributions.py:
526
            ]
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
527
        text.extend(self._toc(non_canonical_contributors))
528
        text.extend([
529
            "== Contributors (from Canonical, but outside "
530
            "the Launchpad team) ==\n\n",
531
            ])
532
        text.extend(self._toc(canonical_contributors))
9373.1.13 by Karl Fogel
* utilities/community-contributions.py:
533
        text.extend(["\n-----\n\n",
534
                     "= What =\n\n",
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
535
                     "== Contributions (from outside Canonical) ==\n\n",
536
                     ])
537
        for val in non_canonical_contributors:
538
            text.extend("<<Anchor(%s)>>\n" % val.name_as_anchor)
539
            text.extend(val.show_contributions())
540
        text.extend(["== Contributions (from Canonical, but outside "
541
                     "the Launchpad team) ==\n\n",
542
                     ])
543
        for val in canonical_contributors:
9373.1.13 by Karl Fogel
* utilities/community-contributions.py:
544
            text.extend("<<Anchor(%s)>>\n" % val.name_as_anchor)
545
            text.extend(val.show_contributions())
546
        return ''.join(text)
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
547
548
    def log_revision(self, lr):
549
        """Log a revision.
550
        :param  lr:   The LogRevision to be logged.
551
        """
552
        # We count on always seeing the containing rev before its subrevs.
553
        if lr.merge_depth == 0:
10456.1.4 by William Grant
Fully support multiple branches -- they will now be linked properly, and their revisions will be labeled.
554
            self.current_top_level_rev = ContainerRevision(
555
                lr, self.branch_info)
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
556
        else:
557
            self.current_top_level_rev.add_subrev(lr)
558
        ex_cons = get_ex_cons(lr.rev.get_apparent_authors(), self.all_ex_cons)
559
        for ec in ex_cons:
10456.1.6 by William Grant
Comment on the purpose and usage of seen_revs.
560
            # If this is the shallowest sighting of a revision, note it
10456.1.9 by William Grant
Comment on shallowness a little more.
561
            # in the ExCon. We may see the revision at different depths
562
            # in different branches, mostly when one of the trunks is
563
            # merged into the other. We only care about the initial
564
            # merge, which should be shallowest.
10456.1.3 by William Grant
Collect the shallowest authored revisions across all branches for each ExCon, only adding their top-level revs once we've seen everything. This gives sane results by ignoring merges from devel->db-devel and db-devel->devel. The main problem now is that db-devel links will point to devel instead.
565
            if (lr.rev.revision_id not in ec.seen_revs or
10456.1.11 by William Grant
Wrap two long lines.
566
                lr.merge_depth <
567
                    ec.seen_revs[lr.rev.revision_id][0].merge_depth):
568
                ec.seen_revs[lr.rev.revision_id] = (
569
                    lr, self.current_top_level_rev)
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
570
571
10456.1.7 by William Grant
Address review comments.
572
class BranchInfo:
573
    """A collection of information about a branch."""
574
10456.1.13 by William Grant
Remove start_revno support.
575
    def __init__(self, path, loggerhead_path, name=None):
10456.1.7 by William Grant
Address review comments.
576
        """Create a new BranchInfo.
577
578
        :param path: Filesystem path to the branch.
579
        :param loggerhead_path: The path to the branch on Launchpad's
580
            Loggerhead instance.
581
        :param name: Optional name to identify the branch's revisions in the
582
            produced document.
583
        """
584
        self.path = path
585
        self.name = name
586
        self.loggerhead_path = loggerhead_path
587
588
9373.1.15 by Karl Fogel
* utilities/community-contributions.py: Add name to "XXX" comments, as
589
# XXX: Karl Fogel 2009-09-10: is this really necessary?  See bzrlib/log.py.
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
590
log.log_formatter_registry.register('external_contributors', LogExCons,
591
                                    'Find non-Canonical contributors.')
592
593
594
def usage():
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
595
    print __doc__
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
596
597
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
598
# Use backslashes to suppress newlines because this is wiki syntax,
599
# not HTML, so newlines would be rendered as line breaks.
9373.1.14 by Karl Fogel
* utilities/community-contributions.py (page_intro): Format source
600
page_intro = """This page shows contributions to Launchpad from \
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
601
developers not on the Launchpad team at Canonical.
602
10456.1.5 by William Grant
Fix obsolete comments, and add a couple more.
603
It lists all changes that have landed in the Launchpad ''devel'' \
604
or ''db-devel'' trees (see the [[Trunk|trunk explanation]] for more).
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
605
9373.1.14 by Karl Fogel
* utilities/community-contributions.py (page_intro): Format source
606
~-''Note for maintainers: this page is updated every 10 minutes by a \
607
cron job running as kfogel on devpad (though if there are no new \
608
contributions, the page's timestamp won't change).  The code that \
609
generates this page is \
610
[[http://bazaar.launchpad.net/%7Elaunchpad-pqm/launchpad/devel/annotate/head%3A/utilities/community-contributions.py|utilities/community-contributions.py]] \
611
in the Launchpad tree.''-~
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
612
613
"""
614
615
def main():
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
616
    quiet = False
617
    dry_run = False
10456.1.10 by William Grant
Take devel and db-devel paths as options instead of arguments, to make ordering more obvious.
618
    devel_path = None
619
    db_devel_path = None
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
620
10301.1.1 by Karl Fogel
* community-contributions.py
621
    wiki_dest = "https://dev.launchpad.net/Contributions"
622
10456.1.4 by William Grant
Fully support multiple branches -- they will now be linked properly, and their revisions will be labeled.
623
    if len(sys.argv) < 3:
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
624
        usage()
625
        sys.exit(1)
626
627
    try:
628
        opts, args = getopt.getopt(sys.argv[1:], '?hq',
10456.1.10 by William Grant
Take devel and db-devel paths as options instead of arguments, to make ordering more obvious.
629
                                   ['help', 'usage', 'dry-run', 'draft-run',
630
                                    'devel=', 'db-devel='])
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
631
    except getopt.GetoptError, e:
632
        sys.stderr.write("ERROR: " + str(e) + '\n\n')
633
        usage()
634
        sys.exit(1)
635
636
    for opt, value in opts:
637
        if opt == '--help' or opt == '-h' or opt == '-?' or opt == 'usage':
638
            usage()
639
            sys.exit(0)
640
        elif opt == '-q' or opt == '--quiet':
641
            quiet = True
642
        elif opt == '--dry-run':
643
            dry_run = True
10301.1.1 by Karl Fogel
* community-contributions.py
644
        elif opt == '--draft-run':
645
            wiki_dest += "/Draft"
10456.1.10 by William Grant
Take devel and db-devel paths as options instead of arguments, to make ordering more obvious.
646
        elif opt == '--devel':
647
            devel_path = value
648
        elif opt == '--db-devel':
649
            db_devel_path = value
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
650
651
    # Ensure we have the arguments we need.
10456.1.10 by William Grant
Take devel and db-devel paths as options instead of arguments, to make ordering more obvious.
652
    if not devel_path or not db_devel_path:
10456.1.4 by William Grant
Fully support multiple branches -- they will now be linked properly, and their revisions will be labeled.
653
        sys.stderr.write("ERROR: paths to Launchpad devel and db-devel "
10456.1.10 by William Grant
Take devel and db-devel paths as options instead of arguments, to make ordering more obvious.
654
                         "branches required as options\n")
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
655
        usage()
656
        sys.exit(1)
657
10456.1.7 by William Grant
Address review comments.
658
    branches = (
659
        BranchInfo(
10456.1.13 by William Grant
Remove start_revno support.
660
            devel_path, '~launchpad-pqm/launchpad/devel'),
10456.1.7 by William Grant
Address review comments.
661
        BranchInfo(
10456.1.13 by William Grant
Remove start_revno support.
662
            db_devel_path, '~launchpad-pqm/launchpad/db-devel', 'db-devel'),
10456.1.7 by William Grant
Address review comments.
663
        )
10456.1.4 by William Grant
Fully support multiple branches -- they will now be linked properly, and their revisions will be labeled.
664
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
665
    lec = LogExCons()
10456.1.2 by William Grant
Take multiple branches, and only count each authored revision once.
666
10456.1.7 by William Grant
Address review comments.
667
    for branch_info in branches:
10456.1.2 by William Grant
Take multiple branches, and only count each authored revision once.
668
        # Do everything.
10456.1.7 by William Grant
Address review comments.
669
        b = Branch.open(branch_info.path)
10456.1.2 by William Grant
Take multiple branches, and only count each authored revision once.
670
10456.1.13 by William Grant
Remove start_revno support.
671
        logger = log.Logger(b, {'direction' : 'reverse',
10456.1.2 by William Grant
Take multiple branches, and only count each authored revision once.
672
                                'levels' : 0, })
673
        if not quiet:
674
            print "Calculating (this may take a while)..."
10456.1.5 by William Grant
Fix obsolete comments, and add a couple more.
675
676
        # Set information about the current branch for later formatting.
10456.1.4 by William Grant
Fully support multiple branches -- they will now be linked properly, and their revisions will be labeled.
677
        lec.branch_info = branch_info
10456.1.2 by William Grant
Take multiple branches, and only count each authored revision once.
678
        logger.show(lec)  # Won't "show" anything -- just gathers data.
679
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
680
    page_contents = page_intro + lec.result()
681
    def update_if_modified(moinfile):
682
        if moinfile._unescape(moinfile.body) == page_contents:
683
            return 0  # Nothing changed, so cancel the edit.
684
        else:
685
            moinfile.body = page_contents
686
            return 1
687
    if not dry_run:
688
        if not quiet:
689
            print "Updating wiki..."
690
        # Not sure how to get editmoin to obey our quiet flag.
10301.1.1 by Karl Fogel
* community-contributions.py
691
        editshortcut(wiki_dest, editfile_func=update_if_modified)
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
692
        if not quiet:
693
            print "Done updating wiki."
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
694
    else:
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
695
        print page_contents
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
696
697
698
if __name__ == '__main__':
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
699
    main()