Merge lp:~thumper/launchpad/bug-branch-proposal-view into lp:launchpad
- bug-branch-proposal-view
- Merge into devel
Proposed by
Tim Penhey
Status: | Merged |
---|---|
Merged at revision: | not available |
Proposed branch: | lp:~thumper/launchpad/bug-branch-proposal-view |
Merge into: | lp:launchpad |
Prerequisite: | lp:~thumper/launchpad/project-sourcecode |
Diff against target: |
640 lines (+233/-57) 10 files modified
lib/lp/code/browser/branchmergeproposal.py (+19/-1) lib/lp/code/browser/configure.zcml (+10/-5) lib/lp/code/browser/tests/test_branchmergeproposal.py (+55/-17) lib/lp/code/model/branchmergeproposal.py (+11/-6) lib/lp/code/stories/branches/xx-branch-merge-proposals.txt (+40/-27) lib/lp/code/templates/branch-index.pt (+4/-0) lib/lp/code/templates/branch-pending-merges.pt (+1/-0) lib/lp/code/templates/branchmergeproposal-link-summary.pt (+2/-1) lib/lp/code/templates/branchmergeproposal-vote-summary.pt (+49/-0) lib/lp/code/tests/helpers.py (+42/-0) |
To merge this branch: | bzr merge lp:~thumper/launchpad/bug-branch-proposal-view |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Barry Warsaw (community) | ui* | Approve | |
Paul Hummer (community) | ui code | Approve | |
Review via email: mp+14736@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Tim Penhey (thumper) wrote : | # |
Revision history for this message
Paul Hummer (rockstar) : | # |
review:
Approve
(ui code)
Revision history for this message
Barry Warsaw (barry) : | # |
review:
Approve
(ui*)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/lp/code/browser/branchmergeproposal.py' |
2 | --- lib/lp/code/browser/branchmergeproposal.py 2009-11-10 22:57:42 +0000 |
3 | +++ lib/lp/code/browser/branchmergeproposal.py 2009-11-18 00:28:15 +0000 |
4 | @@ -60,7 +60,8 @@ |
5 | from canonical.launchpad.webapp.breadcrumb import Breadcrumb |
6 | from canonical.launchpad.webapp.interfaces import IPrimaryContext |
7 | from canonical.launchpad.webapp.menu import NavigationMenu |
8 | -from canonical.launchpad.webapp.tales import FormattersAPI |
9 | +from canonical.launchpad.webapp.tales import ( |
10 | + DateTimeFormatterAPI, FormattersAPI) |
11 | from canonical.widgets.lazrjs import ( |
12 | TextAreaEditorWidget, vocabulary_to_choice_edit_items) |
13 | |
14 | @@ -138,6 +139,23 @@ |
15 | } |
16 | return friendly_texts[self.context.queue_status] |
17 | |
18 | + @property |
19 | + def status_title(self): |
20 | + """The title for the status text. |
21 | + |
22 | + Only set if the status is approved or rejected. |
23 | + """ |
24 | + result = '' |
25 | + if self.context.queue_status in ( |
26 | + BranchMergeProposalStatus.CODE_APPROVED, |
27 | + BranchMergeProposalStatus.REJECTED |
28 | + ): |
29 | + formatter = DateTimeFormatterAPI(self.context.date_reviewed) |
30 | + result = '%s %s' % ( |
31 | + self.context.reviewer.displayname, |
32 | + formatter.displaydate()) |
33 | + return result |
34 | + |
35 | |
36 | class BranchMergeProposalMenuMixin: |
37 | """Mixin class for merge proposal menus.""" |
38 | |
39 | === modified file 'lib/lp/code/browser/configure.zcml' |
40 | --- lib/lp/code/browser/configure.zcml 2009-11-13 20:12:17 +0000 |
41 | +++ lib/lp/code/browser/configure.zcml 2009-11-18 00:28:15 +0000 |
42 | @@ -184,13 +184,18 @@ |
43 | name="+pagelet-summary" |
44 | template="../templates/branchmergeproposal-pagelet-summary.pt"/> |
45 | </browser:pages> |
46 | - <browser:page |
47 | - name="+votes" |
48 | + <browser:pages |
49 | for="lp.code.interfaces.branchmergeproposal.IBranchMergeProposal" |
50 | class="lp.code.browser.branchmergeproposal.BranchMergeProposalVoteView" |
51 | facet="branches" |
52 | - permission="launchpad.View" |
53 | - template="../templates/branchmergeproposal-votes.pt"/> |
54 | + permission="launchpad.View"> |
55 | + <browser:page |
56 | + name="+votes" |
57 | + template="../templates/branchmergeproposal-votes.pt"/> |
58 | + <browser:page |
59 | + name="+vote-summary" |
60 | + template="../templates/branchmergeproposal-vote-summary.pt"/> |
61 | + </browser:pages> |
62 | <browser:pages |
63 | for="lp.code.interfaces.branchmergeproposal.IBranchMergeProposal" |
64 | class="lp.code.browser.branchmergeproposal.BranchMergeProposalEditView" |
65 | @@ -276,7 +281,7 @@ |
66 | class="lp.code.browser.branchmergeproposal.BranchMergeCandidateView" |
67 | facet="branches" |
68 | permission="zope.Public" |
69 | - template="../templates/branch-merge-link-summary.pt"/> |
70 | + template="../templates/branchmergeproposal-link-summary.pt"/> |
71 | <browser:page |
72 | name="+pagelet-subscribers" |
73 | for="lp.code.interfaces.branchmergeproposal.IBranchMergeProposal" |
74 | |
75 | === modified file 'lib/lp/code/browser/tests/test_branchmergeproposal.py' |
76 | --- lib/lp/code/browser/tests/test_branchmergeproposal.py 2009-11-01 23:13:09 +0000 |
77 | +++ lib/lp/code/browser/tests/test_branchmergeproposal.py 2009-11-18 00:28:15 +0000 |
78 | @@ -7,10 +7,11 @@ |
79 | |
80 | __metaclass__ = type |
81 | |
82 | -from datetime import timedelta |
83 | +from datetime import datetime, timedelta |
84 | from difflib import unified_diff |
85 | import unittest |
86 | |
87 | +import pytz |
88 | import transaction |
89 | from zope.component import getMultiAdapter |
90 | from zope.security.interfaces import Unauthorized |
91 | @@ -66,6 +67,7 @@ |
92 | link = menu.add_comment() |
93 | self.assertTrue(menu.add_comment().enabled) |
94 | |
95 | + |
96 | class TestDecoratedCodeReviewVoteReference(TestCaseWithFactory): |
97 | |
98 | layer = DatabaseFunctionalLayer |
99 | @@ -459,13 +461,6 @@ |
100 | self.bmp = self.factory.makeBranchMergeProposal(registrant=self.user) |
101 | login_person(self.user) |
102 | |
103 | - def _createView(self): |
104 | - # Construct the view and initialize it. |
105 | - view = BranchMergeProposalView( |
106 | - self.bmp, LaunchpadTestRequest()) |
107 | - view.initialize() |
108 | - return view |
109 | - |
110 | def makeTeamReview(self): |
111 | owner = self.bmp.source_branch.owner |
112 | review_team = self.factory.makeTeam() |
113 | @@ -477,7 +472,7 @@ |
114 | albert = self.factory.makePerson() |
115 | albert.join(review.reviewer) |
116 | login_person(albert) |
117 | - view = self._createView() |
118 | + view = create_initialized_view(self.bmp, '+index') |
119 | view.claim_action.success({'review_id': review.id}) |
120 | self.assertEqual(albert, review.reviewer) |
121 | |
122 | @@ -486,13 +481,13 @@ |
123 | review = self.makeTeamReview() |
124 | albert = self.factory.makePerson() |
125 | login_person(albert) |
126 | - view = self._createView() |
127 | + view = create_initialized_view(self.bmp, '+index') |
128 | self.assertRaises(Unauthorized, view.claim_action.success, |
129 | {'review_id': review.id}) |
130 | |
131 | def test_preview_diff_text_with_no_diff(self): |
132 | """review_diff should be None when there is no context.review_diff.""" |
133 | - view = self._createView() |
134 | + view = create_initialized_view(self.bmp, '+index') |
135 | self.assertIs(None, view.preview_diff_text) |
136 | |
137 | def test_review_diff_utf8(self): |
138 | @@ -502,8 +497,9 @@ |
139 | diff = StaticDiff.acquireFromText('x', 'y', diff_bytes) |
140 | transaction.commit() |
141 | self.bmp.review_diff = diff |
142 | + view = create_initialized_view(self.bmp, '+index') |
143 | self.assertEqual(diff_bytes.decode('utf-8'), |
144 | - self._createView().preview_diff_text) |
145 | + view.preview_diff_text) |
146 | |
147 | def test_review_diff_all_chars(self): |
148 | """review_diff should work on diffs containing all possible bytes.""" |
149 | @@ -512,8 +508,9 @@ |
150 | diff = StaticDiff.acquireFromText('x', 'y', diff_bytes) |
151 | transaction.commit() |
152 | self.bmp.review_diff = diff |
153 | + view = create_initialized_view(self.bmp, '+index') |
154 | self.assertEqual(diff_bytes.decode('windows-1252', 'replace'), |
155 | - self._createView().preview_diff_text) |
156 | + view.preview_diff_text) |
157 | |
158 | def addReviewDiff(self): |
159 | review_diff_bytes = ''.join(unified_diff('', 'review')) |
160 | @@ -532,27 +529,31 @@ |
161 | def test_preview_diff_prefers_preview_diff(self): |
162 | """The preview will be used for BMP with both a review and preview.""" |
163 | preview_diff = self.addBothDiffs() |
164 | - self.assertEqual(preview_diff, self._createView().preview_diff) |
165 | + view = create_initialized_view(self.bmp, '+index') |
166 | + self.assertEqual(preview_diff, view.preview_diff) |
167 | |
168 | def test_preview_diff_uses_review_diff(self): |
169 | """The review diff will be used if there is no preview.""" |
170 | review_diff = self.addReviewDiff() |
171 | + view = create_initialized_view(self.bmp, '+index') |
172 | self.assertEqual(review_diff.diff, |
173 | - self._createView().preview_diff) |
174 | + view.preview_diff) |
175 | |
176 | def test_review_diff_text_prefers_preview_diff(self): |
177 | """The preview will be used for BMP with both a review and preview.""" |
178 | preview_diff = self.addBothDiffs() |
179 | transaction.commit() |
180 | + view = create_initialized_view(self.bmp, '+index') |
181 | self.assertEqual( |
182 | - preview_diff.text, self._createView().preview_diff_text) |
183 | + preview_diff.text, view.preview_diff_text) |
184 | |
185 | def test_linked_bugs_excludes_mutual_bugs(self): |
186 | """List bugs that are linked to the source only.""" |
187 | bug = self.factory.makeBug() |
188 | self.bmp.source_branch.linkBug(bug, self.bmp.registrant) |
189 | self.bmp.target_branch.linkBug(bug, self.bmp.registrant) |
190 | - self.assertEqual([], self._createView().linked_bugs) |
191 | + view = create_initialized_view(self.bmp, '+index') |
192 | + self.assertEqual([], view.linked_bugs) |
193 | |
194 | |
195 | class TestBranchMergeProposalChangeStatusOptions(TestCaseWithFactory): |
196 | @@ -692,5 +693,42 @@ |
197 | self.assertEqual(u'\u2615', diff_attachment.diff_text) |
198 | |
199 | |
200 | +class TestBranchMergeCandidateView(TestCaseWithFactory): |
201 | + """Test the status title for the view.""" |
202 | + |
203 | + layer = DatabaseFunctionalLayer |
204 | + |
205 | + def test_needs_review_title(self): |
206 | + # No title is set for a proposal needing review. |
207 | + bmp = self.factory.makeBranchMergeProposal( |
208 | + set_state=BranchMergeProposalStatus.NEEDS_REVIEW) |
209 | + view = create_initialized_view(bmp, '+link-summary') |
210 | + self.assertEqual('', view.status_title) |
211 | + |
212 | + def test_approved_shows_reviewer(self): |
213 | + # If the proposal is approved, the approver is shown in the title |
214 | + # along with when they approved it. |
215 | + bmp = self.factory.makeBranchMergeProposal() |
216 | + owner = bmp.target_branch.owner |
217 | + login_person(bmp.target_branch.owner) |
218 | + owner.displayname = 'Eric' |
219 | + bmp.approveBranch(owner, 'some-rev', datetime( |
220 | + year=2008, month=9, day=10, tzinfo=pytz.UTC)) |
221 | + view = create_initialized_view(bmp, '+link-summary') |
222 | + self.assertEqual('Eric on 2008-09-10', view.status_title) |
223 | + |
224 | + def test_rejected_shows_reviewer(self): |
225 | + # If the proposal is rejected, the approver is shown in the title |
226 | + # along with when they approved it. |
227 | + bmp = self.factory.makeBranchMergeProposal() |
228 | + owner = bmp.target_branch.owner |
229 | + login_person(bmp.target_branch.owner) |
230 | + owner.displayname = 'Eric' |
231 | + bmp.rejectBranch(owner, 'some-rev', datetime( |
232 | + year=2008, month=9, day=10, tzinfo=pytz.UTC)) |
233 | + view = create_initialized_view(bmp, '+link-summary') |
234 | + self.assertEqual('Eric on 2008-09-10', view.status_title) |
235 | + |
236 | + |
237 | def test_suite(): |
238 | return unittest.TestLoader().loadTestsFromName(__name__) |
239 | |
240 | === modified file 'lib/lp/code/model/branchmergeproposal.py' |
241 | --- lib/lp/code/model/branchmergeproposal.py 2009-10-05 14:17:48 +0000 |
242 | +++ lib/lp/code/model/branchmergeproposal.py 2009-11-18 00:28:15 +0000 |
243 | @@ -361,7 +361,8 @@ |
244 | # or superseded, then it is valid to be merged. |
245 | return (self.queue_status not in FINAL_STATES) |
246 | |
247 | - def _reviewProposal(self, reviewer, next_state, revision_id): |
248 | + def _reviewProposal(self, reviewer, next_state, revision_id, |
249 | + _date_reviewed=None): |
250 | """Set the proposal to one of the two review statuses.""" |
251 | # Check the reviewer can review the code for the target branch. |
252 | old_state = self.queue_status |
253 | @@ -371,21 +372,25 @@ |
254 | self._transitionToState(next_state, reviewer) |
255 | # Record the reviewer |
256 | self.reviewer = reviewer |
257 | - self.date_reviewed = UTC_NOW |
258 | + if _date_reviewed is None: |
259 | + _date_reviewed = UTC_NOW |
260 | + self.date_reviewed = _date_reviewed |
261 | # Record the reviewed revision id |
262 | self.reviewed_revision_id = revision_id |
263 | notify(BranchMergeProposalStatusChangeEvent( |
264 | self, reviewer, old_state, next_state)) |
265 | |
266 | - def approveBranch(self, reviewer, revision_id): |
267 | + def approveBranch(self, reviewer, revision_id, _date_reviewed=None): |
268 | """See `IBranchMergeProposal`.""" |
269 | self._reviewProposal( |
270 | - reviewer, BranchMergeProposalStatus.CODE_APPROVED, revision_id) |
271 | + reviewer, BranchMergeProposalStatus.CODE_APPROVED, revision_id, |
272 | + _date_reviewed) |
273 | |
274 | - def rejectBranch(self, reviewer, revision_id): |
275 | + def rejectBranch(self, reviewer, revision_id, _date_reviewed=None): |
276 | """See `IBranchMergeProposal`.""" |
277 | self._reviewProposal( |
278 | - reviewer, BranchMergeProposalStatus.REJECTED, revision_id) |
279 | + reviewer, BranchMergeProposalStatus.REJECTED, revision_id, |
280 | + _date_reviewed) |
281 | |
282 | def enqueue(self, queuer, revision_id): |
283 | """See `IBranchMergeProposal`.""" |
284 | |
285 | === modified file 'lib/lp/code/stories/branches/xx-branch-merge-proposals.txt' |
286 | --- lib/lp/code/stories/branches/xx-branch-merge-proposals.txt 2009-10-28 19:31:47 +0000 |
287 | +++ lib/lp/code/stories/branches/xx-branch-merge-proposals.txt 2009-11-18 00:28:15 +0000 |
288 | @@ -29,6 +29,8 @@ |
289 | >>> _unused = branch.subscribe(subscriber, |
290 | ... BranchSubscriptionNotificationLevel.NOEMAIL, None, |
291 | ... CodeReviewNotificationLevel.FULL) |
292 | + >>> from lp.code.tests.helpers import make_erics_fooix_project |
293 | + >>> locals().update(make_erics_fooix_project(factory)) |
294 | >>> logout() |
295 | |
296 | Any logged in user can register a merge proposal. Registering |
297 | @@ -68,7 +70,8 @@ |
298 | |
299 | Registering the merge proposal takes the user to the new merge proposal. |
300 | |
301 | - >>> print nopriv_browser.url |
302 | + >>> klingon_proposal = nopriv_browser.url |
303 | + >>> print klingon_proposal |
304 | http://code.launchpad.dev/~name12/gnome-terminal/klingon/+merge/... |
305 | |
306 | The summary reflects the selected target and prerequisite. |
307 | @@ -97,9 +100,6 @@ |
308 | ... 'Add more <b>mojo</b>') |
309 | >>> nopriv_browser.getControl('Update').click() |
310 | |
311 | - >>> print nopriv_browser.url |
312 | - http://code.launchpad.dev/~name12/gnome-terminal/klingon/+merge/1 |
313 | - |
314 | >>> print_tag_with_id(nopriv_browser.contents, 'edit-description') |
315 | Commit Message |
316 | Add more <b>mojo</b> |
317 | @@ -113,7 +113,6 @@ |
318 | for the source_branch. |
319 | |
320 | >>> login('foo.bar@canonical.com') |
321 | - >>> eric = factory.makePerson(email="eric@example.com", password="test") |
322 | >>> bmp = factory.makeBranchMergeProposal(registrant=eric) |
323 | >>> bmp_url = canonical_url(bmp) |
324 | >>> branch_url = canonical_url(bmp.source_branch) |
325 | @@ -128,14 +127,13 @@ |
326 | |
327 | >>> sample_browser = setupBrowser(auth="Basic test@canonical.com:test") |
328 | |
329 | + |
330 | Requesting reviews |
331 | ------------------ |
332 | |
333 | You can request a review of a merge proposal. |
334 | |
335 | - >>> sample_browser.open( |
336 | - ... 'http://code.launchpad.dev/~name12/gnome-terminal/klingon/+merge/1' |
337 | - ... ) |
338 | + >>> sample_browser.open(klingon_proposal) |
339 | >>> sample_browser.getLink('Request a review').click() |
340 | >>> sample_browser.getControl('Reviewer').value = 'mark' |
341 | >>> sample_browser.getControl('Review type').value = 'first' |
342 | @@ -169,7 +167,7 @@ |
343 | Reviewer Review Type Date Requested Status |
344 | Sample Person Pending [Review] |
345 | Mark Shuttleworth second ... ago Pending |
346 | - Review via email: mp+1@code.launchpad.dev |
347 | + Review via email: mp+...@code.launchpad.dev |
348 | Request another review |
349 | |
350 | |
351 | @@ -178,16 +176,14 @@ |
352 | |
353 | People not logged in cannot perform reviews. |
354 | |
355 | - >>> anon_browser.open('http://code.launchpad.dev/~name12/gnome-terminal' |
356 | - ... '/klingon/+merge/1') |
357 | + >>> anon_browser.open(klingon_proposal) |
358 | >>> link = anon_browser.getLink('[Review]') |
359 | Traceback (most recent call last): |
360 | LinkNotFoundError |
361 | |
362 | People who are logged in can perform reviews. |
363 | |
364 | - >>> nopriv_browser.open('http://code.launchpad.dev/~name12/gnome-terminal' |
365 | - ... '/klingon/+merge/1') |
366 | + >>> nopriv_browser.open(klingon_proposal) |
367 | >>> nopriv_browser.getLink('Add a review or comment').click() |
368 | >>> nopriv_browser.getControl(name='field.comment').value = "Don't like it" |
369 | >>> nopriv_browser.getControl(name='field.vote').getControl( |
370 | @@ -201,8 +197,7 @@ |
371 | |
372 | People can claim reviews for teams of which they are a member. |
373 | |
374 | - >>> sample_browser.open('http://code.launchpad.dev/~name12/gnome-terminal' |
375 | - ... '/klingon/+merge/1') |
376 | + >>> sample_browser.open(klingon_proposal) |
377 | >>> sample_browser.getLink('Request another review').click() |
378 | >>> sample_browser.getControl('Reviewer').value = 'hwdb-team' |
379 | >>> sample_browser.getControl('Review type').value = 'claimable' |
380 | @@ -213,8 +208,7 @@ |
381 | Reviewer Review Type Date Requested Status... |
382 | HWDB Team claimable ... ago Pending ... |
383 | >>> foobar_browser = setupBrowser(auth="Basic foo.bar@canonical.com:test") |
384 | - >>> foobar_browser.open('http://code.launchpad.dev/~name12/gnome-terminal' |
385 | - ... '/klingon/+merge/1') |
386 | + >>> foobar_browser.open(klingon_proposal) |
387 | >>> foobar_browser.getControl('Claim review').click() |
388 | >>> pending = find_tag_by_id( |
389 | ... foobar_browser.contents, 'code-review-votes') |
390 | @@ -230,8 +224,7 @@ |
391 | >>> foobar_browser.getLink('Reassign').click() |
392 | >>> foobar_browser.getControl('Reviewer').value = 'hwdb-team' |
393 | >>> foobar_browser.getControl('Reassign').click() |
394 | - >>> foobar_browser.open('http://code.launchpad.dev/~name12/gnome-terminal' |
395 | - ... '/klingon/+merge/1') |
396 | + >>> foobar_browser.open(klingon_proposal) |
397 | >>> pending = find_tag_by_id( |
398 | ... foobar_browser.contents, 'code-review-votes') |
399 | |
400 | @@ -248,8 +241,7 @@ |
401 | When a branch has been merged into the target branch, the proposal should |
402 | be marked as merged. |
403 | |
404 | - >>> nopriv_browser.open( |
405 | - ... 'http://code.launchpad.dev/~name12/gnome-terminal/klingon/+merge/1') |
406 | + >>> nopriv_browser.open(klingon_proposal) |
407 | |
408 | The edit icon at the end of the status allows the user to edit the status. |
409 | |
410 | @@ -264,8 +256,6 @@ |
411 | >>> nopriv_browser.getControl(name='field.queue_status').displayValue = ( |
412 | ... ['Merged']) |
413 | >>> nopriv_browser.getControl('Change Status').click() |
414 | - >>> print nopriv_browser.url |
415 | - http://code.launchpad.dev/~name12/gnome-terminal/klingon/+merge/1 |
416 | |
417 | The proposal is now shown as have being merged. |
418 | |
419 | @@ -282,6 +272,7 @@ |
420 | >>> print extract_text(find_tag_by_id( |
421 | ... sample_browser.contents, 'landing-targets')) |
422 | Merged into lp://dev/~name12/gnome-terminal/main |
423 | + ... |
424 | >>> sample_browser.getLink('Merged').click() |
425 | >>> print_summary(sample_browser) |
426 | Status: Merged |
427 | @@ -303,6 +294,7 @@ |
428 | >>> print extract_text(find_tag_by_id( |
429 | ... sample_browser.contents, 'landing-targets')) |
430 | Merged into lp://dev/~name12/gnome-terminal/main at revision 42 |
431 | + ... |
432 | |
433 | |
434 | Resubmitting proposals |
435 | @@ -315,9 +307,7 @@ |
436 | branches but with the state set to work-in-progress. |
437 | |
438 | >>> login('foo.bar@canonical.com') |
439 | - >>> fooix = factory.makeProduct(name='fooix') |
440 | - >>> target = factory.makeProductBranch(product=fooix, owner=eric) |
441 | - >>> bmp = factory.makeBranchMergeProposal(target_branch=target) |
442 | + >>> bmp = factory.makeBranchMergeProposal(target_branch=trunk) |
443 | >>> bmp_url = canonical_url(bmp) |
444 | >>> logout() |
445 | >>> eric_browser.open(bmp_url) |
446 | @@ -538,7 +528,6 @@ |
447 | Bug #...: Bug for linking (Undecided – New) |
448 | |
449 | |
450 | - |
451 | Target branch edge cases |
452 | ------------------------ |
453 | |
454 | @@ -626,3 +615,27 @@ |
455 | >>> print extract_text(get_review_diff()) |
456 | Preview Diff |
457 | Empty |
458 | + |
459 | + |
460 | +Merge proposal details shown on the branch page |
461 | +----------------------------------------------- |
462 | + |
463 | +A branch that has a merge proposal, but no requested reviews shows this on the |
464 | +branch page. |
465 | + |
466 | + >>> nopriv_browser.open('http://code.launchpad.dev/~fred/fooix/feature') |
467 | + >>> nopriv_browser.getLink('Propose for merging').click() |
468 | + >>> nopriv_browser.getControl('Reviewer').value = '' |
469 | + >>> nopriv_browser.getControl('Propose Merge').click() |
470 | + >>> nopriv_browser.getLink('lp://dev/~fred/fooix/feature').click() |
471 | + >>> print_tag_with_id(nopriv_browser.contents, 'landing-targets') |
472 | + Ready for review for merging into lp://dev/fooix |
473 | + No reviews requested |
474 | + |
475 | +If there are reviews either pending or completed these are also shown. |
476 | + |
477 | + >>> nopriv_browser.open('http://code.launchpad.dev/~fred/fooix/proposed') |
478 | + >>> print_tag_with_id(nopriv_browser.contents, 'landing-targets') |
479 | + Ready for review for merging into lp://dev/fooix |
480 | + Eric the Viking: Pending (code) requested ... ago |
481 | + Diff: 47 lines |
482 | |
483 | === modified file 'lib/lp/code/templates/branch-index.pt' |
484 | --- lib/lp/code/templates/branch-index.pt 2009-10-11 02:33:30 +0000 |
485 | +++ lib/lp/code/templates/branch-index.pt 2009-11-18 00:28:15 +0000 |
486 | @@ -25,6 +25,10 @@ |
487 | #download-url dd span.branch-url, #upload-url dd span.branch-url { |
488 | font-weight: normal; |
489 | } |
490 | + dl.reviews dd { |
491 | + padding-left: 2em; |
492 | + margin-bottom: 0; |
493 | + } |
494 | |
495 | </style> |
496 | <script type="text/javascript" |
497 | |
498 | === modified file 'lib/lp/code/templates/branch-pending-merges.pt' |
499 | --- lib/lp/code/templates/branch-pending-merges.pt 2009-09-18 21:20:42 +0000 |
500 | +++ lib/lp/code/templates/branch-pending-merges.pt 2009-11-18 00:28:15 +0000 |
501 | @@ -36,6 +36,7 @@ |
502 | <div> |
503 | <tal:merge-fragment tal:replace="structure mergeproposal/@@+link-summary" /> |
504 | </div> |
505 | + <tal:merge-fragment tal:replace="structure mergeproposal/@@+vote-summary" /> |
506 | </tal:landing-candidates> |
507 | </div> |
508 | |
509 | |
510 | === renamed file 'lib/lp/code/templates/branch-merge-link-summary.pt' => 'lib/lp/code/templates/branchmergeproposal-link-summary.pt' |
511 | --- lib/lp/code/templates/branch-merge-link-summary.pt 2009-09-22 16:31:42 +0000 |
512 | +++ lib/lp/code/templates/branchmergeproposal-link-summary.pt 2009-11-18 00:28:15 +0000 |
513 | @@ -4,7 +4,8 @@ |
514 | xmlns:i18n="http://xml.zope.org/namespaces/i18n"> |
515 | |
516 | <img src="/@@/merge-proposal-icon" /> |
517 | - <a tal:attributes="href context/fmt:url" |
518 | + <a tal:attributes="href context/fmt:url; |
519 | + title view/status_title" |
520 | tal:content="view/friendly_text">Approved</a> |
521 | <tal:for-merging condition="not: context/queue_status/enumvalue:MERGED"> |
522 | for merging |
523 | |
524 | === added file 'lib/lp/code/templates/branchmergeproposal-vote-summary.pt' |
525 | --- lib/lp/code/templates/branchmergeproposal-vote-summary.pt 1970-01-01 00:00:00 +0000 |
526 | +++ lib/lp/code/templates/branchmergeproposal-vote-summary.pt 2009-11-18 00:28:15 +0000 |
527 | @@ -0,0 +1,49 @@ |
528 | +<tal:root |
529 | + xmlns:tal="http://xml.zope.org/namespaces/tal" |
530 | + xmlns:metal="http://xml.zope.org/namespaces/metal" |
531 | + xmlns:i18n="http://xml.zope.org/namespaces/i18n"> |
532 | + |
533 | + <tal:comment condition="nothing"> |
534 | + <!-- |
535 | + Yet again we are bitten by white space issues, so some tags in this |
536 | + template have closing brackets on following lines, and not breaks |
537 | + between some tags. |
538 | + --> |
539 | + </tal:comment> |
540 | + |
541 | +<dl class="reviews"> |
542 | + <dd tal:condition="not: view/reviews"> |
543 | + No reviews requested |
544 | + </dd> |
545 | + <dd tal:repeat="review view/current_reviews"> |
546 | + <tal:reviewer replace="structure review/reviewer/fmt:link:mainsite"> |
547 | + Eric the Reviewer</tal:reviewer |
548 | + ><tal:community condition="not: review/trusted"> |
549 | + (community)</tal:community>: |
550 | + <span tal:attributes="class string:vote${review/comment/vote/name}" |
551 | + tal:content="review/status_text"> |
552 | + Approved |
553 | + </span> |
554 | + <tal:vote-tags condition="review/review_type_str"> |
555 | + (<tal:tag replace="review/review_type_str"/>) |
556 | + </tal:vote-tags> |
557 | + <tal:date replace="review/date_of_comment/fmt:displaydate" /> |
558 | + </dd> |
559 | + <dd tal:repeat="review view/requested_reviews" |
560 | + tal:attributes="id string:review-${review/reviewer/name}"> |
561 | + <tal:reviewer |
562 | + tal:replace="structure review/reviewer/fmt:link:mainsite" />: |
563 | + |
564 | + <span class="votePENDING">Pending</span> |
565 | + <tal:vote-tags condition="review/review_type_str"> |
566 | + (<tal:tag replace="review/review_type_str"/>) |
567 | + </tal:vote-tags> |
568 | + requested |
569 | + <tal:date replace="review/date_requested/fmt:approximatedate"/> |
570 | + </dd> |
571 | + <dd tal:condition="context/preview_diff"> |
572 | + Diff: <tal:diff replace="structure context/preview_diff/fmt:link"/> |
573 | + </dd> |
574 | + |
575 | +</dl> |
576 | +</tal:root> |
577 | |
578 | === modified file 'lib/lp/code/tests/helpers.py' |
579 | --- lib/lp/code/tests/helpers.py 2009-10-26 18:40:04 +0000 |
580 | +++ lib/lp/code/tests/helpers.py 2009-11-18 00:28:15 +0000 |
581 | @@ -6,10 +6,12 @@ |
582 | __metaclass__ = type |
583 | __all__ = [ |
584 | 'make_linked_package_branch', |
585 | + 'make_erics_fooix_project', |
586 | ] |
587 | |
588 | |
589 | from datetime import timedelta |
590 | +from difflib import unified_diff |
591 | from itertools import count |
592 | |
593 | from zope.component import getUtility |
594 | @@ -23,6 +25,46 @@ |
595 | from lp.testing import time_counter |
596 | |
597 | |
598 | +def make_erics_fooix_project(factory): |
599 | + """Make Eric, the Fooix project, and some branches. |
600 | + |
601 | + :return: a dict of objects to put into local scope. |
602 | + """ |
603 | + result = {} |
604 | + eric = factory.makePerson( |
605 | + name='eric', displayname='Eric the Viking', |
606 | + email='eric@example.com', password='test') |
607 | + fooix = factory.makeProduct( |
608 | + name='fooix', displayname='Fooix', owner=eric) |
609 | + trunk = factory.makeProductBranch( |
610 | + owner=eric, product=fooix, name='trunk') |
611 | + removeSecurityProxy(fooix.development_focus).branch = trunk |
612 | + # Development is done by Fred. |
613 | + fred = factory.makePerson( |
614 | + name='fred', displayname='Fred Flintstone', |
615 | + email='fred@example.com', password='test') |
616 | + feature = factory.makeProductBranch( |
617 | + owner=fred, product=fooix, name='feature') |
618 | + proposed = factory.makeProductBranch( |
619 | + owner=fred, product=fooix, name='proposed') |
620 | + bmp = proposed.addLandingTarget( |
621 | + registrant=fred, target_branch=trunk, needs_review=True, |
622 | + review_requests=[(eric, 'code')]) |
623 | + # And fake a diff. |
624 | + naked_bmp = removeSecurityProxy(bmp) |
625 | + preview = removeSecurityProxy(bmp.updatePreviewDiff( |
626 | + ''.join(unified_diff('', 'random content')), u'rev-a', u'rev-b')) |
627 | + naked_bmp.source_branch.last_scanned_id = preview.source_revision_id |
628 | + naked_bmp.target_branch.last_scanned_id = preview.target_revision_id |
629 | + preview.diff_lines_count = 47 |
630 | + preview.added_lines_count = 7 |
631 | + preview.remvoed_lines_count = 13 |
632 | + preview.diffstat = {'file1': (3, 8), 'file2': (4, 5)} |
633 | + return { |
634 | + 'eric': eric, 'fooix': fooix, 'trunk':trunk, 'feature': feature, |
635 | + 'proposed': proposed, 'fred': fred} |
636 | + |
637 | + |
638 | def make_linked_package_branch(factory, distribution=None, |
639 | sourcepackagename=None): |
640 | """Make a new package branch and make it official.""" |
Trying the prerequisite branch bit.
This branch shows more merge proposal details on the branch page.
browser/branch.py | 1
Drive by pep-8 cleanup
browser/ branchmergeprop osal.py | 20 ++++++
Define a title for the status link based on the approver/rejecter.
browser/ configure. zcml | 15 +++--
New view, and renamed an old one to be more consistent.
browser/ tests/test_ branchmergeprop osal.py | 72 +++++++ +++++++ +++++-- ----
Cleaned up a test before I realised it was the wrong one.
Added a test for the status title in the view above.
model/ branchmergeprop osal.py | 17 +++--
This change is just adding the ability to pass the review date through to the function for better testing.
stories/ branches/ xx-branch- merge-proposals .txt | 67 +++++++ ++++++- ------- --
Move some object creation out into a helper function.
Change the explicit BMP urls to use a recorded value.
Add a section at the end to show how merge proposals look on branch pages.
templates/ branch- index.pt | 4 +
Some page based styles.
templates/ branch- pending- merges. pt | 1
Add in the vote summary.
templates/ branchmergeprop osal-link- summary. pt | 3 -
Add the title to the status anchor.
templates/ branchmergeprop osal-vote- summary. pt | 49 +++++++++++++++++
Render the details.
tests/helpers.py | 42 ++++++++++++++
Create some standard people/projects for the tests.
11 files changed, 234 insertions(+), 57 deletions(-)
This branch only has the change on the branch page, but I'm expecting to have it on the bug page as well in a follow on branch.