Merge lp://staging/~nmb/bzr/bugs-in-log into lp://staging/bzr

Proposed by Neil Martinsen-Burrell
Status: Merged
Approved by: Andrew Bennetts
Approved revision: not available
Merged at revision: not available
Proposed branch: lp://staging/~nmb/bzr/bugs-in-log
Merge into: lp://staging/bzr
Diff against target: 141 lines (+108/-0)
3 files modified
NEWS (+6/-0)
bzrlib/log.py (+15/-0)
bzrlib/tests/test_log.py (+87/-0)
To merge this branch: bzr merge lp://staging/~nmb/bzr/bugs-in-log
Reviewer Review Type Date Requested Status
Andrew Bennetts Approve
Martin Pool Needs Fixing
Review via email: mp+16537@code.staging.launchpad.net
To post a comment you must log in.
Revision history for this message
Neil Martinsen-Burrell (nmb) wrote :

This adds a log property handler for bug fixes, along with relevant tests. Patch derived from Guillermo Ganzalez's comments in bug 251729.

Revision history for this message
Andrew Bennetts (spiv) wrote :

 review needs-fixing
 merge approve

[i.e. this is good, but it need some small tweaks before landing as specified in
the review. A review of the tweaks isn't necessary, but you're welcome to ask
for one.]

Neil Martinsen-Burrell wrote:
[...]
> === modified file 'bzrlib/log.py'
[...]
> +# Use the properties handlers to print out bug information if available
> +def _bugs_properties_handler(revision):
> + if revision.properties.has_key('bugs'):
> + bug_list = [val.split()[0] for val in

There's too many spaces after the =.

> + revision.properties['bugs'].split('\n') if
> + val.split()[1] == 'fixed'
> + ]

Hmm. I think it'd be good to make this a little more paranoid about the fixes
property. It's a fairly loosely structured field, so a bit of extra protection
like “len(val.split()) > 1)” would be good.

Also, it'd be nice to to avoid repeating the same split... so how about:

 bug_lines = revision.properties['bugs'].split('\n')
 bug_rows = [line.split(' ', 1) for line in bug_lines]
        fixed_bug_urls = [row[0] for row in bug_rows if
                   len(row) > 1 and row[1] == 'fixed']

> === modified file 'bzrlib/tests/test_log.py'
[...]
> +class TestLogWithBugs(TestCaseForLogFormatter):
> +
> + def setUp(self):
> + TestCaseForLogFormatter.setUp(self)
> + log.properties_handler_registry.register(
> + 'bugs_properties_handler',
> + log._bugs_properties_handler)

Hmm. It's good to test just this handler in perfect isolation like this, but
there's a bit of a hole in this test coverage... nothing actually tests that the
default log formatting will use this handler.

I think another test method on this test case that asserts that
bugs_properties_handler is registered in self.properties_handler_registry (which
is the actual registry preserved from bzrlib.log) would be adequate to close
that gap.

Thanks for fixing such an old bug!

-Andrew.

review: Needs Fixing
Revision history for this message
Andrew Bennetts (spiv) wrote :

Oops, I'm the first reviewer, so this still needs to be Needs Review until a 2nd dev reviews.

Revision history for this message
Martin Pool (mbp) wrote :

49 +def make_commits_with_bugs(wt):
50 + """Helper method for LogFormatter tests"""
51 + open('a', 'wb').write('hello moto\n')
52 + wt.add('a')
53 + wt.commit('simple log message', rev_id='a1',
54 + timestamp=1132586655.459960938, timezone=-6*3600,
55 + committer='Joe Foo <email address hidden>',
56 + revprops={'bugs': 'test://bug/id fixed'})
57 + open('b', 'wb').write('goodbye\n')
58 + wt.add('b')

This should (must) change to use self.build_tree() or it will cause problems with file handles leaking on Windows and Jython.

review: Needs Fixing
Revision history for this message
Neil Martinsen-Burrell (nmb) wrote :

Changed in the branch in response to the comments. Thanks for your reviews.

Revision history for this message
Andrew Bennetts (spiv) wrote :

Thanks, that seems to address everything mentioned in the review comments. I'm confident this is good enough to land now, so I'll send this to PQM (after resolving the trivial NEWS conflict).

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'NEWS'
2--- NEWS 2010-01-04 05:40:01 +0000
3+++ NEWS 2010-01-05 04:51:19 +0000
4@@ -59,10 +59,16 @@
5 * Listen to the SIGWINCH signal to update the terminal width.
6 (Vincent Ladeuil, #316357)
7
8+<<<<<<< TREE
9 * The 2a format wasn't properly restarting autopacks when something
10 changed underneath it (like another autopack). Now concurrent
11 autopackers will properly succeed. (John Arbash Meinel, #495000)
12
13+=======
14+* Add bug information to log output when available.
15+ (Neil Martinsen-Burrell, Guillermo Gonzalez, #251729)
16+
17+>>>>>>> MERGE-SOURCE
18 Improvements
19 ************
20
21
22=== modified file 'bzrlib/log.py'
23--- bzrlib/log.py 2009-12-09 05:47:32 +0000
24+++ bzrlib/log.py 2010-01-05 04:51:19 +0000
25@@ -1980,6 +1980,21 @@
26
27 properties_handler_registry = registry.Registry()
28
29+# Use the properties handlers to print out bug information if available
30+def _bugs_properties_handler(revision):
31+ if revision.properties.has_key('bugs'):
32+ bug_lines = revision.properties['bugs'].split('\n')
33+ bug_rows = [line.split(' ', 1) for line in bug_lines]
34+ fixed_bug_urls = [row[0] for row in bug_rows if
35+ len(row) > 1 and row[1] == 'fixed']
36+
37+ if fixed_bug_urls:
38+ return {'fixes bug(s)': ' '.join(fixed_bug_urls)}
39+ return {}
40+
41+properties_handler_registry.register('bugs_properties_handler',
42+ _bugs_properties_handler)
43+
44
45 # adapters which revision ids to log are filtered. When log is called, the
46 # log_rev_iterator is adapted through each of these factory methods.
47
48=== modified file 'bzrlib/tests/test_log.py'
49--- bzrlib/tests/test_log.py 2009-12-03 19:54:38 +0000
50+++ bzrlib/tests/test_log.py 2010-01-05 04:51:19 +0000
51@@ -1527,3 +1527,90 @@
52 log.show_branch_change(tree.branch, s, 3, '3b')
53 self.assertContainsRe(s.getvalue(), 'Removed Revisions:')
54 self.assertNotContainsRe(s.getvalue(), 'Added Revisions:')
55+
56+
57+
58+class TestLogWithBugs(TestCaseForLogFormatter):
59+
60+ def setUp(self):
61+ TestCaseForLogFormatter.setUp(self)
62+ log.properties_handler_registry.register(
63+ 'bugs_properties_handler',
64+ log._bugs_properties_handler)
65+
66+ def make_commits_with_bugs(self):
67+ """Helper method for LogFormatter tests"""
68+ tree = self.make_branch_and_tree(u'.')
69+ self.build_tree(['a', 'b'])
70+ tree.add('a')
71+ tree.commit('simple log message', rev_id='a1',
72+ timestamp=1132586655.459960938, timezone=-6*3600,
73+ committer='Joe Foo <joe@foo.com>',
74+ revprops={'bugs': 'test://bug/id fixed'})
75+ tree.add('b')
76+ tree.commit('multiline\nlog\nmessage\n', rev_id='a2',
77+ timestamp=1132586842.411175966, timezone=-6*3600,
78+ committer='Joe Foo <joe@foo.com>',
79+ authors=['Joe Bar <joe@bar.com>'],
80+ revprops={'bugs': 'test://bug/id fixed\n'
81+ 'test://bug/2 fixed'})
82+ return tree
83+
84+
85+ def test_long_bugs(self):
86+ tree = self.make_commits_with_bugs()
87+ self.assertFormatterResult("""\
88+------------------------------------------------------------
89+revno: 2
90+fixes bug(s): test://bug/id test://bug/2
91+author: Joe Bar <joe@bar.com>
92+committer: Joe Foo <joe@foo.com>
93+branch nick: work
94+timestamp: Mon 2005-11-21 09:27:22 -0600
95+message:
96+ multiline
97+ log
98+ message
99+------------------------------------------------------------
100+revno: 1
101+fixes bug(s): test://bug/id
102+committer: Joe Foo <joe@foo.com>
103+branch nick: work
104+timestamp: Mon 2005-11-21 09:24:15 -0600
105+message:
106+ simple log message
107+""",
108+ tree.branch, log.LongLogFormatter)
109+
110+ def test_short_bugs(self):
111+ tree = self.make_commits_with_bugs()
112+ self.assertFormatterResult("""\
113+ 2 Joe Bar\t2005-11-21
114+ fixes bug(s): test://bug/id test://bug/2
115+ multiline
116+ log
117+ message
118+
119+ 1 Joe Foo\t2005-11-21
120+ fixes bug(s): test://bug/id
121+ simple log message
122+
123+""",
124+ tree.branch, log.ShortLogFormatter)
125+
126+ def test_wrong_bugs_property(self):
127+ tree = self.make_branch_and_tree(u'.')
128+ self.build_tree(['foo'])
129+ tree.commit('simple log message', rev_id='a1',
130+ timestamp=1132586655.459960938, timezone=-6*3600,
131+ committer='Joe Foo <joe@foo.com>',
132+ revprops={'bugs': 'test://bug/id invalid_value'})
133+ self.assertFormatterResult("""\
134+ 1 Joe Foo\t2005-11-21
135+ simple log message
136+
137+""",
138+ tree.branch, log.ShortLogFormatter)
139+
140+ def test_bugs_handler_present(self):
141+ self.properties_handler_registry.get('bugs_properties_handler')