Merge ~twom/launchpad:git-branch-picker-unpicked-with-merge-pickers into launchpad:master
- Git
- lp:~twom/launchpad
- git-branch-picker-unpicked-with-merge-pickers
- Merge into master
Proposed by
Tom Wardill
Status: | Merged |
---|---|
Approved by: | Tom Wardill |
Approved revision: | 38f91a543989fa3f736697462c4c3d8823652e99 |
Merge reported by: | Otto Co-Pilot |
Merged at revision: | not available |
Proposed branch: | ~twom/launchpad:git-branch-picker-unpicked-with-merge-pickers |
Merge into: | launchpad:master |
Prerequisite: | ~twom/launchpad:git-branch-picker-unpicked |
Diff against target: |
383 lines (+70/-99) 4 files modified
lib/lp/code/browser/gitref.py (+42/-63) lib/lp/code/browser/tests/test_branchmergeproposal.py (+24/-24) lib/lp/code/interfaces/branchmergeproposal.py (+2/-2) lib/lp/code/templates/gitref-register-merge.pt (+2/-10) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Colin Watson (community) | Approve | ||
Review via email: mp+394183@code.launchpad.net |
Commit message
Add autocomplete branch picker to git merge proposal page
Description of the change
To post a comment you must log in.
Revision history for this message
Tom Wardill (twom) wrote : | # |
Revision history for this message
Colin Watson (cjwatson) : | # |
review:
Approve
Revision history for this message
Tom Wardill (twom) : | # |
Revision history for this message
Otto Co-Pilot (otto-copilot) wrote : | # |
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/lib/lp/code/browser/gitref.py b/lib/lp/code/browser/gitref.py |
2 | index f17207e..5edce2c 100644 |
3 | --- a/lib/lp/code/browser/gitref.py |
4 | +++ b/lib/lp/code/browser/gitref.py |
5 | @@ -27,9 +27,7 @@ from zope.interface import Interface |
6 | from zope.publisher.interfaces import NotFound |
7 | from zope.schema import ( |
8 | Bool, |
9 | - Choice, |
10 | Text, |
11 | - TextLine, |
12 | ) |
13 | |
14 | from lp import _ |
15 | @@ -37,11 +35,11 @@ from lp.app.browser.launchpadform import ( |
16 | action, |
17 | LaunchpadFormView, |
18 | ) |
19 | -from lp.app.widgets.suggestion import TargetGitRepositoryWidget |
20 | from lp.code.browser.branchmergeproposal import ( |
21 | latest_proposals_for_each_branch, |
22 | ) |
23 | from lp.code.browser.sourcepackagerecipelisting import HasRecipesMenuMixin |
24 | +from lp.code.browser.widgets.gitref import GitRefWidget |
25 | from lp.code.enums import GitRepositoryType |
26 | from lp.code.errors import InvalidBranchMergeProposal |
27 | from lp.code.interfaces.branchmergeproposal import IBranchMergeProposal |
28 | @@ -247,30 +245,15 @@ class GitRefView(LaunchpadView, HasSnapsViewMixin): |
29 | class GitRefRegisterMergeProposalSchema(Interface): |
30 | """The schema to define the form for registering a new merge proposal.""" |
31 | |
32 | - target_git_repository = Choice( |
33 | - title=_("Target repository"), |
34 | - vocabulary="GitRepository", required=True, readonly=True, |
35 | - description=_("The repository that the source will be merged into.")) |
36 | + target_git_ref = copy_field( |
37 | + IBranchMergeProposal['target_git_ref'], required=True) |
38 | |
39 | - target_git_path = TextLine( |
40 | - title=_("Target branch"), required=True, readonly=True, |
41 | - description=_( |
42 | - "The branch within the target repository that the source will " |
43 | - "be merged into.")) |
44 | - |
45 | - prerequisite_git_repository = Choice( |
46 | - title=_("Prerequisite repository"), |
47 | - vocabulary="GitRepository", required=False, readonly=True, |
48 | - description=_( |
49 | - "A repository containing a branch that should be merged before " |
50 | - "this one. (Its changes will not be shown in the diff.)")) |
51 | - |
52 | - prerequisite_git_path = TextLine( |
53 | - title=_("Prerequisite branch"), required=False, readonly=True, |
54 | - description=_( |
55 | - "A branch within the prerequisite repository that should be " |
56 | - "merged before this one. (Its changes will not be shown in the " |
57 | - "diff.)")) |
58 | + prerequisite_git_ref = copy_field( |
59 | + IBranchMergeProposal['prerequisite_git_ref'], required=False, |
60 | + description=_("If the target branch is based on a different branch, " |
61 | + "you can add this as a prerequisite. " |
62 | + "The changes from that branch will not show " |
63 | + "in the diff.")) |
64 | |
65 | comment = Text( |
66 | title=_('Description of the change'), required=False, |
67 | @@ -302,7 +285,10 @@ class GitRefRegisterMergeProposalView(LaunchpadFormView): |
68 | schema = GitRefRegisterMergeProposalSchema |
69 | for_input = True |
70 | |
71 | - custom_widget_target_git_repository = TargetGitRepositoryWidget |
72 | + custom_widget_target_git_ref = CustomWidgetFactory( |
73 | + GitRefWidget, require_branch=True) |
74 | + custom_widget_prerequisite_git_ref = CustomWidgetFactory( |
75 | + GitRefWidget, require_branch=True) |
76 | custom_widget_commit_message = CustomWidgetFactory( |
77 | TextAreaWidget, cssClass='comment-text') |
78 | custom_widget_comment = CustomWidgetFactory( |
79 | @@ -323,15 +309,25 @@ class GitRefRegisterMergeProposalView(LaunchpadFormView): |
80 | def setUpWidgets(self, context=None): |
81 | super(GitRefRegisterMergeProposalView, self).setUpWidgets( |
82 | context=context) |
83 | - term = next( |
84 | - iter(self.widgets['target_git_repository'].vocabulary), |
85 | - None) |
86 | - # If we have a target, and the user hasn't entered a value. |
87 | - if term and not self.widgets['target_git_path'].hasInput(): |
88 | - branch_display = term.value.default_branch |
89 | - if branch_display and branch_display.startswith("refs/heads/"): |
90 | - branch_display = branch_display[len("refs/heads/"):] |
91 | - self.widgets['target_git_path'].setRenderedValue(branch_display) |
92 | + |
93 | + if not self.widgets['target_git_ref'].hasInput(): |
94 | + if self.context.repository.namespace.has_defaults: |
95 | + repo_set = getUtility(IGitRepositorySet) |
96 | + default_repo = repo_set.getDefaultRepository( |
97 | + self.context.repository.target) |
98 | + else: |
99 | + default_repo = None |
100 | + if not default_repo: |
101 | + default_repo = self.context.repository |
102 | + if default_repo.default_branch: |
103 | + default_ref = default_repo.getRefByPath( |
104 | + default_repo.default_branch) |
105 | + with_path = True |
106 | + else: |
107 | + default_ref = self.context |
108 | + with_path = False |
109 | + self.widgets["target_git_ref"].setRenderedValue( |
110 | + default_ref, with_path=with_path) |
111 | |
112 | @action('Propose Merge', name='register', |
113 | failure=LaunchpadFormView.ajax_failure_handler) |
114 | @@ -340,15 +336,8 @@ class GitRefRegisterMergeProposalView(LaunchpadFormView): |
115 | |
116 | registrant = self.user |
117 | source_ref = self.context |
118 | - target_ref = data['target_git_repository'].getRefByPath( |
119 | - data['target_git_path']) |
120 | - if (data.get('prerequisite_git_repository') is not None and |
121 | - data.get('prerequisite_git_path') is not None): |
122 | - prerequisite_ref = ( |
123 | - data['prerequisite_git_repository'].getRefByPath( |
124 | - data['prerequisite_git_path'])) |
125 | - else: |
126 | - prerequisite_ref = None |
127 | + target_ref = data['target_git_ref'] |
128 | + prerequisite_ref = data.get('prerequisite_git_ref') |
129 | |
130 | review_requests = [] |
131 | reviewer = data.get('reviewer') |
132 | @@ -403,41 +392,31 @@ class GitRefRegisterMergeProposalView(LaunchpadFormView): |
133 | self.addError(str(error)) |
134 | |
135 | def _validateRef(self, data, name): |
136 | - repository = data.get('%s_git_repository' % name) |
137 | - path = data.get('%s_git_path' % name) |
138 | - if path: |
139 | - ref = repository.getRefByPath(path) |
140 | - else: |
141 | - ref = None |
142 | - if ref is None: |
143 | - self.setFieldError( |
144 | - '%s_git_path' % name, |
145 | - "The %s path must be the path of a reference in the " |
146 | - "%s repository." % (name, name)) |
147 | - elif ref == self.context: |
148 | + ref = data['{}_git_ref'.format(name)] |
149 | + if ref == self.context: |
150 | self.setFieldError( |
151 | - '%s_git_path' % name, |
152 | + '%s_git_ref' % name, |
153 | "The %s repository and path together cannot be the same " |
154 | "as the source repository and path." % name) |
155 | - return repository |
156 | + return ref.repository |
157 | |
158 | def validate(self, data): |
159 | source_ref = self.context |
160 | # The existence of target_git_repository is handled by the form |
161 | # machinery. |
162 | - if data.get('target_git_repository') is not None: |
163 | + if data.get('target_git_ref') is not None: |
164 | target_repository = self._validateRef(data, 'target') |
165 | if not target_repository.isRepositoryMergeable( |
166 | source_ref.repository): |
167 | self.setFieldError( |
168 | - 'target_git_repository', |
169 | + 'target_git_ref', |
170 | "%s is not mergeable into this repository." % |
171 | source_ref.repository.identity) |
172 | - if data.get('prerequisite_git_repository') is not None: |
173 | + if data.get('prerequisite_git_ref') is not None: |
174 | prerequisite_repository = self._validateRef(data, 'prerequisite') |
175 | if not target_repository.isRepositoryMergeable( |
176 | prerequisite_repository): |
177 | self.setFieldError( |
178 | - 'prerequisite_git_repository', |
179 | + 'prerequisite_git_ref', |
180 | "This repository is not mergeable into %s." % |
181 | target_repository.identity) |
182 | diff --git a/lib/lp/code/browser/tests/test_branchmergeproposal.py b/lib/lp/code/browser/tests/test_branchmergeproposal.py |
183 | index a9ac39b..fedb00d 100644 |
184 | --- a/lib/lp/code/browser/tests/test_branchmergeproposal.py |
185 | +++ b/lib/lp/code/browser/tests/test_branchmergeproposal.py |
186 | @@ -821,6 +821,7 @@ class TestRegisterBranchMergeProposalViewBzr( |
187 | target_branch.unique_name}, |
188 | **extra) |
189 | request.setPrincipal(owner) |
190 | + transaction.commit() |
191 | view = create_initialized_view( |
192 | target_branch, |
193 | name='+register-merge', |
194 | @@ -858,10 +859,7 @@ class TestRegisterBranchMergeProposalViewGit( |
195 | |
196 | @staticmethod |
197 | def _getFormValues(target_branch, extras): |
198 | - values = { |
199 | - 'target_git_repository': target_branch.repository, |
200 | - 'target_git_path': target_branch.path, |
201 | - } |
202 | + values = {'target_git_ref': target_branch} |
203 | values.update(extras) |
204 | return values |
205 | |
206 | @@ -873,17 +871,19 @@ class TestRegisterBranchMergeProposalViewGit( |
207 | view = self._createView() |
208 | self.assertEqual( |
209 | target_branch.repository.default_branch.split('/')[-1], |
210 | - view.widgets['target_git_path']._getCurrentValue()) |
211 | + view.widgets['target_git_ref'].path_widget._getCurrentValue()) |
212 | |
213 | def test_default_branch_no_default_set(self): |
214 | with admin_logged_in(): |
215 | self._makeTargetBranch(target_default=True) |
216 | view = self._createView() |
217 | - self.assertIsNone(view.widgets['target_git_path']._getCurrentValue()) |
218 | + self.assertIsNone( |
219 | + view.widgets['target_git_ref'].path_widget._getCurrentValue()) |
220 | |
221 | def test_default_branch_no_target(self): |
222 | view = self._createView() |
223 | - self.assertIsNone(view.widgets['target_git_path']._getCurrentValue()) |
224 | + self.assertIsNone( |
225 | + view.widgets['target_git_ref'].path_widget._getCurrentValue()) |
226 | |
227 | def test_register_ajax_request_with_confirmation(self): |
228 | # Ajax submits return json data containing info about what the visible |
229 | @@ -929,9 +929,9 @@ class TestRegisterBranchMergeProposalViewGit( |
230 | method='POST', |
231 | form={ |
232 | 'field.actions.register': 'Propose Merge', |
233 | - 'field.target_git_repository.target_git_repository': |
234 | + 'field.target_git_ref.repository': |
235 | target_branch.repository.unique_name, |
236 | - 'field.target_git_path': target_branch.path, |
237 | + 'field.target_git_ref.path': target_branch.path, |
238 | }, |
239 | **extra) |
240 | request.setPrincipal(owner) |
241 | @@ -944,7 +944,7 @@ class TestRegisterBranchMergeProposalViewGit( |
242 | self.assertEqual( |
243 | {'error_summary': 'There is 1 error.', |
244 | 'errors': { |
245 | - 'field.target_git_path': |
246 | + 'field.target_git_ref': |
247 | ('The target repository and path together cannot be the ' |
248 | 'same as the source repository and path.')}, |
249 | 'form_wide_errors': []}, |
250 | @@ -959,9 +959,9 @@ class TestRegisterBranchMergeProposalViewGit( |
251 | method='POST', |
252 | form={ |
253 | 'field.actions.register': 'Propose Merge', |
254 | - 'field.target_git_repository.target_git_repository': '', |
255 | - 'field.target_git_repository-empty-marker': '1', |
256 | - 'field.target_git_path': 'master', |
257 | + 'field.target_git_ref.repository': '', |
258 | + 'field.target_git_ref.repository-empty-marker': '1', |
259 | + 'field.target_git_ref.path': 'master', |
260 | }, |
261 | **extra) |
262 | request.setPrincipal(owner) |
263 | @@ -974,7 +974,7 @@ class TestRegisterBranchMergeProposalViewGit( |
264 | self.assertEqual( |
265 | {'error_summary': 'There is 1 error.', |
266 | 'errors': { |
267 | - 'field.target_git_repository': 'Required input is missing.', |
268 | + 'field.target_git_ref': 'Required input is missing.', |
269 | }, |
270 | 'form_wide_errors': []}, |
271 | simplejson.loads(view.form_result)) |
272 | @@ -984,13 +984,14 @@ class TestRegisterBranchMergeProposalViewGit( |
273 | owner = self.factory.makePerson() |
274 | target_branch = self._makeTargetBranch( |
275 | owner=owner, information_type=InformationType.USERDATA) |
276 | + transaction.commit() |
277 | extra = {'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'} |
278 | with person_logged_in(owner): |
279 | request = LaunchpadTestRequest( |
280 | method='POST', |
281 | form={ |
282 | 'field.actions.register': 'Propose Merge', |
283 | - 'field.target_git_repository.target_git_repository': |
284 | + 'field.target_git_ref.repository': |
285 | target_branch.repository.unique_name, |
286 | }, |
287 | **extra) |
288 | @@ -1004,9 +1005,8 @@ class TestRegisterBranchMergeProposalViewGit( |
289 | self.assertEqual( |
290 | {'error_summary': 'There is 1 error.', |
291 | 'errors': { |
292 | - 'field.target_git_path': |
293 | - ('The target path must be the path of a reference in the ' |
294 | - 'target repository.')}, |
295 | + 'field.target_git_ref': |
296 | + 'Please enter a Git branch path.'}, |
297 | 'form_wide_errors': []}, |
298 | simplejson.loads(view.form_result)) |
299 | |
300 | @@ -1018,16 +1018,17 @@ class TestRegisterBranchMergeProposalViewGit( |
301 | owner=owner, information_type=InformationType.USERDATA) |
302 | prerequisite_branch = self._makeTargetBranch( |
303 | owner=owner, information_type=InformationType.USERDATA) |
304 | + transaction.commit() |
305 | extra = {'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'} |
306 | with person_logged_in(owner): |
307 | request = LaunchpadTestRequest( |
308 | method='POST', |
309 | form={ |
310 | 'field.actions.register': 'Propose Merge', |
311 | - 'field.target_git_repository.target_git_repository': |
312 | + 'field.target_git_ref.repository': |
313 | target_branch.repository.unique_name, |
314 | - 'field.target_git_path': target_branch.path, |
315 | - 'field.prerequisite_git_repository': |
316 | + 'field.target_git_ref.path': target_branch.path, |
317 | + 'field.prerequisite_git_ref.repository': |
318 | prerequisite_branch.repository.unique_name, |
319 | }, |
320 | **extra) |
321 | @@ -1041,9 +1042,8 @@ class TestRegisterBranchMergeProposalViewGit( |
322 | self.assertEqual( |
323 | {'error_summary': 'There is 1 error.', |
324 | 'errors': { |
325 | - 'field.prerequisite_git_path': |
326 | - ('The prerequisite path must be the path of a reference ' |
327 | - 'in the prerequisite repository.')}, |
328 | + 'field.prerequisite_git_ref': |
329 | + 'Please enter a Git branch path.'}, |
330 | 'form_wide_errors': []}, |
331 | simplejson.loads(view.form_result)) |
332 | |
333 | diff --git a/lib/lp/code/interfaces/branchmergeproposal.py b/lib/lp/code/interfaces/branchmergeproposal.py |
334 | index bf481c9..820b7b0 100644 |
335 | --- a/lib/lp/code/interfaces/branchmergeproposal.py |
336 | +++ b/lib/lp/code/interfaces/branchmergeproposal.py |
337 | @@ -174,7 +174,7 @@ class IBranchMergeProposalPublic(IPrivacy): |
338 | target_git_commit_sha1 = TextLine( |
339 | title=_('Target Git commit SHA-1'), required=False, readonly=True) |
340 | target_git_ref = Reference( |
341 | - title=_('Target Git reference'), |
342 | + title=_('Target Git branch'), |
343 | schema=IGitRef, required=False, readonly=True) |
344 | |
345 | prerequisite_branch = exported( |
346 | @@ -205,7 +205,7 @@ class IBranchMergeProposalPublic(IPrivacy): |
347 | title=_('Prerequisite Git commit SHA-1'), |
348 | required=False, readonly=True) |
349 | prerequisite_git_ref = Reference( |
350 | - title=_('Prerequisite Git reference'), |
351 | + title=_('Prerequisite Git branch'), |
352 | schema=IGitRef, required=False, readonly=True) |
353 | |
354 | merge_source = Attribute( |
355 | diff --git a/lib/lp/code/templates/gitref-register-merge.pt b/lib/lp/code/templates/gitref-register-merge.pt |
356 | index 91a06b9..0d9df63 100644 |
357 | --- a/lib/lp/code/templates/gitref-register-merge.pt |
358 | +++ b/lib/lp/code/templates/gitref-register-merge.pt |
359 | @@ -12,11 +12,7 @@ |
360 | <metal:formbody fill-slot="widgets"> |
361 | <table class="form"> |
362 | |
363 | - <tal:widget define="widget nocall:view/widgets/target_git_repository"> |
364 | - <metal:block use-macro="context/@@launchpad_form/widget_row" /> |
365 | - </tal:widget> |
366 | - |
367 | - <tal:widget define="widget nocall:view/widgets/target_git_path"> |
368 | + <tal:widget define="widget nocall:view/widgets/target_git_ref"> |
369 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> |
370 | </tal:widget> |
371 | |
372 | @@ -40,11 +36,7 @@ |
373 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> |
374 | </tal:widget> |
375 | |
376 | - <tal:widget define="widget nocall:view/widgets/prerequisite_git_repository"> |
377 | - <metal:block use-macro="context/@@launchpad_form/widget_row" /> |
378 | - </tal:widget> |
379 | - |
380 | - <tal:widget define="widget nocall:view/widgets/prerequisite_git_path"> |
381 | + <tal:widget define="widget nocall:view/widgets/prerequisite_git_ref"> |
382 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> |
383 | </tal:widget> |
384 |
Screenshots: /people. canonical. com/~tomwardill /git-branch- picker/ Screenshot- 20201119163719- 650x173. png /people. canonical. com/~tomwardill /git-branch- picker/ Screenshot- 20201119163742- 610x156. png
https:/
https:/