~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',
13531.1.2 by William Grant
Update community-contributions.py's name maps.
145
                              u'Huw Wilkins',
11728.1.1 by William Grant
Update community-contributions.py's list Launchpad and Canonical developers, and add some more email merges.
146
                              u'Ian Booth',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
147
                              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.
148
                              u'j.c.sackett',
149
                              u'jc',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
150
                              u'Jelmer Vernooij',
151
                              u'Jeroen Vermeulen',
152
                              u'Jeroen T. Vermeulen',
153
                              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.
154
                              u'Jon Sackett',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
155
                              u'Jonathan Lange',
11702.2.2 by Brian Murray
j.c.sackett works on Launchpad
156
                              u'j.c.sackett',
157
                              u'jonathan.sackett {_AT_} canonical.com',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
158
                              u'jml {_AT_} canonical.com',
159
                              u'jml {_AT_} mumak.net',
160
                              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.
161
                              u'jonathan.knowles {_AT_} canonical.com',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
162
                              u'Julian Edwards',
163
                              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.
164
                              u'Launch Pad',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
165
                              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.
166
                              u'Launchpad Developers',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
167
                              u'Launchpad Patch Queue Manager',
168
                              u'Launchpad PQM Bot',
169
                              u'Leonard Richardson',
170
                              u'Malcolm Cleaton',
171
                              u'Maris Fogels',
172
                              u'Mark Shuttleworth',
173
                              u'Martin Albisetti',
174
                              u'Matt Zimmerman',
175
                              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.
176
                              u'Matthew Thomas',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
177
                              u'Matthew Revell',
178
                              u'matthew.revell {_AT_} canonical.com',
179
                              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.
180
                              u'michael.hudson {_AT_} canonical.com',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
181
                              u'Michael Nelson',
182
                              u'Muharem Hrnjadovic',
183
                              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.
184
                              u'Patch Queue Manager',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
185
                              u'Paul Hummer',
13531.1.2 by William Grant
Update community-contributions.py's name maps.
186
                              u'Raphael Badin',
187
                              u'Raphaël Badin',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
188
                              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.
189
                              u'root <root {_AT_} ubuntu>',
13531.1.2 by William Grant
Update community-contributions.py's name maps.
190
                              u'rvb',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
191
                              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.
192
                              u'Steve Alexander',
11057.1.1 by Jonathan Lange
Correct some bugs with the Launchpad data
193
                              u'Steve Kowalik',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
194
                              u'Steve McInerney',
195
                              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.
196
                              u'test {_AT_} canonical.com',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
197
                              u'Tom Haddon',
198
                              u'Tim Penhey',
199
                              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.
200
                              u'ubuntu <ubuntu {_AT_} lp-dev>',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
201
                              u'Ursula Junque',
13531.1.2 by William Grant
Update community-contributions.py's name maps.
202
                              u'William Grant <william.grant {_AT_} canonical.com>',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
203
                              )]
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
204
205
# People known to work for Canonical but not on the Launchpad team.
206
# Anyone with "@canonical.com" in their email address is considered to
207
# work for Canonical, but some people occasionally submit changes from
208
# their personal email addresses; this list contains people known to
209
# do that, so we can treat them appropriately in the output.
210
known_canonical_non_lp_devs = \
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
211
    [wiki_encode(x) for x in (u'Adam Conrad',
212
                              u'Andrew Bennetts',
213
                              u'Anthony Lenton',
214
                              u'Cody Somerville',
215
                              u'Cody A.W. Somerville',
216
                              u'David Murphy',
11057.1.1 by Jonathan Lange
Correct some bugs with the Launchpad data
217
                              u'Didier Roche',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
218
                              u'Elliot Murphy',
219
                              u'Gabriel Neuman gneuman {_AT_} async.com',
220
                              u'Gustavo Niemeyer',
221
                              u'James Henstridge',
11057.1.1 by Jonathan Lange
Correct some bugs with the Launchpad data
222
                              u'James Westby',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
223
                              u'John Lenton',
224
                              u'Kees Cook',
225
                              u'LaMont Jones',
13531.1.2 by William Grant
Update community-contributions.py's name maps.
226
                              u'Loïc Minier',
11057.1.1 by Jonathan Lange
Correct some bugs with the Launchpad data
227
                              u'Martin Pitt',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
228
                              u'Martin Pool',
229
                              u'Matt Zimmerman',
13531.1.2 by William Grant
Update community-contributions.py's name maps.
230
                              u'mbp {_AT_} sourcefrog.net',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
231
                              u'Michael Casadevall',
232
                              u'Michael Vogt',
233
                              u'Sidnei da Silva',
10667.1.1 by Karl Fogel
* utilities/community-contributions.py
234
                              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.
235
                              u'John Arbash Meinel',
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
236
                              )]
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
237
11057.1.2 by Jonathan Lange
Flakes, space
238
# 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.
239
# 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.
240
# The map is initialized from this list of pairs, where each pair is
241
# of the form (CONTRIBUTOR_AS_SEEN, UNIFYING_IDENTITY_FOR_CONTRIBUTOR).
242
merge_names_pairs = (
243
    (u'Jamal Fanaian <jfanaian {_AT_} gmail.com>',
244
     u'Jamal Fanaian <jamal.fanaian {_AT_} gmail.com>'),
245
    (u'Jamal Fanaian <jamal {_AT_} jfvm1>',
246
     u'Jamal Fanaian <jamal.fanaian {_AT_} gmail.com>'),
247
    (u'LaMont Jones <lamont {_AT_} rover3>',
248
     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.
249
    (u'Sidnei <sidnei {_AT_} ubuntu>',
250
     u'Sidnei da Silva <sidnei.da.silva {_AT_} canonical.com>'),
251
    (u'Sidnei da Silva <sidnei.da.silva {_AT_} gmail.com>',
252
     u'Sidnei da Silva <sidnei.da.silva {_AT_} canonical.com>'),
253
    (u'Sidnei da Silva <sidnei {_AT_} canonical.com>',
254
     u'Sidnei da Silva <sidnei.da.silva {_AT_} canonical.com>'),
255
    (u'Adam Conrad <adconrad {_AT_} ziggup>',
256
     u'Adam Conrad <adconrad {_AT_} 0c3.net>'),
257
    (u'Elliot Murphy <elliot {_AT_} elliotmurphy.com>',
258
     u'Elliot Murphy <elliot {_AT_} canonical.com>'),
259
    (u'Elliot Murphy <elliot.murphy {_AT_} canonical.com>',
260
     u'Elliot Murphy <elliot {_AT_} canonical.com>'),
261
    (u'Cody Somerville <cody-somerville {_AT_} mercurial>',
262
     u'Cody A.W. Somerville <cody.somerville {_AT_} canonical.com>'),
263
    (u'Adam Conrad <adconrad {_AT_} chinstrap>',
264
     u'Adam Conrad <adconrad {_AT_} 0c3.net>'),
265
    (u'Adam Conrad <adconrad {_AT_} cthulhu>',
266
     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.
267
    (u'James Westby <james.westby {_AT_} linaro.org>',
13531.1.2 by William Grant
Update community-contributions.py's name maps.
268
     u'James Westby <james.westby {_AT_} canonical.com>'),
11728.1.1 by William Grant
Update community-contributions.py's list Launchpad and Canonical developers, and add some more email merges.
269
    (u'Bryce Harrington <bryce {_AT_} canonical.com>',
270
     u'Bryce Harrington <bryce.harrington {_AT_} canonical.com>'),
271
    (u'Dustin Kirkland <kirkland {_AT_} x200>',
272
     u'Dustin Kirkland <kirkland {_AT_} canonical.com>'),
273
    (u'Anthony Lenton <antoniolenton {_AT_} gmail.com>',
274
     u'Anthony Lenton <anthony.lenton {_AT_} canonical.com>'),
275
    (u'Steve Kowalik <steven {_AT_} quelled>',
276
     u'Steve Kowalik <steve.kowalik {_AT_} canonical.com>'),
277
    (u'Steve Kowalik <stevenk {_AT_} ubuntu.com>',
278
     u'Steve Kowalik <steve.kowalik {_AT_} canonical.com>'),
279
    (u'jc <jc {_AT_} launchpad>',
280
     u'j.c.sackett <jonathan.sackett {_AT_} canonical.com>'),
281
    (u'Jon Sackett <jc {_AT_} jabberwocky>',
282
     u'j.c.sackett <jonathan.sackett {_AT_} canonical.com>'),
283
    (u'John Arbash Meinel <jameinel {_AT_} falco-lucid>',
284
     u'John Arbash Meinel <john {_AT_} arbash-meinel.com>'),
285
    (u'Martin Pool <mbp {_AT_} sourcefrog.net>',
286
     u'Martin Pool <mbp {_AT_} canonical.com>'),
13531.1.2 by William Grant
Update community-contributions.py's name maps.
287
    (u'mbp {_AT_} sourcefrog.net',
288
     u'Martin Pool <mbp {_AT_} canonical.com>'),
289
    (u'mbp {_AT_} canonical.com',
290
     u'Martin Pool <mbp {_AT_} canonical.com>'),
11728.1.2 by William Grant
Add another email mapping.
291
    (u'Andrea Corbellini <corbellini.andrea {_AT_} gmail.com>',
292
     u'Andrea Corbellini <andrea.corbellini {_AT_} beeseek.org>'),
13531.1.2 by William Grant
Update community-contributions.py's name maps.
293
    (u'Luke Faraone <luke {_AT_} faraone.cc',
294
     u'Luke Faraone <luke {_AT_} faraone.cc>'),
10301.1.8 by Karl Fogel
Clean up the way we do string encoding. No functional change.
295
    )
296
# Then put it in dictionary form with the correct encodings.
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
297
merge_names_map = dict((wiki_encode(a), wiki_encode(b))
298
                       for a, b in merge_names_pairs)
10301.1.8 by Karl Fogel
Clean up the way we do string encoding. No functional change.
299
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
300
301
class ContainerRevision():
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
302
    """A wrapper for a top-level LogRevision containing child LogRevisions."""
303
10456.1.4 by William Grant
Fully support multiple branches -- they will now be linked properly, and their revisions will be labeled.
304
    def __init__(self, top_lr, branch_info):
10456.1.7 by William Grant
Address review comments.
305
        """Create a new ContainerRevision.
306
307
        :param top_lr: The top-level LogRevision.
308
        :param branch_info: The BranchInfo for the containing branch.
309
        """
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
310
        self.top_rev = top_lr       # e.g. LogRevision for r9371.
9373.1.12 by Karl Fogel
* utilities/community-contributions.py: More formatting and
311
        self.contained_revs = []    # e.g. [ {9369.1.1}, {9206.4.4}, ... ],
312
                                    # 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.
313
        self.branch_info = branch_info
314
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
315
    def add_subrev(self, lr):
316
        """Add a descendant child of this container revision."""
317
        self.contained_revs.append(lr)
318
319
    def __str__(self):
9373.1.12 by Karl Fogel
* utilities/community-contributions.py: More formatting and
320
        timestamp = self.top_rev.rev.timestamp
321
        timezone = self.top_rev.rev.timezone
322
        message = self.top_rev.rev.message or "(NO LOG MESSAGE)"
323
        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,
324
        if timestamp:
325
            date_str = format_date(timestamp, timezone or 0, 'original')
326
        else:
327
            date_str = "(NO DATE)"
328
10456.1.4 by William Grant
Fully support multiple branches -- they will now be linked properly, and their revisions will be labeled.
329
        rev_url_base = "http://bazaar.launchpad.net/%s/revision/" % (
10456.1.7 by William Grant
Address review comments.
330
            self.branch_info.loggerhead_path)
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
331
332
        # In loggerhead, you can use either a revision number or a
333
        # revision ID.  In other words, these would reach the same page:
334
        #
335
        # http://bazaar.launchpad.net/~launchpad-pqm/launchpad/devel/\
336
        # revision/9202
337
        #
338
        #   -and-
339
        #
10281.1.2 by Jamal Fanaian
Fixed lint messages regardling line length
340
        # http://bazaar.launchpad.net/~launchpad-pqm/launchpad/devel/\
341
        # revision/launchpad@pqm.canonical.com-20090821221206-\
342
        # ritpv21q8w61gbpt
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
343
        #
344
        # In our links, even when the link text is a revnum, we still
345
        # use a rev-id for the target.  This is both so that the URL will
346
        # still work if you manually tweak it (say to "db-devel" from
347
        # "devel") and so that hovering over a revnum on the wiki page
348
        # will give you some information about it before you click
349
        # (because a rev id often identifies the committer).
350
        rev_id_url = rev_url_base + rev_id
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
351
352
        if len(self.contained_revs) <= 10:
353
            commits_block = "\n ".join(
354
                ["[[%s|%s]]" % (rev_url_base + lr.rev.revision_id, lr.revno)
355
                 for lr in self.contained_revs])
356
        else:
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
357
            commits_block = ("''see the [[%s|full revision]] for details "
358
                             "(it contains %d commits)''"
359
                             % (rev_id_url, len(self.contained_revs)))
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
360
10456.1.7 by William Grant
Address review comments.
361
        name = self.branch_info.name
362
9373.1.13 by Karl Fogel
* utilities/community-contributions.py:
363
        text = [
10456.1.4 by William Grant
Fully support multiple branches -- they will now be linked properly, and their revisions will be labeled.
364
            " * [[%s|r%s%s]] -- %s\n" % (
365
                rev_id_url, self.top_rev.revno,
13531.1.1 by William Grant
community-contributions.py no longer blows up on Unicode names or messages.
366
                ' (%s)' % name.encode('utf-8') 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.
367
                date_str),
13531.1.1 by William Grant
community-contributions.py no longer blows up on Unicode names or messages.
368
            " {{{\n%s\n}}}\n" % message.encode('utf-8'),
9373.1.13 by Karl Fogel
* utilities/community-contributions.py:
369
            " '''Commits:'''\n ",
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
370
            commits_block,
9373.1.13 by Karl Fogel
* utilities/community-contributions.py:
371
            "\n",
372
            ]
373
        return ''.join(text)
11057.1.2 by Jonathan Lange
Flakes, space
374
375
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
376
# "ExternalContributor" is too much to type, so I guess we'll just use this.
377
class ExCon():
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
378
    """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.
379
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
380
    def __init__(self, name, is_canonical=False):
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
381
        """Create a new external contributor named 'name'.
382
383
        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.
384
        within Canonical, but not on the Launchpad team at Canonical.
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
385
        'name' is something like "Veronica Random <vr {_AT_} example.com>".
386
        """
10301.1.3 by Karl Fogel
Disguise email addresses in the source code.
387
        self.name = name
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
388
        self.is_canonical = is_canonical
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
389
        # If name is "Veronica Random <veronica {_AT_} example.com>",
390
        # then name_as_anchor will be "veronica_random".
391
        self.name_as_anchor = \
392
            re.compile("\\s+").sub("_", name.split("<")[0].strip()).lower()
393
        # All the top-level revisions this contributor is associated with
394
        # (key == value == ContainerRevision).  We use a dictionary
395
        # instead of list to get set semantics; set() would be overkill.
9373.1.12 by Karl Fogel
* utilities/community-contributions.py: More formatting and
396
        self._landings = {}
10456.1.6 by William Grant
Comment on the purpose and usage of seen_revs.
397
        # A map of revision IDs authored by this contributor (probably
398
        # not top-level) to a (LogRevision, ContainerRevision) pair. The
399
        # pair contains details of the shallowest found instance of this
400
        # 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.
401
        self.seen_revs = {}
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
402
403
    def num_landings(self):
404
        """Return the number of top-level landings that include revisions
405
        by this contributor."""
406
        return len(self._landings)
407
408
    def add_top_level_revision(self, cr):
9373.1.11 by Karl Fogel
* utilities/community-contributions.py: Stay within 80 columns.
409
        "Record ContainableRevision CR as associated with this contributor."
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
410
        self._landings[cr] = cr
411
412
    def show_contributions(self):
9373.1.11 by Karl Fogel
* utilities/community-contributions.py: Stay within 80 columns.
413
        "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,
414
        plural = "s"
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
415
        name = self.name
416
        if self.is_canonical:
417
            name = name + " (Canonical developer)"
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
418
        if self.num_landings() == 1:
419
            plural = ""
9373.1.13 by Karl Fogel
* utilities/community-contributions.py:
420
        text = [
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
421
            "=== %s ===\n\n" % name,
9373.1.13 by Karl Fogel
* utilities/community-contributions.py:
422
            "''%d top-level landing%s:''\n\n" % (self.num_landings(), plural),
423
            ''.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).
424
                                    key=lambda x: x.top_rev.rev.timestamp,
9373.1.13 by Karl Fogel
* utilities/community-contributions.py:
425
                                    reverse=True))),
426
            "\n",
427
            ]
428
        return ''.join(text)
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
429
430
431
def get_ex_cons(authors, all_ex_cons):
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
432
    """Return a list of ExCon objects corresponding to AUTHORS (a list
433
    of strings).  If there are no external contributors in authors,
434
    return an empty list.
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
435
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
436
    ALL_EX_CONS is a dictionary mapping author names (as received from
437
    the bzr logs, i.e., with email address undisguised) to ExCon objects.
438
    """
9373.1.12 by Karl Fogel
* utilities/community-contributions.py: More formatting and
439
    ex_cons_this_rev = []
10301.1.2 by Karl Fogel
* community-contributions.py
440
    for author in authors:
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
441
        known_canonical_lp_dev = False
442
        known_canonical_non_lp_dev = False
10301.1.3 by Karl Fogel
Disguise email addresses in the source code.
443
        # The authors we list in the source code have their addresses
444
        # disguised (since this source code is public).  We must
445
        # disguise the ones coming from the Bazaar logs in the same way,
446
        # so string matches will work.
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
447
        author = wiki_encode(author)
10301.1.3 by Karl Fogel
Disguise email addresses in the source code.
448
        author = author.replace("@", " {_AT_} ")
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
449
450
        # If someone works/worked for Canonical on the Launchpad team,
451
        # 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.
452
        for name_fragment in known_canonical_lp_devs:
453
            if name_fragment in author:
454
                known_canonical_lp_dev = True
9373.1.12 by Karl Fogel
* utilities/community-contributions.py: More formatting and
455
                break
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
456
        if known_canonical_lp_dev:
457
            continue
458
459
        # Use the merge names map to merge contributions from the same
460
        # person using alternate names and/or emails.
10301.1.5 by Karl Fogel
* community-contributions.py
461
        author = merge_names_map.get(author, author)
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
462
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
463
        if CANONICAL_ADDR in author:
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
464
            known_canonical_non_lp_dev = True
465
        else:
466
            for name_fragment in known_canonical_non_lp_devs:
467
                if name_fragment in author:
468
                    known_canonical_non_lp_dev = True
469
                    break
470
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
471
        # There's a variant of the Singleton pattern that could be
472
        # used for this, whereby instantiating an ExCon object would
473
        # just get back an existing object if such has already been
474
        # instantiated for this name.  But that would make this code
475
        # non-reentrant, and that's just not cool.
476
        ec = all_ex_cons.get(author, None)
477
        if ec is None:
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
478
            ec = ExCon(author, is_canonical=known_canonical_non_lp_dev)
479
            all_ex_cons[author] = ec
480
        ex_cons_this_rev.append(ec)
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
481
    return ex_cons_this_rev
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
482
483
484
# The LogFormatter abstract class should really be called LogReceiver
485
# or something -- subclasses don't have to be about display.
486
class LogExCons(log.LogFormatter):
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
487
    """Log all the external contributions, by Contributor."""
9373.1.9 by Karl Fogel
* utilities/community-contributions.py: Blank line after class docstrings.
488
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
489
    # See log.LogFormatter documentation.
490
    supports_merge_revisions = True
491
492
    def __init__(self):
493
        super(LogExCons, self).__init__(to_file=None)
494
        # Dictionary mapping author names (with undisguised email
495
        # addresses) to ExCon objects.
9373.1.12 by Karl Fogel
* utilities/community-contributions.py: More formatting and
496
        self.all_ex_cons = {}
9373.1.11 by Karl Fogel
* utilities/community-contributions.py: Stay within 80 columns.
497
        # ContainerRevision object representing most-recently-seen
498
        # 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.
499
        self.current_top_level_rev = None
500
        self.branch_info = None
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
501
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
502
    def _toc(self, contributors):
503
        toc_text = []
504
        for val in contributors:
505
            plural = "s"
506
            if val.num_landings() == 1:
507
                plural = ""
508
            toc_text.extend(" 1. [[#%s|%s]] ''(%d top-level landing%s)''\n"
509
                            % (val.name_as_anchor, val.name,
510
                               val.num_landings(), plural))
511
        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.
512
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
513
    def result(self):
9373.1.11 by Karl Fogel
* utilities/community-contributions.py: Stay within 80 columns.
514
        "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.
515
10456.1.6 by William Grant
Comment on the purpose and usage of seen_revs.
516
        # Go through the shallowest authored revisions and add their
517
        # 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.
518
        for excon in self.all_ex_cons.values():
519
            for rev, top_level_rev in excon.seen_revs.values():
520
                excon.add_top_level_revision(top_level_rev)
521
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
522
        # Divide contributors into non-Canonical and Canonical.
523
        non_canonical_contributors = [x for x in self.all_ex_cons.values()
524
                                      if not x.is_canonical]
525
        canonical_contributors = [x for x in self.all_ex_cons.values()
526
                                      if x.is_canonical]
527
        # Sort them.
528
        non_canonical_contributors = sorted(non_canonical_contributors,
529
                                            key=lambda x: x.num_landings(),
530
                                            reverse=True)
531
        canonical_contributors = sorted(canonical_contributors,
532
                                        key=lambda x: x.num_landings(),
533
                                        reverse=True)
534
9373.1.13 by Karl Fogel
* utilities/community-contributions.py:
535
        text = [
536
            "-----\n\n",
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
537
            "= Who =\n\n"
538
            "== Contributors (from outside Canonical) ==\n\n",
9373.1.13 by Karl Fogel
* utilities/community-contributions.py:
539
            ]
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
540
        text.extend(self._toc(non_canonical_contributors))
541
        text.extend([
542
            "== Contributors (from Canonical, but outside "
543
            "the Launchpad team) ==\n\n",
544
            ])
545
        text.extend(self._toc(canonical_contributors))
9373.1.13 by Karl Fogel
* utilities/community-contributions.py:
546
        text.extend(["\n-----\n\n",
547
                     "= What =\n\n",
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
548
                     "== Contributions (from outside Canonical) ==\n\n",
549
                     ])
550
        for val in non_canonical_contributors:
551
            text.extend("<<Anchor(%s)>>\n" % val.name_as_anchor)
552
            text.extend(val.show_contributions())
553
        text.extend(["== Contributions (from Canonical, but outside "
554
                     "the Launchpad team) ==\n\n",
555
                     ])
556
        for val in canonical_contributors:
9373.1.13 by Karl Fogel
* utilities/community-contributions.py:
557
            text.extend("<<Anchor(%s)>>\n" % val.name_as_anchor)
558
            text.extend(val.show_contributions())
559
        return ''.join(text)
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
560
561
    def log_revision(self, lr):
562
        """Log a revision.
563
        :param  lr:   The LogRevision to be logged.
564
        """
565
        # We count on always seeing the containing rev before its subrevs.
566
        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.
567
            self.current_top_level_rev = ContainerRevision(
568
                lr, self.branch_info)
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
569
        else:
570
            self.current_top_level_rev.add_subrev(lr)
571
        ex_cons = get_ex_cons(lr.rev.get_apparent_authors(), self.all_ex_cons)
572
        for ec in ex_cons:
10456.1.6 by William Grant
Comment on the purpose and usage of seen_revs.
573
            # If this is the shallowest sighting of a revision, note it
10456.1.9 by William Grant
Comment on shallowness a little more.
574
            # in the ExCon. We may see the revision at different depths
575
            # in different branches, mostly when one of the trunks is
576
            # merged into the other. We only care about the initial
577
            # 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.
578
            if (lr.rev.revision_id not in ec.seen_revs or
10456.1.11 by William Grant
Wrap two long lines.
579
                lr.merge_depth <
580
                    ec.seen_revs[lr.rev.revision_id][0].merge_depth):
581
                ec.seen_revs[lr.rev.revision_id] = (
582
                    lr, self.current_top_level_rev)
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
583
584
10456.1.7 by William Grant
Address review comments.
585
class BranchInfo:
586
    """A collection of information about a branch."""
587
10456.1.13 by William Grant
Remove start_revno support.
588
    def __init__(self, path, loggerhead_path, name=None):
10456.1.7 by William Grant
Address review comments.
589
        """Create a new BranchInfo.
590
591
        :param path: Filesystem path to the branch.
592
        :param loggerhead_path: The path to the branch on Launchpad's
593
            Loggerhead instance.
594
        :param name: Optional name to identify the branch's revisions in the
595
            produced document.
596
        """
597
        self.path = path
598
        self.name = name
599
        self.loggerhead_path = loggerhead_path
600
601
9373.1.15 by Karl Fogel
* utilities/community-contributions.py: Add name to "XXX" comments, as
602
# 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
603
log.log_formatter_registry.register('external_contributors', LogExCons,
604
                                    'Find non-Canonical contributors.')
605
606
607
def usage():
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
608
    print __doc__
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
609
610
10301.1.13 by Karl Fogel
Various tweaks, based on Jonathan Lange's review.
611
# Use backslashes to suppress newlines because this is wiki syntax,
612
# not HTML, so newlines would be rendered as line breaks.
9373.1.14 by Karl Fogel
* utilities/community-contributions.py (page_intro): Format source
613
page_intro = """This page shows contributions to Launchpad from \
10301.1.4 by Karl Fogel
Show Canonical contributors from outside the Launchpad team.
614
developers not on the Launchpad team at Canonical.
615
10456.1.5 by William Grant
Fix obsolete comments, and add a couple more.
616
It lists all changes that have landed in the Launchpad ''devel'' \
617
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
618
13541.2.1 by William Grant
kfogel no longer runs community-contributions.py. I do.
619
~-''Note for maintainers: this page is updated every hour by a \
620
cron job running as wgrant on devpad (though if there are no new \
9373.1.14 by Karl Fogel
* utilities/community-contributions.py (page_intro): Format source
621
contributions, the page's timestamp won't change).  The code that \
622
generates this page is \
623
[[http://bazaar.launchpad.net/%7Elaunchpad-pqm/launchpad/devel/annotate/head%3A/utilities/community-contributions.py|utilities/community-contributions.py]] \
624
in the Launchpad tree.''-~
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
625
626
"""
627
628
def main():
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
629
    quiet = False
630
    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.
631
    devel_path = None
632
    db_devel_path = None
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
633
10301.1.1 by Karl Fogel
* community-contributions.py
634
    wiki_dest = "https://dev.launchpad.net/Contributions"
635
10456.1.4 by William Grant
Fully support multiple branches -- they will now be linked properly, and their revisions will be labeled.
636
    if len(sys.argv) < 3:
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
637
        usage()
638
        sys.exit(1)
639
640
    try:
641
        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.
642
                                   ['help', 'usage', 'dry-run', 'draft-run',
643
                                    'devel=', 'db-devel='])
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
644
    except getopt.GetoptError, e:
645
        sys.stderr.write("ERROR: " + str(e) + '\n\n')
646
        usage()
647
        sys.exit(1)
648
649
    for opt, value in opts:
650
        if opt == '--help' or opt == '-h' or opt == '-?' or opt == 'usage':
651
            usage()
652
            sys.exit(0)
653
        elif opt == '-q' or opt == '--quiet':
654
            quiet = True
655
        elif opt == '--dry-run':
656
            dry_run = True
10301.1.1 by Karl Fogel
* community-contributions.py
657
        elif opt == '--draft-run':
658
            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.
659
        elif opt == '--devel':
660
            devel_path = value
661
        elif opt == '--db-devel':
662
            db_devel_path = value
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
663
664
    # 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.
665
    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.
666
        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.
667
                         "branches required as options\n")
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
668
        usage()
669
        sys.exit(1)
670
10456.1.7 by William Grant
Address review comments.
671
    branches = (
672
        BranchInfo(
10456.1.13 by William Grant
Remove start_revno support.
673
            devel_path, '~launchpad-pqm/launchpad/devel'),
10456.1.7 by William Grant
Address review comments.
674
        BranchInfo(
10456.1.13 by William Grant
Remove start_revno support.
675
            db_devel_path, '~launchpad-pqm/launchpad/db-devel', 'db-devel'),
10456.1.7 by William Grant
Address review comments.
676
        )
10456.1.4 by William Grant
Fully support multiple branches -- they will now be linked properly, and their revisions will be labeled.
677
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
678
    lec = LogExCons()
10456.1.2 by William Grant
Take multiple branches, and only count each authored revision once.
679
10456.1.7 by William Grant
Address review comments.
680
    for branch_info in branches:
10456.1.2 by William Grant
Take multiple branches, and only count each authored revision once.
681
        # Do everything.
10456.1.7 by William Grant
Address review comments.
682
        b = Branch.open(branch_info.path)
10456.1.2 by William Grant
Take multiple branches, and only count each authored revision once.
683
10456.1.13 by William Grant
Remove start_revno support.
684
        logger = log.Logger(b, {'direction' : 'reverse',
10456.1.2 by William Grant
Take multiple branches, and only count each authored revision once.
685
                                'levels' : 0, })
686
        if not quiet:
687
            print "Calculating (this may take a while)..."
10456.1.5 by William Grant
Fix obsolete comments, and add a couple more.
688
689
        # 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.
690
        lec.branch_info = branch_info
10456.1.2 by William Grant
Take multiple branches, and only count each authored revision once.
691
        logger.show(lec)  # Won't "show" anything -- just gathers data.
692
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
693
    page_contents = page_intro + lec.result()
694
    def update_if_modified(moinfile):
695
        if moinfile._unescape(moinfile.body) == page_contents:
696
            return 0  # Nothing changed, so cancel the edit.
697
        else:
698
            moinfile.body = page_contents
699
            return 1
700
    if not dry_run:
701
        if not quiet:
702
            print "Updating wiki..."
703
        # Not sure how to get editmoin to obey our quiet flag.
10301.1.1 by Karl Fogel
* community-contributions.py
704
        editshortcut(wiki_dest, editfile_func=update_if_modified)
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
705
        if not quiet:
706
            print "Done updating wiki."
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
707
    else:
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
708
        print page_contents
9373.1.1 by Karl Fogel
Add utilities/community-contributions.py (descended from lpcc.py in
709
710
711
if __name__ == '__main__':
9373.1.4 by Karl Fogel
* utilities/community-contributions.py: Reindent with py-offset-level 4,
712
    main()