launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #01956
[Merge] lp:~abentley/launchpad/find-review into lp:launchpad/devel
Aaron Bentley has proposed merging lp:~abentley/launchpad/find-review into lp:launchpad/devel.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
#677077 It should be possible to find the merge proposal that approved a revision via the API
https://bugs.launchpad.net/bugs/677077
= Summary =
Fix bug #677077: It should be possible to find the merge proposal that approved
a revision via the API
== Proposed fix ==
IBranch.getMergeProposals and add merged_revnos parameter.
== Pre-implementation notes ==
None
== Implementation details ==
IBranch derives from IHasMergeProposals, so it already provides
getMergeProposals. merged_revnos only makes sense in the context of a single
branch, because a revnos only refers to a specific revision in the context of a
branch. Therefore, merged_revnos could not be provided on IHasMergeProposals.
Therefore, getMergeProposals was exposed on IBranch.
merge_revnos is plural (not merged_revno) in order to support efficient access
to multiple merge proposals, should that be desired.
== Tests ==
bin/test -t test_getMergeProposals_with_merged_revnos -t test_merge_proposals_merging_revno
== Demo and Q/A ==
Write a commandline script that uses merged_revnos to get a merge proposal over
the API.
= Launchpad lint =
Checking for conflicts and issues in changed files.
Linting changed files:
lib/lp/code/model/branchcollection.py
lib/lp/code/interfaces/branch.py
lib/lp/code/model/branch.py
lib/lp/code/model/tests/test_branchcollection.py
lib/canonical/launchpad/interfaces/_schema_circular_imports.py
lib/lp/code/model/tests/test_branch.py
--
https://code.launchpad.net/~abentley/launchpad/find-review/+merge/41195
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~abentley/launchpad/find-review into lp:launchpad/devel.
=== modified file 'lib/canonical/launchpad/interfaces/_schema_circular_imports.py'
--- lib/canonical/launchpad/interfaces/_schema_circular_imports.py 2010-11-09 15:07:38 +0000
+++ lib/canonical/launchpad/interfaces/_schema_circular_imports.py 2010-11-18 16:50:14 +0000
@@ -169,6 +169,8 @@
IBranch, '_createMergeProposal', 'target_branch', IBranch)
patch_plain_parameter_type(
IBranch, '_createMergeProposal', 'prerequisite_branch', IBranch)
+patch_collection_return_type(
+ IBranch, 'getMergeProposals', IBranchMergeProposal)
IBranchMergeProposal['getComment'].queryTaggedValue(
LAZR_WEBSERVICE_EXPORTED)['return_type'].schema = ICodeReviewComment
=== modified file 'lib/lp/code/interfaces/branch.py'
--- lib/lp/code/interfaces/branch.py 2010-11-04 19:59:02 +0000
+++ lib/lp/code/interfaces/branch.py 2010-11-18 16:50:14 +0000
@@ -39,6 +39,7 @@
exported,
mutator_for,
operation_parameters,
+ operation_returns_collection_of,
operation_returns_entry,
REQUEST_USER,
)
@@ -75,6 +76,7 @@
)
from lp.code.enums import (
BranchLifecycleStatus,
+ BranchMergeProposalStatus,
BranchSubscriptionDiffSize,
BranchSubscriptionNotificationLevel,
CodeReviewNotificationLevel,
@@ -585,6 +587,19 @@
:param review_requests: An optional list of (`Person`, review_type).
"""
+ @operation_parameters(
+ status=List(
+ title=_("A list of merge proposal statuses to filter by."),
+ value_type=Choice(vocabulary=BranchMergeProposalStatus)),
+ merged_revnos=List(Int(
+ title=_('The target-branch revno of the merge.'))))
+ @call_with(visible_by_user=REQUEST_USER)
+ @operation_returns_collection_of(Interface) # Really IBranchMergeProposal.
+ @export_read_operation()
+ def getMergeProposals(status=None, visible_by_user=None,
+ merged_revnos=None):
+ """Return matching BranchMergeProposals."""
+
def scheduleDiffUpdates():
"""Create UpdatePreviewDiffJobs for this branch's targets."""
=== modified file 'lib/lp/code/model/branch.py'
--- lib/lp/code/model/branch.py 2010-11-09 08:43:34 +0000
+++ lib/lp/code/model/branch.py 2010-11-18 16:50:14 +0000
@@ -360,8 +360,9 @@
BranchMergeProposal.queue_status NOT IN %s
""" % sqlvalues(self, BRANCH_MERGE_PROPOSAL_FINAL_STATES))
- def getMergeProposals(self, status=None, visible_by_user=None):
- """See `IHasMergeProposals`."""
+ def getMergeProposals(self, status=None, visible_by_user=None,
+ merged_revnos=None):
+ """See `IBranch`."""
if not status:
status = (
BranchMergeProposalStatus.CODE_APPROVED,
@@ -369,7 +370,8 @@
BranchMergeProposalStatus.WORK_IN_PROGRESS)
collection = getUtility(IAllBranches).visibleByUser(visible_by_user)
- return collection.getMergeProposals(status, target_branch=self)
+ return collection.getMergeProposals(
+ status, target_branch=self, merged_revnos=merged_revnos)
def isBranchMergeable(self, target_branch):
"""See `IBranch`."""
=== modified file 'lib/lp/code/model/branchcollection.py'
--- lib/lp/code/model/branchcollection.py 2010-08-20 20:31:18 +0000
+++ lib/lp/code/model/branchcollection.py 2010-11-18 16:50:14 +0000
@@ -145,7 +145,7 @@
return self.store.using(*tables).find(Branch, *expressions)
def getMergeProposals(self, statuses=None, for_branches=None,
- target_branch=None):
+ target_branch=None, merged_revnos=None):
"""See `IBranchCollection`."""
expressions = [
BranchMergeProposal.source_branchID.is_in(
@@ -158,6 +158,9 @@
if target_branch is not None:
expressions.append(
BranchMergeProposal.target_branch == target_branch)
+ if merged_revnos is not None:
+ expressions.append(
+ BranchMergeProposal.merged_revno.is_in(merged_revnos))
expressions.extend(self._getExtraMergeProposalExpressions())
if statuses is not None:
expressions.append(
=== modified file 'lib/lp/code/model/tests/test_branch.py'
--- lib/lp/code/model/tests/test_branch.py 2010-11-04 19:59:02 +0000
+++ lib/lp/code/model/tests/test_branch.py 2010-11-18 16:50:14 +0000
@@ -66,7 +66,6 @@
InvalidBranchMergeProposal,
InvalidMergeQueueConfig,
)
-from lp.code.event.branchmergeproposal import NewBranchMergeProposalEvent
from lp.code.interfaces.branch import (
DEFAULT_BRANCH_STATUS_IN_LISTING,
IBranch,
@@ -2757,7 +2756,8 @@
branch = self.factory.makeBranch()
config = simplejson.dumps({
'path': '/',
- 'test': 'make test',})
+ 'test': 'make test',
+ })
with person_logged_in(branch.owner):
branch.setMergeQueueConfig(config)
@@ -2815,6 +2815,19 @@
branch2 = ws_object(launchpad, db_branch)
self.assertEqual(branch2.merge_queue_config, configuration)
+ def test_getMergeProposals_with_merged_revnos(self):
+ """Specifying merged revnos selects the correct merge proposal."""
+ mp = self.factory.makeBranchMergeProposal()
+ launchpad = launchpadlib_for('test', mp.registrant,
+ service_root="http://api.launchpad.dev:8085")
+ with person_logged_in(mp.registrant):
+ mp.markAsMerged(merged_revno=123)
+ transaction.commit()
+ target = ws_object(launchpad, mp.target_branch)
+ mp = ws_object(launchpad, mp)
+ self.assertEqual([mp], list(target.getMergeProposals(
+ status=['Merged'], merged_revnos=[123])))
+
def test_suite():
return TestLoader().loadTestsFromName(__name__)
=== modified file 'lib/lp/code/model/tests/test_branchcollection.py'
--- lib/lp/code/model/tests/test_branchcollection.py 2010-08-20 20:31:18 +0000
+++ lib/lp/code/model/tests/test_branchcollection.py 2010-11-18 16:50:14 +0000
@@ -40,6 +40,7 @@
from lp.code.model.branchcollection import GenericBranchCollection
from lp.registry.interfaces.pocket import PackagePublishingPocket
from lp.testing import (
+ person_logged_in,
run_with_login,
TestCaseWithFactory,
)
@@ -638,6 +639,24 @@
proposals = collection.getMergeProposals()
self.assertEqual([mp1], list(proposals))
+ def test_merge_proposals_merging_revno(self):
+ """Specifying merged_revnos selects the correct merge proposals."""
+ target = self.factory.makeBranch()
+ mp1 = self.factory.makeBranchMergeProposal(target_branch=target)
+ mp2 = self.factory.makeBranchMergeProposal(target_branch=target)
+ mp3 = self.factory.makeBranchMergeProposal(target_branch=target)
+ with person_logged_in(target.owner):
+ mp1.markAsMerged(123)
+ mp2.markAsMerged(123)
+ mp3.markAsMerged(321)
+ collection = self.all_branches
+ result = collection.getMergeProposals(
+ target_branch=target, merged_revnos=[123])
+ self.assertEqual(sorted([mp1, mp2]), sorted(result))
+ result = collection.getMergeProposals(
+ target_branch=target, merged_revnos=[123, 321])
+ self.assertEqual(sorted([mp1, mp2, mp3]), sorted(result))
+
def test_target_branch_private(self):
# The target branch must be in the branch collection, as must the
# source branch.