Merge lp:~dobey/tarmac/bug-closure into lp:tarmac

Proposed by dobey
Status: Merged
Approved by: Paul Hummer
Approved revision: 338
Merged at revision: 336
Proposed branch: lp:~dobey/tarmac/bug-closure
Merge into: lp:tarmac
Diff against target: 357 lines (+261/-9)
6 files modified
tarmac/branch.py (+24/-4)
tarmac/config.py (+3/-2)
tarmac/plugins/bugresolver.py (+32/-0)
tarmac/tests/__init__.py (+5/-1)
tarmac/tests/mock.py (+9/-2)
tarmac/tests/test_branch.py (+188/-0)
To merge this branch: bzr merge lp:~dobey/tarmac/bug-closure
Reviewer Review Type Date Requested Status
Paul Hummer Approve
Review via email: mp+32242@code.launchpad.net

Commit message

Get the list of bugs fixed in the to-be-merged branch
Set the status of fixed bugs to 'Fix committed'
Bring back test_branch.py and make it work in local isolation

To post a comment you must log in.
lp:~dobey/tarmac/bug-closure updated
337. By dobey

Remove debugging pdb usage

338. By dobey

Move the actual bug resolving code to a plug-in
Change the fixed_bugs method to a property
Fix up the MockLPBranch class to take a MockLPBranch as the source_branch arg
Set up revision_count property on MockLPBranch objects for testing

Revision history for this message
Paul Hummer (rockstar) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'tarmac/branch.py'
2--- tarmac/branch.py 2010-07-25 23:53:05 +0000
3+++ tarmac/branch.py 2010-08-11 19:57:43 +0000
4@@ -26,6 +26,8 @@
5 import tempfile
6
7 from bzrlib import branch as bzr_branch
8+from bzrlib import missing
9+from bzrlib.errors import NoSuchRevision
10 from bzrlib.workingtree import WorkingTree
11
12 from tarmac.config import BranchConfig
13@@ -47,7 +49,6 @@
14 @classmethod
15 def create(cls, lp_branch, config, create_tree=False):
16 if create_tree:
17- assert config.has_section(lp_branch.bzr_identity)
18 clazz = cls(lp_branch, config)
19 clazz.create_tree()
20 else:
21@@ -107,8 +108,6 @@
22
23 def commit(self, commit_message, revprops=None, **kwargs):
24 '''Commit changes.'''
25- assert self.tree
26-
27 if not revprops:
28 revprops = {}
29
30@@ -148,6 +147,27 @@
31
32 @property
33 def has_changes(self):
34- if not self.has_tree:
35+ if not self.tree:
36 return False
37 return self.tree.changes_from(self.tree.basis_tree())
38+
39+ @property
40+ def fixed_bugs(self):
41+ """Return the list of bugs fixed by the branch."""
42+ bugs_list = []
43+
44+ self.bzr_branch.lock_read()
45+ oldrevid = self.bzr_branch.get_rev_id(self.lp_branch.revision_count)
46+ for rev_info in self.bzr_branch.iter_merge_sorted_revisions(
47+ stop_revision_id=oldrevid):
48+ try:
49+ rev = self.bzr_branch.repository.get_revision(rev_info[0])
50+ for bug in rev.iter_bugs():
51+ if bug[0].startswith('https://launchpad.net/bugs/'):
52+ bugs_list.append(bug[0].replace(
53+ 'https://launchpad.net/bugs/', ''))
54+ except NoSuchRevision:
55+ continue
56+
57+ self.bzr_branch.unlock()
58+ return bugs_list
59
60=== modified file 'tarmac/config.py'
61--- tarmac/config.py 2010-07-21 20:33:26 +0000
62+++ tarmac/config.py 2010-08-11 19:57:43 +0000
63@@ -106,5 +106,6 @@
64 '''
65
66 def __init__(self, branch_name, config):
67- for key, val in config.items(branch_name):
68- setattr(self, key, val)
69+ if config.has_section(branch_name):
70+ for key, val in config.items(branch_name):
71+ setattr(self, key, val)
72
73=== added file 'tarmac/plugins/bugresolver.py'
74--- tarmac/plugins/bugresolver.py 1970-01-01 00:00:00 +0000
75+++ tarmac/plugins/bugresolver.py 2010-08-11 19:57:43 +0000
76@@ -0,0 +1,32 @@
77+# Copyright 2010 Canonical, Ltd.
78+# This file is part of Tarmac.
79+#
80+# Tarmac is free software: you can redistribute it and/or modify
81+# it under the terms of the GNU General Public License version 3 as
82+# published by the Free Software Foundation.
83+#
84+# Tarmac is distributed in the hope that it will be useful,
85+# but WITHOUT ANY WARRANTY; without even the implied warranty of
86+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
87+# GNU General Public License for more details.
88+#
89+# You should have received a copy of the GNU General Public License
90+# along with Tarmac. If not, see <http://www.gnu.org/licenses/>.
91+"""Tarmac plug-in for setting a bug status post-commit."""
92+
93+from tarmac.hooks import tarmac_hooks
94+from tarmac.plugins import TarmacPlugin
95+
96+
97+class BugResolver(TarmacPlugin):
98+ """Tarmac plug-in for resolving a bug."""
99+
100+ def run(self, command, target, source, proposal):
101+ """Mark bugs fixed in the bug tracker."""
102+ for bug_id in target.fixed_bugs:
103+ bug = command.launchpad.bugs[bug_id]
104+ bug.setStatus(u'Fix committed')
105+ bug.lp_save()
106+
107+
108+tarmac_hooks['tarmac_post_commit'].hook(BugResolver(), 'Bug resolver')
109
110=== modified file 'tarmac/tests/__init__.py'
111--- tarmac/tests/__init__.py 2010-07-24 13:23:55 +0000
112+++ tarmac/tests/__init__.py 2010-08-11 19:57:43 +0000
113@@ -58,7 +58,11 @@
114 self.tempdir, 'credentials')
115
116 # Create self.tempdir; it is removed in tearDown().
117- os.makedirs(self.tempdir)
118+ try:
119+ os.makedirs(self.tempdir)
120+ except OSError, e:
121+ if e.errno != 17:
122+ raise e
123
124 if self.NEEDS_SAMPLE_DATA:
125 config = TarmacConfig()
126
127=== modified file 'tarmac/tests/mock.py'
128--- tarmac/tests/mock.py 2010-04-24 03:55:28 +0000
129+++ tarmac/tests/mock.py 2010-08-11 19:57:43 +0000
130@@ -18,6 +18,7 @@
131 from base64 import b64encode
132 import math
133 import os
134+import shutil
135 import tempfile
136
137 from bzrlib.bzrdir import BzrDir
138@@ -36,18 +37,24 @@
139 '''A mock LP Branch.'''
140
141 def __init__(self, source_branch=None):
142- self.temp_dir = tempfile.mkdtemp()
143+ tempfile.tempdir = os.getcwd()
144+ self.temp_dir = tempfile.mkdtemp(dir=os.getcwd())
145 if source_branch:
146- bzrdir = source_branch.bzrdir.sprout(
147+ bzrdir = source_branch._internal_bzr_branch.bzrdir.sprout(
148 self.temp_dir)
149 self._internal_tree, self._internal_bzr_branch = \
150 bzrdir.open_tree_or_branch(self.temp_dir)
151+ self.revision_count = source_branch.revision_count
152 else:
153 self._internal_bzr_branch = BzrDir.create_branch_convenience(
154 self.temp_dir)
155+ self.revision_count = 0
156 self.bzr_identity = self._internal_bzr_branch.base
157 self.project = MockLPProject()
158
159+ def cleanup(self):
160+ shutil.rmtree(self.temp_dir)
161+
162
163 class cmd_mock(TarmacCommand):
164 '''A mock command.'''
165
166=== added file 'tarmac/tests/test_branch.py'
167--- tarmac/tests/test_branch.py 1970-01-01 00:00:00 +0000
168+++ tarmac/tests/test_branch.py 2010-08-11 19:57:43 +0000
169@@ -0,0 +1,188 @@
170+# Copyright 2009 Paul Hummer
171+# Copyright 2009 Canonical Ltd.
172+#
173+# This file is part of Tarmac.
174+#
175+# Tarmac is free software: you can redistribute it and/or modify
176+# it under the terms of the GNU General Public License version 3 as
177+# published by
178+# the Free Software Foundation.
179+#
180+# Tarmac is distributed in the hope that it will be useful,
181+# but WITHOUT ANY WARRANTY; without even the implied warranty of
182+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
183+# GNU General Public License for more details.
184+#
185+# You should have received a copy of the GNU General Public License
186+# along with Tarmac. If not, see <http://www.gnu.org/licenses/>.
187+
188+'''Tests for tarmac.branch'''
189+import os
190+
191+from bzrlib.errors import NoCommits
192+
193+from tarmac import branch
194+from tarmac.config import TarmacConfig
195+from tarmac.tests import TarmacTestCase
196+from tarmac.tests.mock import MockLPBranch
197+
198+CONFIG_TEMPLATE = '''
199+[%(url)s]
200+tree_dir = %(temp_tree)s
201+log_file = %(temp_log)s
202+'''
203+
204+
205+class TestBranch(TarmacTestCase):
206+ '''Test for Tarmac.branch.Branch.'''
207+
208+ def setUp(self):
209+ '''Set up the test environment.'''
210+ TarmacTestCase.setUp(self)
211+
212+ self.bzrdir = os.path.join(os.getcwd(), "bzr")
213+ os.environ['BZR_HOME'] = self.bzrdir
214+
215+ self.config = TarmacConfig()
216+ self.write_config_file()
217+
218+ def make_two_branches_to_merge(self):
219+ '''Make two branches, one with revisions to merge.'''
220+ mock1 = MockLPBranch()
221+ self.CONFIG_TEMPLATE = CONFIG_TEMPLATE % {
222+ 'url' : 'file://%s' % mock1.temp_dir,
223+ 'temp_log' : mock1.temp_dir + '.log',
224+ 'temp_tree' : mock1.temp_dir
225+ }
226+ self.write_config_file()
227+
228+ a_branch = branch.Branch.create(mock1, self.config, create_tree=True)
229+ a_branch.commit("Reading, 'riting, 'rithmetic")
230+ a_branch.lp_branch.revision_count += 1
231+ another_branch = branch.Branch.create(MockLPBranch(
232+ source_branch=a_branch.lp_branch), self.config, create_tree=True)
233+ another_branch.commit('ABC...')
234+ another_branch.commit('...as easy as 123')
235+ another_branch.lp_branch.revision_count += 2
236+
237+ return a_branch, another_branch
238+
239+ def test_create(self):
240+ '''Test the creation of a TarmacBranch instance.'''
241+ mock1 = MockLPBranch()
242+ self.CONFIG_TEMPLATE = CONFIG_TEMPLATE % {
243+ 'url' : 'file://%s' % mock1.temp_dir,
244+ 'temp_log' : mock1.temp_dir + '.log',
245+ 'temp_tree' : mock1.temp_dir
246+ }
247+ self.write_config_file()
248+
249+ self.assertTrue(self.config.has_section('file://%s' % mock1.temp_dir))
250+ self.assertEqual(self.config.get('file://%s' % mock1.temp_dir,
251+ 'tree_dir', None),
252+ mock1.temp_dir)
253+ a_branch = branch.Branch.create(mock1, self.config)
254+
255+ self.assertTrue(isinstance(a_branch, branch.Branch))
256+ self.assertTrue(a_branch.lp_branch.bzr_identity)
257+ self.assertFalse(hasattr(a_branch, 'tree'))
258+
259+ def test_create_with_tree(self):
260+ '''Test the creation of a TarmacBranch with a created tree.'''
261+ mock1 = MockLPBranch()
262+ self.CONFIG_TEMPLATE = CONFIG_TEMPLATE % {
263+ 'url' : 'file://%s' % mock1.temp_dir,
264+ 'temp_log' : mock1.temp_dir + '.log',
265+ 'temp_tree' : mock1.temp_dir
266+ }
267+ self.write_config_file()
268+
269+ a_branch = branch.Branch.create(mock1, self.config,
270+ create_tree=True)
271+
272+ self.assertTrue(isinstance(a_branch, branch.Branch))
273+ self.assertTrue(a_branch.lp_branch.bzr_identity)
274+ self.assertTrue(hasattr(a_branch, 'tree'))
275+
276+ def test_merge_raises_exception_with_no_tree(self):
277+ '''A merge on a branch with no tree will raise an exception.'''
278+ a_branch = branch.Branch(MockLPBranch())
279+ another_branch = branch.Branch(MockLPBranch())
280+
281+ self.assertRaises(
282+ AttributeError, a_branch.merge, another_branch)
283+
284+ def test_merge_no_changes(self):
285+ '''A merge on a branch with a tree will raise an exception if no
286+ changes are present.'''
287+ a_branch = branch.Branch.create(MockLPBranch(), self.config,
288+ create_tree=True)
289+ another_branch = branch.Branch(MockLPBranch())
290+
291+ # XXX: Find a way to generate dummy revisions for the second branch.
292+ self.assertRaises(NoCommits, a_branch.merge, another_branch)
293+
294+ def test_merge(self):
295+ '''A merge on a branch with a tree of a branch with changes will merge.
296+ '''
297+ a_branch, another_branch = self.make_two_branches_to_merge()
298+ a_branch.merge(another_branch)
299+ self.assertTrue(a_branch.has_changes)
300+ a_branch.lp_branch.cleanup()
301+ another_branch.lp_branch.cleanup()
302+
303+ def test_merge_with_authors(self):
304+ '''A merge from a branch with authors'''
305+ branch1, branch2 = self.make_two_branches_to_merge()
306+ authors = [ 'author1', 'author2' ]
307+ branch1.commit('Authors test', authors=authors)
308+ branch2.merge(branch1)
309+ branch2.commit('Authors Merge test', authors=branch1.authors)
310+ self.assertEqual(branch2.authors.sort(), authors.sort())
311+
312+ def test_merge_with_bugs(self):
313+ '''A merge from a branch with authors'''
314+ branch1, branch2 = self.make_two_branches_to_merge()
315+ bugs = ['https://launchpad.net/bugs/1 fixed',
316+ 'https://bugzilla.gnome.org/show_bug.cgi?id=1 fixed',
317+ 'https://launchpad.net/bugs/2 fixed'
318+ ]
319+ revprops = {}
320+ revprops['bugs'] = '\n'.join(bugs)
321+ branch1.commit('Bugs test', revprops)
322+ branch1.commit('Testing')
323+ branch2.commit('Foo',
324+ revprops={'bugs':'https://launchpad.net/bugs/3 fixed'})
325+ branch2.lp_branch.revision_count += 1
326+ branch2.merge(branch1)
327+ branch2.commit('Landed bugs')
328+ self.assertEqual(branch2.fixed_bugs, branch1.fixed_bugs)
329+ branch2.cleanup()
330+
331+ def test_merge_with_reviewers(self):
332+ '''A merge with reviewers.'''
333+ reviewers = [ 'reviewer1', 'reviewer2' ]
334+
335+ a_branch, another_branch = self.make_two_branches_to_merge()
336+ a_branch.merge(another_branch)
337+ a_branch.commit('Reviewers test', reviewers=reviewers)
338+
339+ last_rev = a_branch.lp_branch._internal_bzr_branch.last_revision()
340+ self.assertNotEquals(last_rev, 'null:')
341+ rev = a_branch.lp_branch._internal_bzr_branch.repository.get_revision(
342+ last_rev)
343+ self.assertEquals('\n'.join(reviewers), rev.properties['reviewers'])
344+ a_branch.lp_branch.cleanup()
345+ another_branch.lp_branch.cleanup()
346+
347+ def test_cleanup(self):
348+ '''The branch object should clean up after itself.'''
349+ a_branch, another_branch = self.make_two_branches_to_merge()
350+ a_branch.merge(another_branch)
351+ self.assertTrue(a_branch.has_changes)
352+
353+ a_branch.cleanup()
354+ self.assertTrue(a_branch.has_changes)
355+
356+ a_branch.lp_branch.cleanup()
357+ another_branch.lp_branch.cleanup()

Subscribers

People subscribed via source and target branches