Merge lp:~cjwatson/launchpad/git-export-mp-collections into lp:launchpad

Proposed by Colin Watson
Status: Merged
Merged at revision: 17549
Proposed branch: lp:~cjwatson/launchpad/git-export-mp-collections
Merge into: lp:launchpad
Diff against target: 249 lines (+153/-23)
6 files modified
lib/lp/_schema_circular_imports.py (+9/-0)
lib/lp/code/interfaces/gitref.py (+25/-11)
lib/lp/code/interfaces/gitrepository.py (+24/-11)
lib/lp/code/model/gitrepository.py (+1/-1)
lib/lp/code/model/tests/test_gitref.py (+47/-0)
lib/lp/code/model/tests/test_gitrepository.py (+47/-0)
To merge this branch: bzr merge lp:~cjwatson/launchpad/git-export-mp-collections
Reviewer Review Type Date Requested Status
William Grant code Approve
Review via email: mp+261206@code.launchpad.net

Commit message

Export merge proposal collections on GitRepository and GitRef.

Description of the change

Export merge proposal collections on GitRepository and GitRef.

10:54 <cjwatson> wgrant: Have you thought of any better names for landing_candidates et al? Otherwise I'm inclined to export the current names on the grounds that Tarmac will need them and it's probably least confusing there for them to match Bazaar.
10:55 <wgrant> shuf -n 2 /usr/share/dict/words says extrusions_begun, which is probably less confusing than landing_candidates.
10:56 <cjwatson> :-P
10:56 <wgrant> The current names aren't obviously worse than the Bazaar equivalents, are they?
10:57 <wgrant> Apart from the repo vs branch stuff, nothing has changed terribly.
10:57 <cjwatson> The current names are identical to the Bazaar equivalents.
10:57 <wgrant> Right, but there's no real reason we have to change them.
10:57 <wgrant> That I can recall.
10:57 <cjwatson> That was my thought.
10:57 <cjwatson> I mean, they suck but they can suck equally.
10:57 <wgrant> It was just a "this bit of Bazaar codehosting is stupid, let's see if we can do it better before stabilising the API"
10:57 <wgrant> And at this point I think the answer is no.
10:58 <cjwatson> Like most things that talk about sources and targets etc., it's very easy to get into directional confusion.
10:58 <wgrant> Yeah
10:58 <cjwatson> Especially for this kind of thing where it's really "merge proposals for which this branch etc. is the source"
10:58 <wgrant> The least confusing thing might almost be to have lp.merge_proposals...
10:59 <wgrant> But exporting the existing properties works.
11:03 <cjwatson> lp.merge_proposals has the nice property that we could introduce it later without too much clutter, indeed.

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) :
review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/_schema_circular_imports.py'
2--- lib/lp/_schema_circular_imports.py 2015-05-15 12:20:05 +0000
3+++ lib/lp/_schema_circular_imports.py 2015-06-05 11:17:24 +0000
4@@ -562,6 +562,9 @@
5 IGitRef, 'createMergeProposal', 'merge_target', IGitRef)
6 patch_plain_parameter_type(
7 IGitRef, 'createMergeProposal', 'merge_prerequisite', IGitRef)
8+patch_collection_property(IGitRef, 'landing_targets', IBranchMergeProposal)
9+patch_collection_property(IGitRef, 'landing_candidates', IBranchMergeProposal)
10+patch_collection_property(IGitRef, 'dependent_landings', IBranchMergeProposal)
11 patch_entry_return_type(IGitRef, 'createMergeProposal', IBranchMergeProposal)
12 patch_collection_return_type(
13 IGitRef, 'getMergeProposals', IBranchMergeProposal)
14@@ -572,6 +575,12 @@
15 patch_collection_property(IGitRepository, 'subscriptions', IGitSubscription)
16 patch_entry_return_type(IGitRepository, 'subscribe', IGitSubscription)
17 patch_entry_return_type(IGitRepository, 'getSubscription', IGitSubscription)
18+patch_collection_property(
19+ IGitRepository, 'landing_targets', IBranchMergeProposal)
20+patch_collection_property(
21+ IGitRepository, 'landing_candidates', IBranchMergeProposal)
22+patch_collection_property(
23+ IGitRepository, 'dependent_landings', IBranchMergeProposal)
24
25 # ILiveFSFile
26 patch_reference_property(ILiveFSFile, 'livefsbuild', ILiveFSBuild)
27
28=== modified file 'lib/lp/code/interfaces/gitref.py'
29--- lib/lp/code/interfaces/gitref.py 2015-05-26 12:18:12 +0000
30+++ lib/lp/code/interfaces/gitref.py 2015-06-05 11:17:24 +0000
31@@ -22,6 +22,7 @@
32 REQUEST_USER,
33 )
34 from lazr.restful.fields import (
35+ CollectionField,
36 Reference,
37 ReferenceChoice,
38 )
39@@ -196,17 +197,30 @@
40 and their subscriptions.
41 """
42
43- # XXX cjwatson 2015-04-16: These names are too awful to set in stone by
44- # exporting them on the webservice; find better names before exporting.
45- landing_targets = Attribute(
46- "A collection of the merge proposals where this reference is the "
47- "source.")
48- landing_candidates = Attribute(
49- "A collection of the merge proposals where this reference is the "
50- "target.")
51- dependent_landings = Attribute(
52- "A collection of the merge proposals that are dependent on this "
53- "reference.")
54+ landing_targets = exported(CollectionField(
55+ title=_("Landing targets"),
56+ description=_(
57+ "A collection of the merge proposals where this reference is the "
58+ "source."),
59+ readonly=True,
60+ # Really IBranchMergeProposal, patched in _schema_circular_imports.py.
61+ value_type=Reference(Interface)))
62+ landing_candidates = exported(CollectionField(
63+ title=_("Landing candidates"),
64+ description=_(
65+ "A collection of the merge proposals where this reference is the "
66+ "target."),
67+ readonly=True,
68+ # Really IBranchMergeProposal, patched in _schema_circular_imports.py.
69+ value_type=Reference(Interface)))
70+ dependent_landings = exported(CollectionField(
71+ title=_("Dependent landings"),
72+ description=_(
73+ "A collection of the merge proposals that are dependent on this "
74+ "reference."),
75+ readonly=True,
76+ # Really IBranchMergeProposal, patched in _schema_circular_imports.py.
77+ value_type=Reference(Interface)))
78
79 # XXX cjwatson 2015-04-16: Rename in line with landing_targets above
80 # once we have a better name.
81
82=== modified file 'lib/lp/code/interfaces/gitrepository.py'
83--- lib/lp/code/interfaces/gitrepository.py 2015-05-26 12:18:12 +0000
84+++ lib/lp/code/interfaces/gitrepository.py 2015-06-05 11:17:24 +0000
85@@ -449,17 +449,30 @@
86 and their subscriptions.
87 """
88
89- # XXX cjwatson 2015-04-16: These names are too awful to set in stone by
90- # exporting them on the webservice; find better names before exporting.
91- landing_targets = Attribute(
92- "A collection of the merge proposals where this repository is the "
93- "source.")
94- landing_candidates = Attribute(
95- "A collection of the merge proposals where this repository is the "
96- "target.")
97- dependent_landings = Attribute(
98- "A collection of the merge proposals that are dependent on this "
99- "repository.")
100+ landing_targets = exported(CollectionField(
101+ title=_("Landing targets"),
102+ description=_(
103+ "A collection of the merge proposals where this repository is the "
104+ "source."),
105+ readonly=True,
106+ # Really IBranchMergeProposal, patched in _schema_circular_imports.py.
107+ value_type=Reference(Interface)))
108+ landing_candidates = exported(CollectionField(
109+ title=_("Landing candidates"),
110+ description=_(
111+ "A collection of the merge proposals where this repository is the "
112+ "target."),
113+ readonly=True,
114+ # Really IBranchMergeProposal, patched in _schema_circular_imports.py.
115+ value_type=Reference(Interface)))
116+ dependent_landings = exported(CollectionField(
117+ title=_("Dependent landings"),
118+ description=_(
119+ "A collection of the merge proposals that are dependent on this "
120+ "repository."),
121+ readonly=True,
122+ # Really IBranchMergeProposal, patched in _schema_circular_imports.py.
123+ value_type=Reference(Interface)))
124
125 def getMergeProposalByID(id):
126 """Return this repository's merge proposal with this id, or None."""
127
128=== modified file 'lib/lp/code/model/gitrepository.py'
129--- lib/lp/code/model/gitrepository.py 2015-06-01 16:05:12 +0000
130+++ lib/lp/code/model/gitrepository.py 2015-06-05 11:17:24 +0000
131@@ -789,7 +789,7 @@
132 """See `IGitRepository`."""
133 return Store.of(self).find(
134 BranchMergeProposal,
135- BranchMergeProposal.prerequisite_git_repository,
136+ BranchMergeProposal.prerequisite_git_repository == self,
137 Not(BranchMergeProposal.queue_status.is_in(
138 BRANCH_MERGE_PROPOSAL_FINAL_STATES)))
139
140
141=== modified file 'lib/lp/code/model/tests/test_gitref.py'
142--- lib/lp/code/model/tests/test_gitref.py 2015-05-21 16:36:14 +0000
143+++ lib/lp/code/model/tests/test_gitref.py 2015-06-05 11:17:24 +0000
144@@ -77,3 +77,50 @@
145 self.assertEqual(
146 unicode(hashlib.sha1(u"refs/heads/master").hexdigest()),
147 result["commit_sha1"])
148+
149+ def test_landing_candidates(self):
150+ bmp_db = self.factory.makeBranchMergeProposalForGit()
151+ with person_logged_in(bmp_db.registrant):
152+ bmp_url = api_url(bmp_db)
153+ ref_url = api_url(bmp_db.target_git_ref)
154+ webservice = webservice_for_person(
155+ bmp_db.registrant, permission=OAuthPermission.READ_PUBLIC)
156+ webservice.default_api_version = "devel"
157+ ref = webservice.get(ref_url).jsonBody()
158+ landing_candidates = webservice.get(
159+ ref["landing_candidates_collection_link"]).jsonBody()
160+ self.assertEqual(1, len(landing_candidates["entries"]))
161+ self.assertThat(
162+ landing_candidates["entries"][0]["self_link"], EndsWith(bmp_url))
163+
164+ def test_landing_targets(self):
165+ bmp_db = self.factory.makeBranchMergeProposalForGit()
166+ with person_logged_in(bmp_db.registrant):
167+ bmp_url = api_url(bmp_db)
168+ ref_url = api_url(bmp_db.source_git_ref)
169+ webservice = webservice_for_person(
170+ bmp_db.registrant, permission=OAuthPermission.READ_PUBLIC)
171+ webservice.default_api_version = "devel"
172+ ref = webservice.get(ref_url).jsonBody()
173+ landing_targets = webservice.get(
174+ ref["landing_targets_collection_link"]).jsonBody()
175+ self.assertEqual(1, len(landing_targets["entries"]))
176+ self.assertThat(
177+ landing_targets["entries"][0]["self_link"], EndsWith(bmp_url))
178+
179+ def test_dependent_landings(self):
180+ [ref] = self.factory.makeGitRefs()
181+ bmp_db = self.factory.makeBranchMergeProposalForGit(
182+ prerequisite_ref=ref)
183+ with person_logged_in(bmp_db.registrant):
184+ bmp_url = api_url(bmp_db)
185+ ref_url = api_url(ref)
186+ webservice = webservice_for_person(
187+ bmp_db.registrant, permission=OAuthPermission.READ_PUBLIC)
188+ webservice.default_api_version = "devel"
189+ ref = webservice.get(ref_url).jsonBody()
190+ dependent_landings = webservice.get(
191+ ref["dependent_landings_collection_link"]).jsonBody()
192+ self.assertEqual(1, len(dependent_landings["entries"]))
193+ self.assertThat(
194+ dependent_landings["entries"][0]["self_link"], EndsWith(bmp_url))
195
196=== modified file 'lib/lp/code/model/tests/test_gitrepository.py'
197--- lib/lp/code/model/tests/test_gitrepository.py 2015-06-01 23:02:20 +0000
198+++ lib/lp/code/model/tests/test_gitrepository.py 2015-06-05 11:17:24 +0000
199@@ -2082,3 +2082,50 @@
200 self.assertEqual(200, response.status)
201 with person_logged_in(subscriber_db):
202 self.assertNotIn(subscriber_db, repository_db.subscribers)
203+
204+ def test_landing_candidates(self):
205+ bmp_db = self.factory.makeBranchMergeProposalForGit()
206+ with person_logged_in(bmp_db.registrant):
207+ bmp_url = api_url(bmp_db)
208+ repository_url = api_url(bmp_db.target_git_repository)
209+ webservice = webservice_for_person(
210+ bmp_db.registrant, permission=OAuthPermission.READ_PUBLIC)
211+ webservice.default_api_version = "devel"
212+ repository = webservice.get(repository_url).jsonBody()
213+ landing_candidates = webservice.get(
214+ repository["landing_candidates_collection_link"]).jsonBody()
215+ self.assertEqual(1, len(landing_candidates["entries"]))
216+ self.assertThat(
217+ landing_candidates["entries"][0]["self_link"], EndsWith(bmp_url))
218+
219+ def test_landing_targets(self):
220+ bmp_db = self.factory.makeBranchMergeProposalForGit()
221+ with person_logged_in(bmp_db.registrant):
222+ bmp_url = api_url(bmp_db)
223+ repository_url = api_url(bmp_db.source_git_repository)
224+ webservice = webservice_for_person(
225+ bmp_db.registrant, permission=OAuthPermission.READ_PUBLIC)
226+ webservice.default_api_version = "devel"
227+ repository = webservice.get(repository_url).jsonBody()
228+ landing_targets = webservice.get(
229+ repository["landing_targets_collection_link"]).jsonBody()
230+ self.assertEqual(1, len(landing_targets["entries"]))
231+ self.assertThat(
232+ landing_targets["entries"][0]["self_link"], EndsWith(bmp_url))
233+
234+ def test_dependent_landings(self):
235+ [ref] = self.factory.makeGitRefs()
236+ bmp_db = self.factory.makeBranchMergeProposalForGit(
237+ prerequisite_ref=ref)
238+ with person_logged_in(bmp_db.registrant):
239+ bmp_url = api_url(bmp_db)
240+ repository_url = api_url(ref.repository)
241+ webservice = webservice_for_person(
242+ bmp_db.registrant, permission=OAuthPermission.READ_PUBLIC)
243+ webservice.default_api_version = "devel"
244+ repository = webservice.get(repository_url).jsonBody()
245+ dependent_landings = webservice.get(
246+ repository["dependent_landings_collection_link"]).jsonBody()
247+ self.assertEqual(1, len(dependent_landings["entries"]))
248+ self.assertThat(
249+ dependent_landings["entries"][0]["self_link"], EndsWith(bmp_url))