Merge lp:~gagern/bzr/bug513322-authors into lp:bzr

Proposed by Martin von Gagern
Status: Superseded
Proposed branch: lp:~gagern/bzr/bug513322-authors
Merge into: lp:bzr
Diff against target: 311 lines (+206/-9)
4 files modified
NEWS (+4/-0)
bzrlib/builtins.py (+9/-2)
bzrlib/log.py (+48/-7)
bzrlib/tests/test_log.py (+145/-0)
To merge this branch: bzr merge lp:~gagern/bzr/bug513322-authors
Reviewer Review Type Date Requested Status
Robert Collins (community) Needs Fixing
Review via email: mp+22609@code.launchpad.net

This proposal has been superseded by a proposal from 2010-04-09.

Description of the change

This patch introduces a --authors switch to bzr log, allowing users to override the choice of authors for all built-in formats. It comes with a NEWS item and several test cases.

I'm not perfectly happy with the naming, so if you prefer different names for some method or attribute, let me know. I also haven't included a blackbox test ensuring that the --authors command line switch actually gets passed to the log formatter. Do you consider this necessary?

To post a comment you must log in.
Revision history for this message
Robert Collins (lifeless) wrote :

The manual parsing and the structure of the if block says to me that this would be better handled by a registry of author handlers.

review: Needs Fixing

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'NEWS'
2--- NEWS 2010-04-08 08:48:59 +0000
3+++ NEWS 2010-04-09 16:42:30 +0000
4@@ -136,6 +136,10 @@
5 * Merges can be proposed on Launchpad with the new lp-propose-merge command.
6 (Aaron Bentley, Jonathan Lange)
7
8+* New command line option ``--authors`` to ``bzr log`` allows users to
9+ select which of the apparent authors and committer should be
10+ included in the log. Defaults depend on format.
11+
12 Bug Fixes
13 *********
14
15
16=== modified file 'bzrlib/builtins.py'
17--- bzrlib/builtins.py 2010-04-08 06:05:44 +0000
18+++ bzrlib/builtins.py 2010-04-09 16:42:30 +0000
19@@ -2288,6 +2288,11 @@
20 help='Show just the specified revision.'
21 ' See also "help revisionspec".'),
22 'log-format',
23+ RegistryOption('authors',
24+ 'What names to list as authors - first, all or committer.',
25+ title='Authors',
26+ lazy_registry=('bzrlib.log', 'author_list_registry'),
27+ ),
28 Option('levels',
29 short_name='n',
30 help='Number of levels to display - 0 for all, 1 for flat.',
31@@ -2323,7 +2328,8 @@
32 message=None,
33 limit=None,
34 show_diff=False,
35- include_merges=False):
36+ include_merges=False,
37+ authors=None):
38 from bzrlib.log import (
39 Logger,
40 make_log_request_dict,
41@@ -2403,7 +2409,8 @@
42 show_timezone=timezone,
43 delta_format=get_verbosity_level(),
44 levels=levels,
45- show_advice=levels is None)
46+ show_advice=levels is None,
47+ author_list_handler=authors)
48
49 # Choose the algorithm for doing the logging. It's annoying
50 # having multiple code paths like this but necessary until
51
52=== modified file 'bzrlib/log.py'
53--- bzrlib/log.py 2010-04-01 00:40:31 +0000
54+++ bzrlib/log.py 2010-04-09 16:42:30 +0000
55@@ -1321,7 +1321,7 @@
56
57 def __init__(self, to_file, show_ids=False, show_timezone='original',
58 delta_format=None, levels=None, show_advice=False,
59- to_exact_file=None):
60+ to_exact_file=None, author_list_handler=None):
61 """Create a LogFormatter.
62
63 :param to_file: the file to output to
64@@ -1335,6 +1335,8 @@
65 let the log formatter decide.
66 :param show_advice: whether to show advice at the end of the
67 log or not
68+ :param author_list_handler: callable generating a list of
69+ authors to display for a given revision
70 """
71 self.to_file = to_file
72 # 'exact' stream used to show diff, it should print content 'as is'
73@@ -1355,6 +1357,7 @@
74 self.levels = levels
75 self._show_advice = show_advice
76 self._merge_count = 0
77+ self._author_list_handler = author_list_handler
78
79 def get_levels(self):
80 """Get the number of levels to display or 0 for all."""
81@@ -1392,10 +1395,24 @@
82 return address
83
84 def short_author(self, rev):
85- name, address = config.parse_username(rev.get_apparent_authors()[0])
86- if name:
87- return name
88- return address
89+ return self.authors(rev, 'first', True, ', ')
90+
91+ def authors(self, rev, who, short=False, sep=None):
92+ if self._author_list_handler is not None:
93+ author_list_handler = self._author_list_handler
94+ else:
95+ author_list_handler = author_list_registry.get(who)
96+ names = author_list_handler(rev)
97+ if short:
98+ for i in range(len(names)):
99+ name, address = config.parse_username(names[i])
100+ if name:
101+ names[i] = name
102+ else:
103+ names[i] = address
104+ if sep is not None:
105+ names = sep.join(names)
106+ return names
107
108 def merge_marker(self, revision):
109 """Get the merge marker to include in the output or '' if none."""
110@@ -1503,7 +1520,7 @@
111 lines.extend(self.custom_properties(revision.rev))
112
113 committer = revision.rev.committer
114- authors = revision.rev.get_apparent_authors()
115+ authors = self.authors(revision.rev, 'all')
116 if authors != [committer]:
117 lines.append('author: %s' % (", ".join(authors),))
118 lines.append('committer: %s' % (committer,))
119@@ -1683,7 +1700,8 @@
120 self.show_timezone,
121 date_fmt='%Y-%m-%d',
122 show_offset=False)
123- committer_str = revision.rev.get_apparent_authors()[0].replace (' <', ' <')
124+ committer_str = self.authors(revision.rev, 'first', sep=', ')
125+ committer_str = committer_str.replace(' <', ' <')
126 to_file.write('%s %s\n\n' % (date_str,committer_str))
127
128 if revision.delta is not None and revision.delta.has_changed():
129@@ -1753,6 +1771,29 @@
130 except KeyError:
131 raise errors.BzrCommandError("unknown log formatter: %r" % name)
132
133+def author_list_all(rev):
134+ return rev.get_apparent_authors()[:]
135+
136+def author_list_first(rev):
137+ lst = rev.get_apparent_authors()
138+ try:
139+ return [lst[0]]
140+ except IndexError:
141+ return []
142+
143+def author_list_committer(rev):
144+ return [rev.committer]
145+
146+author_list_registry = registry.Registry()
147+
148+author_list_registry.register('all', author_list_all,
149+ 'All authors')
150+
151+author_list_registry.register('first', author_list_first,
152+ 'The first author')
153+
154+author_list_registry.register('committer', author_list_committer,
155+ 'The committer')
156
157 def show_one_log(revno, rev, delta, verbose, to_file, show_timezone):
158 # deprecated; for compatibility
159
160=== modified file 'bzrlib/tests/test_log.py'
161--- bzrlib/tests/test_log.py 2010-03-25 08:14:04 +0000
162+++ bzrlib/tests/test_log.py 2010-04-09 16:42:30 +0000
163@@ -1541,3 +1541,148 @@
164
165 def test_bugs_handler_present(self):
166 self.properties_handler_registry.get('bugs_properties_handler')
167+
168+
169+class TestLogForAuthors(TestCaseForLogFormatter):
170+
171+ def setUp(self):
172+ TestCaseForLogFormatter.setUp(self)
173+ self.wt = self.make_standard_commit('nicky',
174+ authors=['John Doe <jdoe@example.com>',
175+ 'Jane Rey <jrey@example.com>'])
176+
177+ def assertFormatterResult(self, formatter, who, result):
178+ formatter_kwargs = dict()
179+ if who is not None:
180+ author_list_handler = log.author_list_registry.get(who)
181+ formatter_kwargs['author_list_handler'] = author_list_handler
182+ TestCaseForLogFormatter.assertFormatterResult(self, result,
183+ self.wt.branch, formatter, formatter_kwargs=formatter_kwargs)
184+
185+ def test_line_default(self):
186+ self.assertFormatterResult(log.LineLogFormatter, None, """\
187+1: John Doe 2005-11-22 add a
188+""")
189+
190+ def test_line_committer(self):
191+ self.assertFormatterResult(log.LineLogFormatter, 'committer', """\
192+1: Lorem Ipsum 2005-11-22 add a
193+""")
194+
195+ def test_line_first(self):
196+ self.assertFormatterResult(log.LineLogFormatter, 'first', """\
197+1: John Doe 2005-11-22 add a
198+""")
199+
200+ def test_line_all(self):
201+ self.assertFormatterResult(log.LineLogFormatter, 'all', """\
202+1: John Doe, Jane Rey 2005-11-22 add a
203+""")
204+
205+
206+ def test_short_default(self):
207+ self.assertFormatterResult(log.ShortLogFormatter, None, """\
208+ 1 John Doe\t2005-11-22
209+ add a
210+
211+""")
212+
213+ def test_short_committer(self):
214+ self.assertFormatterResult(log.ShortLogFormatter, 'committer', """\
215+ 1 Lorem Ipsum\t2005-11-22
216+ add a
217+
218+""")
219+
220+ def test_short_first(self):
221+ self.assertFormatterResult(log.ShortLogFormatter, 'first', """\
222+ 1 John Doe\t2005-11-22
223+ add a
224+
225+""")
226+
227+ def test_short_all(self):
228+ self.assertFormatterResult(log.ShortLogFormatter, 'all', """\
229+ 1 John Doe, Jane Rey\t2005-11-22
230+ add a
231+
232+""")
233+
234+ def test_long_default(self):
235+ self.assertFormatterResult(log.LongLogFormatter, None, """\
236+------------------------------------------------------------
237+revno: 1
238+author: John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
239+committer: Lorem Ipsum <test@example.com>
240+branch nick: nicky
241+timestamp: Tue 2005-11-22 00:00:00 +0000
242+message:
243+ add a
244+""")
245+
246+ def test_long_committer(self):
247+ self.assertFormatterResult(log.LongLogFormatter, 'committer', """\
248+------------------------------------------------------------
249+revno: 1
250+committer: Lorem Ipsum <test@example.com>
251+branch nick: nicky
252+timestamp: Tue 2005-11-22 00:00:00 +0000
253+message:
254+ add a
255+""")
256+
257+ def test_long_first(self):
258+ self.assertFormatterResult(log.LongLogFormatter, 'first', """\
259+------------------------------------------------------------
260+revno: 1
261+author: John Doe <jdoe@example.com>
262+committer: Lorem Ipsum <test@example.com>
263+branch nick: nicky
264+timestamp: Tue 2005-11-22 00:00:00 +0000
265+message:
266+ add a
267+""")
268+
269+ def test_long_all(self):
270+ self.assertFormatterResult(log.LongLogFormatter, 'all', """\
271+------------------------------------------------------------
272+revno: 1
273+author: John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
274+committer: Lorem Ipsum <test@example.com>
275+branch nick: nicky
276+timestamp: Tue 2005-11-22 00:00:00 +0000
277+message:
278+ add a
279+""")
280+
281+ def test_gnu_changelog_default(self):
282+ self.assertFormatterResult(log.GnuChangelogLogFormatter, None, """\
283+2005-11-22 John Doe <jdoe@example.com>
284+
285+\tadd a
286+
287+""")
288+
289+ def test_gnu_changelog_committer(self):
290+ self.assertFormatterResult(log.GnuChangelogLogFormatter, 'committer', """\
291+2005-11-22 Lorem Ipsum <test@example.com>
292+
293+\tadd a
294+
295+""")
296+
297+ def test_gnu_changelog_first(self):
298+ self.assertFormatterResult(log.GnuChangelogLogFormatter, 'first', """\
299+2005-11-22 John Doe <jdoe@example.com>
300+
301+\tadd a
302+
303+""")
304+
305+ def test_gnu_changelog_all(self):
306+ self.assertFormatterResult(log.GnuChangelogLogFormatter, 'all', """\
307+2005-11-22 John Doe <jdoe@example.com>, Jane Rey <jrey@example.com>
308+
309+\tadd a
310+
311+""")