Merge lp:~dobey/tarmac/merge-specific into lp:tarmac

Proposed by dobey
Status: Merged
Approved by: dobey
Approved revision: 432
Merged at revision: 430
Proposed branch: lp:~dobey/tarmac/merge-specific
Merge into: lp:tarmac
Diff against target: 167 lines (+73/-8)
3 files modified
tarmac/bin/commands.py (+19/-3)
tarmac/bin/options.py (+4/-0)
tarmac/tests/test_commands.py (+50/-5)
To merge this branch: bzr merge lp:~dobey/tarmac/merge-specific
Reviewer Review Type Date Requested Status
Francis Ginther Approve
Review via email: mp+208037@code.launchpad.net

Commit message

Add an option to merge a single specific proposal to a branch.

Description of the change

This adds the --proposal option to the tarmac merge command, so that a specific proposal can be merged. The argument is the web link to the MP to be merged. Passing this argument to the merge command will result in tarmac attempting to merge only that MP, and no others, not even branches for other targets which are set up in tarmac.conf.

To post a comment you must log in.
lp:~dobey/tarmac/merge-specific updated
430. By dobey

Add a couple more tests.
Fix a typo.
Revert the changes to addProposal.
Clean up the branch created by addProposal.

431. By dobey

Always use the branch_url from the MP when --proposal is used.

432. By dobey

Revert one more line.

Revision history for this message
Francis Ginther (fginther) wrote :

This implements the requested feature. Tests and code changes look good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'tarmac/bin/commands.py'
--- tarmac/bin/commands.py 2014-02-20 03:16:01 +0000
+++ tarmac/bin/commands.py 2014-02-24 23:41:56 +0000
@@ -174,6 +174,7 @@
174 options.imply_commit_message_option,174 options.imply_commit_message_option,
175 options.one_option,175 options.one_option,
176 options.list_approved_option,176 options.list_approved_option,
177 options.proposal_option,
177 ]178 ]
178179
179 def _handle_merge_error(self, proposal, failure):180 def _handle_merge_error(self, proposal, failure):
@@ -201,14 +202,17 @@
201 proposal.setStatus(status=u'Needs review')202 proposal.setStatus(status=u'Needs review')
202 proposal.lp_save()203 proposal.lp_save()
203204
204 def _do_merges(self, branch_url):205 def _do_merges(self, branch_url, source_mp=None):
205 """Merge the approved proposals for %branch_url."""206 """Merge the approved proposals for %branch_url."""
206 lp_branch = self.launchpad.branches.getByUrl(url=branch_url)207 lp_branch = self.launchpad.branches.getByUrl(url=branch_url)
207 if lp_branch is None:208 if lp_branch is None:
208 self.logger.info('Not a valid branch: {0}'.format(branch_url))209 self.logger.info('Not a valid branch: {0}'.format(branch_url))
209 return210 return
210211
211 proposals = self._get_mergable_proposals_for_branch(lp_branch)212 if source_mp is not None:
213 proposals = [source_mp]
214 else:
215 proposals = self._get_mergable_proposals_for_branch(lp_branch)
212216
213 if not proposals:217 if not proposals:
214 self.logger.info(218 self.logger.info(
@@ -409,6 +413,12 @@
409413
410 return reviews414 return reviews
411415
416 def _get_proposal_from_mp_url(self, mp_url):
417 """Return a branch_merge_proposal object from its web URL."""
418 urlp = re.compile('http[s]?://code.launchpad\.net/')
419 api_url = urlp.sub('https://api.launchpad.net/1.0/', mp_url)
420 return self.launchpad.load(api_url)
421
412 def run(self, branch_url=None, launchpad=None, **kwargs):422 def run(self, branch_url=None, launchpad=None, **kwargs):
413 for key, value in kwargs.iteritems():423 for key, value in kwargs.iteritems():
414 self.config.set('Tarmac', key, value)424 self.config.set('Tarmac', key, value)
@@ -429,12 +439,18 @@
429 self.launchpad = self.get_launchpad_object()439 self.launchpad = self.get_launchpad_object()
430 self.logger.debug('launchpad object loaded')440 self.logger.debug('launchpad object loaded')
431441
442 proposal = None
443 if self.config.proposal:
444 proposal = self._get_proposal_from_mp_url(self.config.proposal)
445 # Always override branch_url with the correct one.
446 branch_url = proposal.target_branch.bzr_identity
447
432 if branch_url:448 if branch_url:
433 self.logger.debug('%(branch_url)s specified as branch_url' % {449 self.logger.debug('%(branch_url)s specified as branch_url' % {
434 'branch_url': branch_url})450 'branch_url': branch_url})
435 if not branch_url.startswith('lp:'):451 if not branch_url.startswith('lp:'):
436 raise TarmacCommandError('Branch urls must start with lp:')452 raise TarmacCommandError('Branch urls must start with lp:')
437 self._do_merges(branch_url)453 self._do_merges(branch_url, source_mp=proposal)
438454
439 else:455 else:
440 for branch in self.config.branches:456 for branch in self.config.branches:
441457
=== modified file 'tarmac/bin/options.py'
--- tarmac/bin/options.py 2014-02-17 20:12:51 +0000
+++ tarmac/bin/options.py 2014-02-24 23:41:56 +0000
@@ -36,3 +36,7 @@
36list_approved_option = Option(36list_approved_option = Option(
37 'list-approved', short_name='l',37 'list-approved', short_name='l',
38 help='List Approved merge proposals for the target branch.')38 help='List Approved merge proposals for the target branch.')
39proposal_option = Option(
40 'proposal', short_name='p',
41 type=str, argname='url',
42 help='Pass the URL for a specific proposal to merge to the target branch.')
3943
=== modified file 'tarmac/tests/test_commands.py'
--- tarmac/tests/test_commands.py 2014-02-20 03:16:01 +0000
+++ tarmac/tests/test_commands.py 2014-02-24 23:41:56 +0000
@@ -19,7 +19,7 @@
19import shutil19import shutil
20import sys20import sys
2121
22from mock import patch22from mock import patch, MagicMock
23from tarmac.bin import commands23from tarmac.bin import commands
24from tarmac.bin.registry import CommandRegistry24from tarmac.bin.registry import CommandRegistry
25from tarmac.branch import Branch25from tarmac.branch import Branch
@@ -157,7 +157,7 @@
157 reviewer=Thing(display_name=u'Reviewer'))]),157 reviewer=Thing(display_name=u'Reviewer'))]),
158 Thing(158 Thing(
159 self_link=u'https://api.launchpad.net/1.0/proposal1',159 self_link=u'https://api.launchpad.net/1.0/proposal1',
160 web_link=u'https://codelaunchpad.net/proposal1',160 web_link=u'https://code.launchpad.net/proposal1',
161 queue_status=u'Approved',161 queue_status=u'Approved',
162 commit_message=u'Commit this.',162 commit_message=u'Commit this.',
163 source_branch=self.branches[0],163 source_branch=self.branches[0],
@@ -201,8 +201,8 @@
201 branch3.lp_branch.unique_name = '~user/branch/' + name201 branch3.lp_branch.unique_name = '~user/branch/' + name
202 branch3.lp_branch.landing_candidates = []202 branch3.lp_branch.landing_candidates = []
203 b3_proposal = Thing(203 b3_proposal = Thing(
204 self_link=u'http://api.edge.launchpad.net/devel/proposal3',204 self_link=u'https://api.launchpad.net/1.0/proposal3',
205 web_link=u'http://edge.launchpad.net/proposal3',205 web_link=u'https://code.launchpad.net/proposal3',
206 queue_status=u'Approved',206 queue_status=u'Approved',
207 commit_message=u'Commitable.',207 commit_message=u'Commitable.',
208 source_branch=branch3.lp_branch,208 source_branch=branch3.lp_branch,
@@ -219,7 +219,7 @@
219 branch3.lp_branch.landing_targets = [b3_proposal]219 branch3.lp_branch.landing_targets = [b3_proposal]
220 self.proposals.append(b3_proposal)220 self.proposals.append(b3_proposal)
221 self.branches.append(branch3.lp_branch)221 self.branches.append(branch3.lp_branch)
222222 self.addCleanup(shutil.rmtree, branch3_dir)
223223
224 def lp_save(self, *args, **kwargs):224 def lp_save(self, *args, **kwargs):
225 """Do nothing here."""225 """Do nothing here."""
@@ -491,3 +491,48 @@
491 self.addProposal("one_prerequisite", self.branches[0])491 self.addProposal("one_prerequisite", self.branches[0])
492 proposals = self.command._get_prerequisite_proposals(self.proposals[2])492 proposals = self.command._get_prerequisite_proposals(self.proposals[2])
493 self.assertEqual(len(proposals), 2)493 self.assertEqual(len(proposals), 2)
494
495 @patch('tarmac.bin.commands.Launchpad.load')
496 def test__get_proposal_from_mp_url(self, mocked):
497 """Test that the URL is substituted correctly."""
498 self.command.launchpad = MagicMock()
499 self.command.launchpad.load = mocked
500 self.command._get_proposal_from_mp_url(
501 'https://code.launchpad.net/~foo/bar/baz/+merge/10')
502 mocked.assert_called_once_with(
503 'https://api.launchpad.net/1.0/~foo/bar/baz/+merge/10')
504
505 @patch('tarmac.bin.commands.Launchpad.load')
506 def test__get_proposal_from_mp_url_with_api_url(self, mocked):
507 """Test that the URL is ignored correctly."""
508 self.command.launchpad = MagicMock()
509 self.command.launchpad.load = mocked
510 self.command._get_proposal_from_mp_url(
511 'https://api.launchpad.net/1.0/~foo/bar/baz/+merge/10')
512 mocked.assert_called_once_with(
513 'https://api.launchpad.net/1.0/~foo/bar/baz/+merge/10')
514
515 def test_run_merge_with_specific_proposal_without_branch_url(self):
516 """Test that a specific proposal is merged, with the others ignored."""
517 self.proposals[1].reviewed_revid = \
518 self.branch2.bzr_branch.last_revision()
519 self.addProposal('specific_merge_without_branch_url')
520 self.launchpad.load = MagicMock(return_value=self.proposals[1])
521 self.command._get_reviews = MagicMock()
522 self.config.proposal = self.proposals[1].web_link
523 self.command.run(launchpad=self.launchpad)
524 self.launchpad.load.assert_called_once_with(self.proposals[1].self_link)
525 self.command._get_reviews.assert_called_once_with(self.proposals[1])
526
527 def test_run_merge_with_specific_proposal_with_branch_url(self):
528 """Test that a specific proposal is merged, with the others ignored."""
529 self.proposals[1].reviewed_revid = \
530 self.branch2.bzr_branch.last_revision()
531 self.addProposal('specific_merge_with_branch_url')
532 self.launchpad.load = MagicMock(return_value=self.proposals[1])
533 self.command._get_reviews = MagicMock()
534 self.config.proposal = self.proposals[1].web_link
535 self.command.run(launchpad=self.launchpad,
536 branch_url=self.branches[1].bzr_identity)
537 self.launchpad.load.assert_called_once_with(self.proposals[1].self_link)
538 self.command._get_reviews.assert_called_once_with(self.proposals[1])

Subscribers

People subscribed via source and target branches