Merge ~twom/launchpad:git-branch-picker-unpicked-with-merge-pickers into launchpad: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)
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

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
1diff --git a/lib/lp/code/browser/gitref.py b/lib/lp/code/browser/gitref.py
2index 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)
182diff --git a/lib/lp/code/browser/tests/test_branchmergeproposal.py b/lib/lp/code/browser/tests/test_branchmergeproposal.py
183index 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
333diff --git a/lib/lp/code/interfaces/branchmergeproposal.py b/lib/lp/code/interfaces/branchmergeproposal.py
334index 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(
355diff --git a/lib/lp/code/templates/gitref-register-merge.pt b/lib/lp/code/templates/gitref-register-merge.pt
356index 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

Subscribers

People subscribed via source and target branches

to status/vote changes: