Merge lp:~stevenk/launchpad/preload-landing_candidates into lp:launchpad
- preload-landing_candidates
- Merge into devel
Proposed by
Steve Kowalik
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 16507 | ||||
Proposed branch: | lp:~stevenk/launchpad/preload-landing_candidates | ||||
Merge into: | lp:launchpad | ||||
Diff against target: |
502 lines (+80/-95) 3 files modified
lib/lp/code/browser/branch.py (+8/-1) lib/lp/code/browser/tests/test_branch.py (+69/-93) lib/lp/code/configure.zcml (+3/-1) |
||||
To merge this branch: | bzr merge lp:~stevenk/launchpad/preload-landing_candidates | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
William Grant | code | Approve | |
Review via email: mp+150255@code.launchpad.net |
Commit message
Preload candidate branches in BranchView.
Description of the change
Preload candidate branches in BranchView.
Clean up a bunch of test_branch, having it use create_view or create_
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/code/browser/branch.py' |
2 | --- lib/lp/code/browser/branch.py 2013-02-21 05:43:21 +0000 |
3 | +++ lib/lp/code/browser/branch.py 2013-02-25 05:26:21 +0000 |
4 | @@ -127,11 +127,14 @@ |
5 | from lp.code.interfaces.branchmergeproposal import IBranchMergeProposal |
6 | from lp.code.interfaces.branchtarget import IBranchTarget |
7 | from lp.code.interfaces.codereviewvote import ICodeReviewVoteReference |
8 | +from lp.code.model.branch import Branch |
9 | +from lp.code.model.branchcollection import GenericBranchCollection |
10 | from lp.registry.interfaces.person import IPersonSet |
11 | from lp.registry.interfaces.productseries import IProductSeries |
12 | from lp.registry.vocabularies import UserTeamsParticipationPlusSelfVocabulary |
13 | from lp.services import searchbuilder |
14 | from lp.services.config import config |
15 | +from lp.services.database.bulk import load_related |
16 | from lp.services.database.constants import UTC_NOW |
17 | from lp.services.feeds.browser import ( |
18 | BranchFeedLink, |
19 | @@ -554,7 +557,11 @@ |
20 | @cachedproperty |
21 | def landing_candidates(self): |
22 | """Return a decorated list of landing candidates.""" |
23 | - candidates = self.context.landing_candidates |
24 | + candidates = list(self.context.landing_candidates) |
25 | + branches = load_related( |
26 | + Branch, candidates, ['source_branchID', 'prerequisite_branchID']) |
27 | + GenericBranchCollection.preloadVisibleStackedOnBranches( |
28 | + branches, self.user) |
29 | return [proposal for proposal in candidates |
30 | if check_permission('launchpad.View', proposal)] |
31 | |
32 | |
33 | === modified file 'lib/lp/code/browser/tests/test_branch.py' |
34 | --- lib/lp/code/browser/tests/test_branch.py 2012-11-14 15:45:10 +0000 |
35 | +++ lib/lp/code/browser/tests/test_branch.py 2013-02-25 05:26:21 +0000 |
36 | @@ -1,4 +1,4 @@ |
37 | -# Copyright 2009-2012 Canonical Ltd. This software is licensed under the |
38 | +# Copyright 2009-2013 Canonical Ltd. This software is licensed under the |
39 | # GNU Affero General Public License version 3 (see the file LICENSE). |
40 | |
41 | """Unit tests for BranchView.""" |
42 | @@ -10,6 +10,8 @@ |
43 | |
44 | from BeautifulSoup import BeautifulSoup |
45 | import pytz |
46 | +from storm.store import Store |
47 | +from testtools.matchers import Equals |
48 | from zope.component import getUtility |
49 | from zope.publisher.interfaces import NotFound |
50 | from zope.security.proxy import removeSecurityProxy |
51 | @@ -22,12 +24,7 @@ |
52 | BugTaskStatus, |
53 | UNRESOLVED_BUGTASK_STATUSES, |
54 | ) |
55 | -from lp.code.browser.branch import ( |
56 | - BranchMirrorStatusView, |
57 | - BranchReviewerEditView, |
58 | - BranchView, |
59 | - ) |
60 | -from lp.code.browser.branchlisting import PersonOwnedBranchesView |
61 | +from lp.code.browser.branch import BranchMirrorStatusView |
62 | from lp.code.bzr import ( |
63 | BranchFormat, |
64 | ControlFormat, |
65 | @@ -48,6 +45,7 @@ |
66 | login_person, |
67 | logout, |
68 | person_logged_in, |
69 | + StormStatementRecorder, |
70 | TestCaseWithFactory, |
71 | ) |
72 | from lp.testing.layers import ( |
73 | @@ -57,6 +55,7 @@ |
74 | from lp.testing.matchers import ( |
75 | BrowsesWithQueryLimit, |
76 | Contains, |
77 | + HasQueryCount, |
78 | ) |
79 | from lp.testing.pages import ( |
80 | extract_text, |
81 | @@ -76,7 +75,7 @@ |
82 | layer = LaunchpadFunctionalLayer |
83 | |
84 | def setUp(self): |
85 | - TestCaseWithFactory.setUp(self) |
86 | + super(TestBranchMirrorHidden, self).setUp() |
87 | config.push( |
88 | "test", dedent("""\ |
89 | [codehosting] |
90 | @@ -85,15 +84,14 @@ |
91 | |
92 | def tearDown(self): |
93 | config.pop("test") |
94 | - TestCaseWithFactory.tearDown(self) |
95 | + super(TestBranchMirrorHidden, self).tearDown() |
96 | |
97 | def testNormalBranch(self): |
98 | # A branch from a normal location is fine. |
99 | branch = self.factory.makeAnyBranch( |
100 | branch_type=BranchType.MIRRORED, |
101 | url="http://example.com/good/mirror") |
102 | - view = BranchView(branch, LaunchpadTestRequest()) |
103 | - view.initialize() |
104 | + view = create_initialized_view(branch, '+index') |
105 | self.assertTrue(view.user is None) |
106 | self.assertEqual( |
107 | "http://example.com/good/mirror", view.mirror_location) |
108 | @@ -101,10 +99,8 @@ |
109 | def testLocationlessRemoteBranch(self): |
110 | # A branch from a normal location is fine. |
111 | branch = self.factory.makeAnyBranch( |
112 | - branch_type=BranchType.REMOTE, |
113 | - url=None) |
114 | - view = BranchView(branch, LaunchpadTestRequest()) |
115 | - view.initialize() |
116 | + branch_type=BranchType.REMOTE, url=None) |
117 | + view = create_initialized_view(branch, '+index') |
118 | self.assertTrue(view.user is None) |
119 | self.assertIs(None, view.mirror_location) |
120 | |
121 | @@ -114,11 +110,9 @@ |
122 | branch = self.factory.makeAnyBranch( |
123 | branch_type=BranchType.MIRRORED, |
124 | url="http://private.example.com/bzr-mysql/mysql-5.0") |
125 | - view = BranchView(branch, LaunchpadTestRequest()) |
126 | - view.initialize() |
127 | + view = create_initialized_view(branch, '+index') |
128 | self.assertTrue(view.user is None) |
129 | - self.assertEqual( |
130 | - "<private server>", view.mirror_location) |
131 | + self.assertEqual("<private server>", view.mirror_location) |
132 | |
133 | def testHiddenBranchAsBranchOwner(self): |
134 | # A branch location with a defined private host is visible to the |
135 | @@ -126,12 +120,10 @@ |
136 | owner = self.factory.makePerson(email="eric@example.com") |
137 | branch = self.factory.makeAnyBranch( |
138 | branch_type=BranchType.MIRRORED, |
139 | - owner=owner, |
140 | - url="http://private.example.com/bzr-mysql/mysql-5.0") |
141 | + owner=owner, url="http://private.example.com/bzr-mysql/mysql-5.0") |
142 | # Now log in the owner. |
143 | login('eric@example.com') |
144 | - view = BranchView(branch, LaunchpadTestRequest()) |
145 | - view.initialize() |
146 | + view = create_initialized_view(branch, '+index') |
147 | self.assertEqual(view.user, owner) |
148 | self.assertEqual( |
149 | "http://private.example.com/bzr-mysql/mysql-5.0", |
150 | @@ -143,33 +135,26 @@ |
151 | owner = self.factory.makePerson(email="eric@example.com") |
152 | other = self.factory.makePerson(email="other@example.com") |
153 | branch = self.factory.makeAnyBranch( |
154 | - branch_type=BranchType.MIRRORED, |
155 | - owner=owner, |
156 | + branch_type=BranchType.MIRRORED, owner=owner, |
157 | url="http://private.example.com/bzr-mysql/mysql-5.0") |
158 | # Now log in the other person. |
159 | login('other@example.com') |
160 | - view = BranchView(branch, LaunchpadTestRequest()) |
161 | - view.initialize() |
162 | + view = create_initialized_view(branch, '+index') |
163 | self.assertEqual(view.user, other) |
164 | - self.assertEqual( |
165 | - "<private server>", view.mirror_location) |
166 | + self.assertEqual("<private server>", view.mirror_location) |
167 | |
168 | |
169 | class TestBranchView(BrowserTestCase): |
170 | |
171 | layer = DatabaseFunctionalLayer |
172 | |
173 | - def setUp(self): |
174 | - super(TestBranchView, self).setUp() |
175 | - self.request = LaunchpadTestRequest() |
176 | - |
177 | def testMirrorStatusMessageIsTruncated(self): |
178 | """mirror_status_message is truncated if the text is overly long.""" |
179 | branch = self.factory.makeBranch(branch_type=BranchType.MIRRORED) |
180 | branch.mirrorFailed( |
181 | "on quick brown fox the dog jumps to" * |
182 | BranchMirrorStatusView.MAXIMUM_STATUS_MESSAGE_LENGTH) |
183 | - branch_view = BranchMirrorStatusView(branch, self.request) |
184 | + branch_view = create_view(branch, '+mirror-status') |
185 | self.assertEqual( |
186 | truncate_text(branch.mirror_status_message, |
187 | branch_view.MAXIMUM_STATUS_MESSAGE_LENGTH) + ' ...', |
188 | @@ -179,7 +164,7 @@ |
189 | """mirror_status_message on the view is the same as on the branch.""" |
190 | branch = self.factory.makeBranch(branch_type=BranchType.MIRRORED) |
191 | branch.mirrorFailed("This is a short error message.") |
192 | - branch_view = BranchMirrorStatusView(branch, self.request) |
193 | + branch_view = create_view(branch, '+mirror-status') |
194 | self.assertTrue( |
195 | len(branch.mirror_status_message) |
196 | <= branch_view.MAXIMUM_STATUS_MESSAGE_LENGTH, |
197 | @@ -194,18 +179,16 @@ |
198 | def testShowMergeLinksOnManyBranchProject(self): |
199 | # The merge links are shown on projects that have multiple branches. |
200 | product = self.factory.makeProduct(name='super-awesome-project') |
201 | - branch1 = self.factory.makeAnyBranch(product=product) |
202 | + branch = self.factory.makeAnyBranch(product=product) |
203 | self.factory.makeAnyBranch(product=product) |
204 | - view = BranchView(branch1, self.request) |
205 | - view.initialize() |
206 | + view = create_initialized_view(branch, '+index') |
207 | self.assertTrue(view.show_merge_links) |
208 | |
209 | def testShowMergeLinksOnJunkBranch(self): |
210 | # The merge links are not shown on junk branches because they do not |
211 | # support merge proposals. |
212 | junk_branch = self.factory.makeBranch(product=None) |
213 | - view = BranchView(junk_branch, self.request) |
214 | - view.initialize() |
215 | + view = create_initialized_view(junk_branch, '+index') |
216 | self.assertFalse(view.show_merge_links) |
217 | |
218 | def testShowMergeLinksOnSingleBranchProject(self): |
219 | @@ -213,17 +196,14 @@ |
220 | # only has one branch because it's pointless to propose it for merging |
221 | # if there's nothing to merge into. |
222 | branch = self.factory.makeAnyBranch() |
223 | - view = BranchView(branch, self.request) |
224 | - view.initialize() |
225 | + view = create_initialized_view(branch, '+index') |
226 | self.assertFalse(view.show_merge_links) |
227 | |
228 | def testNoProductSeriesPushingTranslations(self): |
229 | # By default, a branch view shows no product series pushing |
230 | # translations to the branch. |
231 | branch = self.factory.makeBranch() |
232 | - |
233 | - view = BranchView(branch, self.request) |
234 | - view.initialize() |
235 | + view = create_initialized_view(branch, '+index') |
236 | self.assertEqual(list(view.translations_sources()), []) |
237 | |
238 | def testProductSeriesPushingTranslations(self): |
239 | @@ -233,16 +213,13 @@ |
240 | trunk = product.getSeries('trunk') |
241 | branch = self.factory.makeBranch(owner=product.owner) |
242 | removeSecurityProxy(trunk).translations_branch = branch |
243 | - |
244 | - view = BranchView(branch, self.request) |
245 | - view.initialize() |
246 | + view = create_initialized_view(branch, '+index') |
247 | self.assertEqual(list(view.translations_sources()), [trunk]) |
248 | |
249 | def test_is_empty_directory(self): |
250 | # Branches are considered empty until they get a control format. |
251 | branch = self.factory.makeBranch() |
252 | - view = BranchView(branch, self.request) |
253 | - view.initialize() |
254 | + view = create_initialized_view(branch, '+index') |
255 | self.assertTrue(view.is_empty_directory) |
256 | with person_logged_in(branch.owner): |
257 | # Make it look as though the branch has been pushed. |
258 | @@ -541,6 +518,24 @@ |
259 | browser = self.getUserBrowser(url, user=user) |
260 | self.assertIn(product_name, browser.contents) |
261 | |
262 | + def test_query_count_landing_candidates(self): |
263 | + product = self.factory.makeProduct() |
264 | + branch = self.factory.makeBranch(product=product) |
265 | + for i in range(10): |
266 | + self.factory.makeBranchMergeProposal(target_branch=branch) |
267 | + stacked = self.factory.makeBranch(product=product) |
268 | + source = self.factory.makeBranch(stacked_on=stacked, product=product) |
269 | + prereq = self.factory.makeBranch(product=product) |
270 | + self.factory.makeBranchMergeProposal( |
271 | + source_branch=source, target_branch=branch, |
272 | + prerequisite_branch=prereq) |
273 | + Store.of(branch).flush() |
274 | + Store.of(branch).invalidate() |
275 | + view = create_view(branch, '+index') |
276 | + with StormStatementRecorder() as recorder: |
277 | + view.landing_candidates |
278 | + self.assertThat(recorder, HasQueryCount(Equals(5))) |
279 | + |
280 | |
281 | class TestBranchViewPrivateArtifacts(BrowserTestCase): |
282 | """ Tests that branches with private team artifacts can be viewed. |
283 | @@ -733,28 +728,23 @@ |
284 | # the branch. |
285 | branch = self.factory.makeAnyBranch() |
286 | self.assertIs(None, branch.reviewer) |
287 | - view = BranchReviewerEditView(branch, LaunchpadTestRequest()) |
288 | - self.assertEqual( |
289 | - branch.owner, |
290 | - view.initial_values['reviewer']) |
291 | + view = create_view(branch, '+reviewer') |
292 | + self.assertEqual(branch.owner, view.initial_values['reviewer']) |
293 | |
294 | def test_initial_reviewer_set(self): |
295 | # If the reviewer has been set, it is shown as the initial value. |
296 | branch = self.factory.makeAnyBranch() |
297 | login_person(branch.owner) |
298 | branch.reviewer = self.factory.makePerson() |
299 | - view = BranchReviewerEditView(branch, LaunchpadTestRequest()) |
300 | - self.assertEqual( |
301 | - branch.reviewer, |
302 | - view.initial_values['reviewer']) |
303 | + view = create_view(branch, '+reviewer') |
304 | + self.assertEqual(branch.reviewer, view.initial_values['reviewer']) |
305 | |
306 | def test_set_reviewer(self): |
307 | # Test setting the reviewer. |
308 | branch = self.factory.makeAnyBranch() |
309 | reviewer = self.factory.makePerson() |
310 | login_person(branch.owner) |
311 | - view = BranchReviewerEditView(branch, LaunchpadTestRequest()) |
312 | - view.initialize() |
313 | + view = create_initialized_view(branch, '+reviewer') |
314 | view.change_action.success({'reviewer': reviewer}) |
315 | self.assertEqual(reviewer, branch.reviewer) |
316 | # Last modified has been updated. |
317 | @@ -767,8 +757,7 @@ |
318 | branch = self.factory.makeAnyBranch() |
319 | login_person(branch.owner) |
320 | branch.reviewer = self.factory.makePerson() |
321 | - view = BranchReviewerEditView(branch, LaunchpadTestRequest()) |
322 | - view.initialize() |
323 | + view = create_initialized_view(branch, '+reviewer') |
324 | view.change_action.success({'reviewer': branch.owner}) |
325 | self.assertIs(None, branch.reviewer) |
326 | # Last modified has been updated. |
327 | @@ -781,8 +770,7 @@ |
328 | # modified is not updated. |
329 | modified_date = datetime(2007, 1, 1, tzinfo=pytz.UTC) |
330 | branch = self.factory.makeAnyBranch(date_created=modified_date) |
331 | - view = BranchReviewerEditView(branch, LaunchpadTestRequest()) |
332 | - view.initialize() |
333 | + view = create_initialized_view(branch, '+reviewer') |
334 | view.change_action.success({'reviewer': branch.owner}) |
335 | self.assertIs(None, branch.reviewer) |
336 | # Last modified has not been updated. |
337 | @@ -803,8 +791,8 @@ |
338 | # the development focus branch. |
339 | login_person(product.owner) |
340 | product.development_focus.branch = branch |
341 | - view = PersonOwnedBranchesView(branch.owner, LaunchpadTestRequest()) |
342 | - view.initialize() |
343 | + view = create_initialized_view( |
344 | + branch.owner, '+ownedbranches', rootsite='code') |
345 | navigator = view.branches() |
346 | [decorated_branch] = navigator.branches |
347 | self.assertEqual("lp://dev/fooix", decorated_branch.bzr_identity) |
348 | @@ -815,15 +803,12 @@ |
349 | |
350 | layer = DatabaseFunctionalLayer |
351 | |
352 | - def setUp(self): |
353 | - TestCaseWithFactory.setUp(self) |
354 | - |
355 | def test_public_target(self): |
356 | # If the user can see the target, then there are merges, and the |
357 | # landing_target is available for the template rendering. |
358 | bmp = self.factory.makeBranchMergeProposal() |
359 | branch = bmp.source_branch |
360 | - view = BranchView(branch, LaunchpadTestRequest()) |
361 | + view = create_view(branch, '+index') |
362 | self.assertFalse(view.no_merges) |
363 | [target] = view.landing_targets |
364 | # Check the ids as the target is a DecoratedMergeProposal. |
365 | @@ -835,7 +820,7 @@ |
366 | branch = bmp.source_branch |
367 | removeSecurityProxy(bmp.target_branch).information_type = ( |
368 | InformationType.USERDATA) |
369 | - view = BranchView(branch, LaunchpadTestRequest()) |
370 | + view = create_view(branch, '+index') |
371 | self.assertTrue(view.no_merges) |
372 | self.assertEqual([], view.landing_targets) |
373 | |
374 | @@ -844,7 +829,7 @@ |
375 | # landing_candidate is available for the template rendering. |
376 | bmp = self.factory.makeBranchMergeProposal() |
377 | branch = bmp.target_branch |
378 | - view = BranchView(branch, LaunchpadTestRequest()) |
379 | + view = create_view(branch, '+index') |
380 | self.assertFalse(view.no_merges) |
381 | [candidate] = view.landing_candidates |
382 | # Check the ids as the target is a DecoratedMergeProposal. |
383 | @@ -857,7 +842,7 @@ |
384 | branch = bmp.target_branch |
385 | removeSecurityProxy(bmp.source_branch).information_type = ( |
386 | InformationType.USERDATA) |
387 | - view = BranchView(branch, LaunchpadTestRequest()) |
388 | + view = create_view(branch, '+index') |
389 | self.assertTrue(view.no_merges) |
390 | self.assertEqual([], view.landing_candidates) |
391 | |
392 | @@ -866,7 +851,7 @@ |
393 | # there are merges. |
394 | branch = self.factory.makeProductBranch() |
395 | bmp = self.factory.makeBranchMergeProposal(prerequisite_branch=branch) |
396 | - view = BranchView(branch, LaunchpadTestRequest()) |
397 | + view = create_view(branch, '+index') |
398 | self.assertFalse(view.no_merges) |
399 | [proposal] = view.dependent_branches |
400 | self.assertEqual(bmp, proposal) |
401 | @@ -878,7 +863,7 @@ |
402 | bmp = self.factory.makeBranchMergeProposal(prerequisite_branch=branch) |
403 | removeSecurityProxy(bmp.source_branch).information_type = ( |
404 | InformationType.USERDATA) |
405 | - view = BranchView(branch, LaunchpadTestRequest()) |
406 | + view = create_view(branch, '+index') |
407 | self.assertTrue(view.no_merges) |
408 | self.assertEqual([], view.dependent_branches) |
409 | |
410 | @@ -1009,8 +994,7 @@ |
411 | browser.getControl("Change Branch").click() |
412 | self.assertThat( |
413 | browser.contents, |
414 | - Contains( |
415 | - 'Public branches are not allowed for target Commercial.')) |
416 | + Contains('Public branches are not allowed for target Commercial.')) |
417 | with person_logged_in(owner): |
418 | self.assertEquals(initial_target, branch.target.context) |
419 | |
420 | @@ -1026,8 +1010,7 @@ |
421 | browser.getControl("Private", index=1).click() |
422 | browser.getControl("Change Branch").click() |
423 | with person_logged_in(person): |
424 | - self.assertEqual( |
425 | - InformationType.USERDATA, branch.information_type) |
426 | + self.assertEqual(InformationType.USERDATA, branch.information_type) |
427 | |
428 | def test_can_not_change_privacy_of_stacked_on_private(self): |
429 | # The privacy field is not shown if the branch is stacked on a |
430 | @@ -1042,8 +1025,7 @@ |
431 | with person_logged_in(owner): |
432 | browser = self.getUserBrowser( |
433 | canonical_url(branch) + '/+edit', user=owner) |
434 | - self.assertRaises( |
435 | - LookupError, browser.getControl, "Information Type") |
436 | + self.assertRaises(LookupError, browser.getControl, "Information Type") |
437 | |
438 | def test_edit_view_ajax_render(self): |
439 | # An information type change request is processed as expected when an |
440 | @@ -1058,11 +1040,10 @@ |
441 | 'field.information_type': 'PUBLICSECURITY'}, |
442 | **extra) |
443 | with person_logged_in(person): |
444 | - view = create_view( |
445 | + view = create_initialized_view( |
446 | branch, name='+edit-information-type', |
447 | request=request, principal=person) |
448 | request.traversed_objects = [person, branch.product, branch, view] |
449 | - view.initialize() |
450 | result = view.render() |
451 | self.assertEqual('', result) |
452 | self.assertEqual( |
453 | @@ -1088,10 +1069,8 @@ |
454 | branch = self.factory.makeBranch( |
455 | information_type=InformationType.PUBLIC) |
456 | self.assertShownTypes( |
457 | - [InformationType.PUBLIC, |
458 | - InformationType.PUBLICSECURITY, |
459 | - InformationType.PRIVATESECURITY, |
460 | - InformationType.USERDATA], |
461 | + [InformationType.PUBLIC, InformationType.PUBLICSECURITY, |
462 | + InformationType.PRIVATESECURITY, InformationType.USERDATA], |
463 | branch) |
464 | |
465 | def test_branch_with_disallowed_type(self): |
466 | @@ -1103,12 +1082,9 @@ |
467 | branch = self.factory.makeBranch( |
468 | product=product, information_type=InformationType.PROPRIETARY) |
469 | self.assertShownTypes( |
470 | - [InformationType.PUBLIC, |
471 | - InformationType.PUBLICSECURITY, |
472 | - InformationType.PRIVATESECURITY, |
473 | - InformationType.USERDATA, |
474 | - InformationType.PROPRIETARY], |
475 | - branch) |
476 | + [InformationType.PUBLIC, InformationType.PUBLICSECURITY, |
477 | + InformationType.PRIVATESECURITY, InformationType.USERDATA, |
478 | + InformationType.PROPRIETARY], branch) |
479 | |
480 | def test_stacked_on_private(self): |
481 | # A branch stacked on a private branch has its choices limited |
482 | |
483 | === modified file 'lib/lp/code/configure.zcml' |
484 | --- lib/lp/code/configure.zcml 2013-01-22 02:06:41 +0000 |
485 | +++ lib/lp/code/configure.zcml 2013-02-25 05:26:21 +0000 |
486 | @@ -1,4 +1,4 @@ |
487 | -<!-- Copyright 2009-2011 Canonical Ltd. This software is licensed under the |
488 | +<!-- Copyright 2009-2013 Canonical Ltd. This software is licensed under the |
489 | GNU Affero General Public License version 3 (see the file LICENSE). |
490 | --> |
491 | |
492 | @@ -223,8 +223,10 @@ |
493 | id |
494 | registrant |
495 | source_branch |
496 | + source_branchID |
497 | target_branch |
498 | prerequisite_branch |
499 | + prerequisite_branchID |
500 | description |
501 | whiteboard |
502 | queue_status |