Merge lp:~cjwatson/launchpad/codeimport-git-new-view into lp:launchpad
- codeimport-git-new-view
- Merge into devel
Proposed by
Colin Watson
Status: | Merged |
---|---|
Merged at revision: | 18242 |
Proposed branch: | lp:~cjwatson/launchpad/codeimport-git-new-view |
Merge into: | lp:launchpad |
Prerequisite: | lp:~cjwatson/launchpad/codeimport-git-worker-fixes |
Diff against target: |
560 lines (+238/-35) 7 files modified
lib/lp/code/browser/codeimport.py (+59/-16) lib/lp/code/interfaces/gitnamespace.py (+7/-0) lib/lp/code/model/codeimport.py (+0/-1) lib/lp/code/model/gitnamespace.py (+13/-0) lib/lp/code/model/tests/test_gitnamespace.py (+99/-0) lib/lp/code/stories/codeimport/xx-create-codeimport.txt (+49/-17) lib/lp/code/templates/codeimport-new.pt (+11/-1) |
To merge this branch: | bzr merge lp:~cjwatson/launchpad/codeimport-git-new-view |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
William Grant | code | Approve | |
Review via email: mp+308545@code.launchpad.net |
Commit message
Extend CodeImportNewView to be able to create Git-to-Git code imports.
Description of the change
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/codeimport.py' |
2 | --- lib/lp/code/browser/codeimport.py 2016-10-15 01:12:01 +0000 |
3 | +++ lib/lp/code/browser/codeimport.py 2016-10-15 02:22:43 +0000 |
4 | @@ -68,6 +68,7 @@ |
5 | CodeImportAlreadyRequested, |
6 | CodeImportAlreadyRunning, |
7 | CodeImportNotInReviewedState, |
8 | + GitRepositoryExists, |
9 | ) |
10 | from lp.code.interfaces.branch import ( |
11 | IBranch, |
12 | @@ -82,6 +83,10 @@ |
13 | ICodeImportSet, |
14 | ) |
15 | from lp.code.interfaces.codeimportmachine import ICodeImportMachineSet |
16 | +from lp.code.interfaces.gitnamespace import ( |
17 | + get_git_namespace, |
18 | + IGitNamespacePolicy, |
19 | + ) |
20 | from lp.registry.interfaces.product import IProduct |
21 | from lp.registry.interfaces.role import IPersonRoles |
22 | from lp.services.fields import URIField |
23 | @@ -254,9 +259,10 @@ |
24 | git_repo_url = URIField( |
25 | title=_("Repo URL"), required=False, |
26 | description=_( |
27 | - "The URL of the git repository. The HEAD branch will be " |
28 | - "imported. You can import different branches by appending " |
29 | - "',branch=$name' to the URL."), |
30 | + "The URL of the Git repository. For imports to Bazaar, the " |
31 | + "HEAD branch will be imported by default, but you can import " |
32 | + "different branches by appending ',branch=$name' to the URL. " |
33 | + "For imports to Git, the entire repository will be imported."), |
34 | allowed_schemes=["git", "http", "https"], |
35 | allow_userinfo=True, |
36 | allow_port=True, |
37 | @@ -264,6 +270,13 @@ |
38 | allow_fragment=False, |
39 | trailing_slash=False) |
40 | |
41 | + git_target_rcs_type = Choice( |
42 | + title=_("Target version control system"), |
43 | + description=_( |
44 | + "The version control system that the source code should be " |
45 | + "imported into on the Launchpad side."), |
46 | + required=False, vocabulary=TargetRevisionControlSystems) |
47 | + |
48 | bzr_branch_url = URIField( |
49 | title=_("Branch URL"), required=False, |
50 | description=_("The URL of the Bazaar branch."), |
51 | @@ -277,10 +290,10 @@ |
52 | branch_name = copy_field( |
53 | IBranch['name'], |
54 | __name__='branch_name', |
55 | - title=_('Branch Name'), |
56 | + title=_('Name'), |
57 | description=_( |
58 | - "This will be used in the branch URL to identify the " |
59 | - "imported branch. Examples: main, trunk."), |
60 | + "This will be used in the branch or repository URL to identify " |
61 | + "the import. Examples: main, trunk."), |
62 | ) |
63 | |
64 | product = Choice( |
65 | @@ -297,6 +310,7 @@ |
66 | for_input = True |
67 | |
68 | custom_widget('rcs_type', LaunchpadRadioWidget) |
69 | + custom_widget('git_target_rcs_type', LaunchpadRadioWidget) |
70 | |
71 | @property |
72 | def initial_values(self): |
73 | @@ -304,6 +318,7 @@ |
74 | 'owner': self.user, |
75 | 'rcs_type': RevisionControlSystems.BZR, |
76 | 'branch_name': 'trunk', |
77 | + 'git_target_rcs_type': TargetRevisionControlSystems.BZR, |
78 | } |
79 | |
80 | @property |
81 | @@ -365,6 +380,9 @@ |
82 | self.rcs_type_git = str(git_button) |
83 | self.rcs_type_bzr = str(bzr_button) |
84 | self.rcs_type_emptymarker = str(empty_marker) |
85 | + # This widget is only conditionally required in the rcs_type == GIT |
86 | + # case, but we still don't want a "(nothing selected)" item. |
87 | + self.widgets['git_target_rcs_type']._displayItemForMissingValue = False |
88 | |
89 | def _getImportLocation(self, data): |
90 | """Return the import location based on type.""" |
91 | @@ -385,13 +403,18 @@ |
92 | """Create the code import.""" |
93 | product = self.getProduct(data) |
94 | cvs_root, cvs_module, url = self._getImportLocation(data) |
95 | + if data['rcs_type'] == RevisionControlSystems.GIT: |
96 | + target_rcs_type = data.get( |
97 | + 'git_target_rcs_type', TargetRevisionControlSystems.BZR) |
98 | + else: |
99 | + target_rcs_type = TargetRevisionControlSystems.BZR |
100 | return getUtility(ICodeImportSet).new( |
101 | registrant=self.user, |
102 | owner=data['owner'], |
103 | context=product, |
104 | branch_name=data['branch_name'], |
105 | rcs_type=data['rcs_type'], |
106 | - target_rcs_type=TargetRevisionControlSystems.BZR, |
107 | + target_rcs_type=target_rcs_type, |
108 | url=url, |
109 | cvs_root=cvs_root, |
110 | cvs_module=cvs_module, |
111 | @@ -419,16 +442,19 @@ |
112 | except BranchExists as e: |
113 | self._setBranchExists(e.existing_branch) |
114 | return |
115 | + except GitRepositoryExists as e: |
116 | + self._setBranchExists(e.existing_repository) |
117 | + return |
118 | |
119 | # Subscribe the user. |
120 | - code_import.branch.subscribe( |
121 | + code_import.target.subscribe( |
122 | self.user, |
123 | BranchSubscriptionNotificationLevel.FULL, |
124 | BranchSubscriptionDiffSize.NODIFF, |
125 | CodeReviewNotificationLevel.NOEMAIL, |
126 | self.user) |
127 | |
128 | - self.next_url = canonical_url(code_import.branch) |
129 | + self.next_url = canonical_url(code_import.target) |
130 | |
131 | self.request.response.addNotification(""" |
132 | New code import created. The code import will start shortly.""") |
133 | @@ -440,24 +466,41 @@ |
134 | else: |
135 | return data.get('product') |
136 | |
137 | + def validate_widgets(self, data, names=None): |
138 | + """See `LaunchpadFormView`.""" |
139 | + self.widgets['git_target_rcs_type'].context.required = ( |
140 | + data.get('rcs_type') == RevisionControlSystems.GIT) |
141 | + super(CodeImportNewView, self).validate_widgets(data, names=names) |
142 | + |
143 | def validate(self, data): |
144 | """See `LaunchpadFormView`.""" |
145 | - # Make sure that the user is able to create branches for the specified |
146 | - # namespace. |
147 | + rcs_type = data['rcs_type'] |
148 | + if rcs_type == RevisionControlSystems.GIT: |
149 | + target_rcs_type = data.get( |
150 | + 'git_target_rcs_type', TargetRevisionControlSystems.BZR) |
151 | + else: |
152 | + target_rcs_type = TargetRevisionControlSystems.BZR |
153 | + |
154 | + # Make sure that the user is able to create branches/repositories |
155 | + # for the specified namespace. |
156 | product = self.getProduct(data) |
157 | # 'owner' in data may be None if it failed validation. |
158 | owner = data.get('owner') |
159 | if product is not None and owner is not None: |
160 | - namespace = get_branch_namespace(owner, product) |
161 | - policy = IBranchNamespacePolicy(namespace) |
162 | - if not policy.canCreateBranches(self.user): |
163 | + if target_rcs_type == TargetRevisionControlSystems.BZR: |
164 | + namespace = get_branch_namespace(owner, product) |
165 | + policy = IBranchNamespacePolicy(namespace) |
166 | + can_create = policy.canCreateBranches(self.user) |
167 | + else: |
168 | + namespace = get_git_namespace(product, owner) |
169 | + policy = IGitNamespacePolicy(namespace) |
170 | + can_create = policy.canCreateRepositories(self.user) |
171 | + if not can_create: |
172 | self.setFieldError( |
173 | 'product', |
174 | "You are not allowed to register imports for %s." |
175 | % product.displayname) |
176 | |
177 | - rcs_type = data['rcs_type'] |
178 | - target_rcs_type = TargetRevisionControlSystems.BZR |
179 | # Make sure fields for unselected revision control systems |
180 | # are blanked out: |
181 | if rcs_type == RevisionControlSystems.CVS: |
182 | |
183 | === modified file 'lib/lp/code/interfaces/gitnamespace.py' |
184 | --- lib/lp/code/interfaces/gitnamespace.py 2016-10-12 23:24:24 +0000 |
185 | +++ lib/lp/code/interfaces/gitnamespace.py 2016-10-15 02:22:43 +0000 |
186 | @@ -104,6 +104,13 @@ |
187 | "Can recipe names reasonably be generated from the target name " |
188 | "rather than the branch name?") |
189 | |
190 | + def canCreateRepositories(user): |
191 | + """Is the user allowed to create repositories for this namespace? |
192 | + |
193 | + :param user: An `IPerson`. |
194 | + :return: A Boolean value. |
195 | + """ |
196 | + |
197 | def getAllowedInformationTypes(who): |
198 | """Get the information types that a repository in this namespace can |
199 | have. |
200 | |
201 | === modified file 'lib/lp/code/model/codeimport.py' |
202 | --- lib/lp/code/model/codeimport.py 2016-10-15 01:47:26 +0000 |
203 | +++ lib/lp/code/model/codeimport.py 2016-10-15 02:22:43 +0000 |
204 | @@ -63,7 +63,6 @@ |
205 | from lp.code.interfaces.githosting import IGitHostingClient |
206 | from lp.code.interfaces.gitnamespace import get_git_namespace |
207 | from lp.code.interfaces.gitrepository import IGitRepository |
208 | -from lp.code.interfaces.hasbranches import IHasCodeImports |
209 | from lp.code.interfaces.hasgitrepositories import IHasGitRepositories |
210 | from lp.code.mail.codeimport import code_import_updated |
211 | from lp.code.model.codeimportjob import CodeImportJobWorkflow |
212 | |
213 | === modified file 'lib/lp/code/model/gitnamespace.py' |
214 | --- lib/lp/code/model/gitnamespace.py 2016-10-12 23:24:24 +0000 |
215 | +++ lib/lp/code/model/gitnamespace.py 2016-10-15 02:22:43 +0000 |
216 | @@ -211,6 +211,19 @@ |
217 | match = default |
218 | return match |
219 | |
220 | + def canCreateRepositories(self, user): |
221 | + """See `IGitNamespacePolicy`.""" |
222 | + try: |
223 | + self.validateRegistrant(user) |
224 | + except GitRepositoryCreatorNotMemberOfOwnerTeam: |
225 | + return False |
226 | + except GitRepositoryCreatorNotOwner: |
227 | + return False |
228 | + except GitRepositoryCreationForbidden: |
229 | + return False |
230 | + else: |
231 | + return True |
232 | + |
233 | def getAllowedInformationTypes(self, who=None): |
234 | """See `IGitNamespace`.""" |
235 | raise NotImplementedError |
236 | |
237 | === modified file 'lib/lp/code/model/tests/test_gitnamespace.py' |
238 | --- lib/lp/code/model/tests/test_gitnamespace.py 2016-10-05 10:18:56 +0000 |
239 | +++ lib/lp/code/model/tests/test_gitnamespace.py 2016-10-15 02:22:43 +0000 |
240 | @@ -520,6 +520,105 @@ |
241 | self.assertEqual(dsp, namespace.target) |
242 | |
243 | |
244 | +class BaseCanCreateRepositoriesMixin: |
245 | + """Common tests for all namespaces.""" |
246 | + |
247 | + layer = DatabaseFunctionalLayer |
248 | + |
249 | + def _getNamespace(self, owner): |
250 | + # Return a namespace appropriate for the owner specified. |
251 | + raise NotImplementedError(self._getNamespace) |
252 | + |
253 | + def test_individual(self): |
254 | + # For a GitNamespace for an individual, only the individual can own |
255 | + # repositories there. |
256 | + person = self.factory.makePerson() |
257 | + namespace = self._getNamespace(person) |
258 | + self.assertTrue(namespace.canCreateRepositories(person)) |
259 | + |
260 | + def test_other_user(self): |
261 | + # Any other individual cannot own repositories targeted to the |
262 | + # person. |
263 | + person = self.factory.makePerson() |
264 | + namespace = self._getNamespace(person) |
265 | + self.assertFalse( |
266 | + namespace.canCreateRepositories(self.factory.makePerson())) |
267 | + |
268 | + def test_team_member(self): |
269 | + # A member of a team is able to create a repository in this |
270 | + # namespace. |
271 | + person = self.factory.makePerson() |
272 | + self.factory.makeTeam(owner=person) |
273 | + namespace = self._getNamespace(person) |
274 | + self.assertTrue(namespace.canCreateRepositories(person)) |
275 | + |
276 | + def test_team_non_member(self): |
277 | + # A person who is not part of the team cannot create repositories |
278 | + # for the personal team target. |
279 | + person = self.factory.makePerson() |
280 | + self.factory.makeTeam(owner=person) |
281 | + namespace = self._getNamespace(person) |
282 | + self.assertFalse( |
283 | + namespace.canCreateRepositories(self.factory.makePerson())) |
284 | + |
285 | + |
286 | +class TestPersonalGitNamespaceCanCreateRepositories( |
287 | + TestCaseWithFactory, BaseCanCreateRepositoriesMixin): |
288 | + |
289 | + def _getNamespace(self, owner): |
290 | + return PersonalGitNamespace(owner) |
291 | + |
292 | + |
293 | +class TestPackageGitNamespaceCanCreateBranches( |
294 | + TestCaseWithFactory, BaseCanCreateRepositoriesMixin): |
295 | + |
296 | + def _getNamespace(self, owner): |
297 | + source_package = self.factory.makeSourcePackage() |
298 | + return PackageGitNamespace(owner, source_package) |
299 | + |
300 | + |
301 | +class TestProjectGitNamespaceCanCreateBranches( |
302 | + TestCaseWithFactory, BaseCanCreateRepositoriesMixin): |
303 | + |
304 | + def _getNamespace(self, owner, |
305 | + branch_sharing_policy=BranchSharingPolicy.PUBLIC): |
306 | + project = self.factory.makeProduct( |
307 | + branch_sharing_policy=branch_sharing_policy) |
308 | + return ProjectGitNamespace(owner, project) |
309 | + |
310 | + def setUp(self): |
311 | + # Setting visibility policies is an admin-only task. |
312 | + super(TestProjectGitNamespaceCanCreateBranches, self).setUp( |
313 | + "admin@canonical.com") |
314 | + |
315 | + def test_any_person(self): |
316 | + # If there is no privacy set up, any person can create a personal |
317 | + # branch on the product. |
318 | + person = self.factory.makePerson() |
319 | + namespace = self._getNamespace(person, BranchSharingPolicy.PUBLIC) |
320 | + self.assertTrue(namespace.canCreateRepositories(person)) |
321 | + |
322 | + def test_any_person_with_proprietary_repositories(self): |
323 | + # If the sharing policy defaults to PROPRIETARY, then non-privileged |
324 | + # users cannot create a repository. |
325 | + person = self.factory.makePerson() |
326 | + namespace = self._getNamespace(person, BranchSharingPolicy.PROPRIETARY) |
327 | + self.assertFalse(namespace.canCreateRepositories(person)) |
328 | + |
329 | + def test_grantee_with_proprietary_repositories(self): |
330 | + # If the sharing policy defaults to PROPRIETARY, then non-privileged |
331 | + # users cannot create a repository. |
332 | + person = self.factory.makePerson() |
333 | + other_person = self.factory.makePerson() |
334 | + team = self.factory.makeTeam(members=[person]) |
335 | + namespace = self._getNamespace(team, BranchSharingPolicy.PROPRIETARY) |
336 | + getUtility(IService, "sharing").sharePillarInformation( |
337 | + namespace.target, team, namespace.target.owner, |
338 | + {InformationType.PROPRIETARY: SharingPermission.ALL}) |
339 | + self.assertTrue(namespace.canCreateRepositories(person)) |
340 | + self.assertFalse(namespace.canCreateRepositories(other_person)) |
341 | + |
342 | + |
343 | class TestNamespaceSet(TestCaseWithFactory): |
344 | """Tests for `get_namespace`.""" |
345 | |
346 | |
347 | === modified file 'lib/lp/code/stories/codeimport/xx-create-codeimport.txt' |
348 | --- lib/lp/code/stories/codeimport/xx-create-codeimport.txt 2016-10-13 14:46:41 +0000 |
349 | +++ lib/lp/code/stories/codeimport/xx-create-codeimport.txt 2016-10-15 02:22:43 +0000 |
350 | @@ -66,7 +66,7 @@ |
351 | The user is required to enter a project that the import is for, a name |
352 | for the import branch, and a Bazaar branch location. |
353 | |
354 | - >>> browser.getControl('Branch Name').value = "mirrored" |
355 | + >>> browser.getControl('Name').value = "mirrored" |
356 | >>> browser.getControl('Branch URL', index=0).value = ( |
357 | ... "http://bzr.example.com/firefox/trunk") |
358 | >>> browser.getControl('Request Import').click() |
359 | @@ -87,7 +87,7 @@ |
360 | URL. |
361 | |
362 | >>> browser.open("http://code.launchpad.dev/+code-imports/+new") |
363 | - >>> browser.getControl('Branch Name').value = "with-password" |
364 | + >>> browser.getControl('Name').value = "with-password" |
365 | >>> browser.getControl('Branch URL', index=0).value = ( |
366 | ... "http://user:password@bzr.example.com/firefox/trunk") |
367 | >>> browser.getControl('Project').value = "firefox" |
368 | @@ -102,7 +102,7 @@ |
369 | Specifying a Launchpad URL results in an error. |
370 | |
371 | >>> browser.open("http://code.launchpad.dev/+code-imports/+new") |
372 | - >>> browser.getControl('Branch Name').value = "invalid" |
373 | + >>> browser.getControl('Name').value = "invalid" |
374 | >>> browser.getControl('Branch URL', index=0).value = ( |
375 | ... "http://bazaar.launchpad.net/firefox/trunk") |
376 | >>> browser.getControl('Project').value = "firefox" |
377 | @@ -116,7 +116,7 @@ |
378 | |
379 | >>> browser.open("http://code.launchpad.dev/+code-imports/+new") |
380 | >>> browser.getControl('Project').value = "firefox" |
381 | - >>> browser.getControl('Branch Name').value = "lp-git-import" |
382 | + >>> browser.getControl('Name').value = "lp-git-import" |
383 | >>> browser.getControl('Git').click() |
384 | >>> browser.getControl('Repo URL', index=0).value = ( |
385 | ... "git://git.launchpad.net/firefox.git") |
386 | @@ -136,7 +136,7 @@ |
387 | >>> browser.open("http://code.launchpad.dev/+code-imports/+new") |
388 | >>> browser.getControl('Subversion').click() |
389 | >>> browser.getControl('Project').value = "firefox" |
390 | - >>> browser.getControl('Branch Name').value = "imported" |
391 | + >>> browser.getControl('Name').value = "imported" |
392 | >>> browser.getControl('Branch URL', index=1).value = ( |
393 | ... "http://svn.example.com/firefox/trunk") |
394 | >>> browser.getControl('Request Import').click() |
395 | @@ -167,7 +167,7 @@ |
396 | |
397 | >>> browser.open("http://code.launchpad.dev/+code-imports/+new") |
398 | >>> browser.getControl('Subversion').click() |
399 | - >>> browser.getControl('Branch Name').value = "svn-with-password" |
400 | + >>> browser.getControl('Name').value = "svn-with-password" |
401 | >>> browser.getControl('Branch URL', index=1).value = ( |
402 | ... "http://user:password@svn.example.com/firefox/trunk") |
403 | >>> browser.getControl('Project').value = "firefox" |
404 | @@ -180,21 +180,21 @@ |
405 | as soon as possible. |
406 | |
407 | |
408 | -Requesting a Git import |
409 | -======================= |
410 | +Requesting a Git-to-Bazaar import |
411 | +================================= |
412 | |
413 | The user is required to enter a project that the import is for, |
414 | -a name for the import branch, and a subversion branch location. |
415 | +a name for the import branch, and a Git repository location. |
416 | |
417 | >>> browser.open("http://code.launchpad.dev/+code-imports/+new") |
418 | >>> browser.getControl('Project').value = "firefox" |
419 | - >>> browser.getControl('Branch Name').value = "git-import" |
420 | + >>> browser.getControl('Name').value = "git-import" |
421 | >>> browser.getControl('Git').click() |
422 | >>> browser.getControl('Repo URL', index=0).value = ( |
423 | ... "git://example.com/firefox.git") |
424 | >>> browser.getControl('Request Import').click() |
425 | |
426 | -When the user clicks continue, the approved import branch is created |
427 | +When the user clicks continue, the approved import branch is created. |
428 | |
429 | >>> print extract_text(find_tag_by_id(browser.contents, "import-details")) |
430 | Import Status: Reviewed |
431 | @@ -203,6 +203,38 @@ |
432 | The next import is scheduled to run as soon as possible. |
433 | |
434 | |
435 | +Requesting a Git-to-Git import |
436 | +============================== |
437 | + |
438 | +The user is required to enter a project that the import is for, |
439 | +a name for the import repository, and a Git repository location. |
440 | + |
441 | + >>> from lp.code.interfaces.codeimport import ( |
442 | + ... CODE_IMPORT_GIT_TARGET_FEATURE_FLAG, |
443 | + ... ) |
444 | + >>> from lp.code.tests.helpers import GitHostingFixture |
445 | + >>> from lp.services.features.testing import FeatureFixture |
446 | + |
447 | + >>> with FeatureFixture({CODE_IMPORT_GIT_TARGET_FEATURE_FLAG: u'on'}): |
448 | + ... browser.open("http://code.launchpad.dev/+code-imports/+new") |
449 | + ... browser.getControl('Project').value = "firefox" |
450 | + ... browser.getControl('Name').value = "upstream" |
451 | + ... browser.getControl('Git', index=0).click() |
452 | + ... browser.getControl('Git', index=1).click() |
453 | + ... browser.getControl('Repo URL', index=0).value = ( |
454 | + ... "git://example.com/firefox2.git") |
455 | + ... with GitHostingFixture(): |
456 | + ... browser.getControl('Request Import').click() |
457 | + |
458 | +When the user clicks continue, the approved import repository is created. |
459 | + |
460 | + >>> print extract_text(find_tag_by_id(browser.contents, "import-details")) |
461 | + Import Status: Reviewed |
462 | + This repository is an import of the Git repository at |
463 | + git://example.com/firefox2.git. |
464 | + The next import is scheduled to run as soon as possible. |
465 | + |
466 | + |
467 | Requesting a CVS import |
468 | ======================= |
469 | |
470 | @@ -211,7 +243,7 @@ |
471 | |
472 | >>> browser.open("http://code.launchpad.dev/+code-imports/+new") |
473 | >>> browser.getControl('Project').value = "firefox" |
474 | - >>> browser.getControl('Branch Name').value = "import2" |
475 | + >>> browser.getControl('Name').value = "import2" |
476 | >>> browser.getControl('CVS').click() |
477 | >>> browser.getControl('Repository').value = ( |
478 | ... ":pserver:anonymous@cvs.example.com:/mozilla/cvs") |
479 | @@ -233,7 +265,7 @@ |
480 | |
481 | >>> browser.open("http://code.launchpad.dev/+code-imports/+new") |
482 | >>> browser.getControl('Project').value = "firefox" |
483 | - >>> browser.getControl('Branch Name').value = "import2" |
484 | + >>> browser.getControl('Name').value = "import2" |
485 | >>> browser.getControl('CVS').click() |
486 | >>> browser.getControl('Repository').value = ( |
487 | ... ":anonymous@cvs.example.com:/mozilla/cvs") |
488 | @@ -256,7 +288,7 @@ |
489 | The error is shown even if the project is different. |
490 | |
491 | >>> browser.getControl('Project').value = "thunderbird" |
492 | - >>> browser.getControl('Branch Name').value = "imported" |
493 | + >>> browser.getControl('Name').value = "imported" |
494 | >>> browser.getControl('CVS').click() |
495 | >>> browser.getControl('Repository').value = ( |
496 | ... ":pserver:anonymous@cvs.example.com:/mozilla/cvs") |
497 | @@ -290,7 +322,7 @@ |
498 | >>> browser.open("http://code.launchpad.dev/+code-imports/+new") |
499 | >>> browser.getControl('Subversion').click() |
500 | >>> browser.getControl('Project').value = "firefox" |
501 | - >>> browser.getControl('Branch Name').value = "imported" |
502 | + >>> browser.getControl('Name').value = "imported" |
503 | >>> browser.getControl('Branch URL', index=1).value = ( |
504 | ... "http://svn.example.com/firefox/other") |
505 | >>> browser.getControl('Request Import').click() |
506 | @@ -307,7 +339,7 @@ |
507 | |
508 | >>> browser.open("http://code.launchpad.dev/+code-imports/+new") |
509 | >>> browser.getControl('Project').value = "launchpad" |
510 | - >>> browser.getControl('Branch Name').value = "imported" |
511 | + >>> browser.getControl('Name').value = "imported" |
512 | >>> browser.getControl('Branch URL', index=0).value = ( |
513 | ... "http://svn.example.com/launchpage/fake") |
514 | >>> browser.getControl('Request Import').click() |
515 | @@ -324,7 +356,7 @@ |
516 | |
517 | >>> browser.open("http://code.launchpad.dev/+code-imports/+new") |
518 | >>> browser.getControl('Project').value = "no-such-product" |
519 | - >>> browser.getControl('Branch Name').value = "imported" |
520 | + >>> browser.getControl('Name').value = "imported" |
521 | >>> browser.getControl('Branch URL', index=0).value = ( |
522 | ... "http://svn.example.com/launchpage/fake") |
523 | >>> browser.getControl('Request Import').click() |
524 | |
525 | === modified file 'lib/lp/code/templates/codeimport-new.pt' |
526 | --- lib/lp/code/templates/codeimport-new.pt 2012-10-09 01:07:52 +0000 |
527 | +++ lib/lp/code/templates/codeimport-new.pt 2016-10-15 02:22:43 +0000 |
528 | @@ -45,7 +45,7 @@ |
529 | <tr> |
530 | <td colspan="2"> |
531 | <div class="formHelp"> |
532 | - Enter details for the selected repository type. |
533 | + Enter details for the selected version control system. |
534 | </div> |
535 | </td> |
536 | </tr> |
537 | @@ -74,6 +74,10 @@ |
538 | <tal:widget define="widget nocall:view/widgets/git_repo_url"> |
539 | <metal:block use-macro="context/@@launchpad_form/widget_row" /> |
540 | </tal:widget> |
541 | + <tal:widget define="widget nocall:view/widgets/git_target_rcs_type" |
542 | + condition="request/features/code.import.git_target"> |
543 | + <metal:block use-macro="context/@@launchpad_form/widget_row" /> |
544 | + </tal:widget> |
545 | </table> |
546 | </td> |
547 | </tr> |
548 | @@ -131,6 +135,12 @@ |
549 | } |
550 | } |
551 | updateField(form['field.git_repo_url'], rcs_type === 'GIT'); |
552 | + for (i = 0; i < form.elements.length; i++) { |
553 | + if (form.elements[i].id.startsWith( |
554 | + 'field.git_target_rcs_type.')) { |
555 | + updateField(form.elements[i], rcs_type === 'GIT'); |
556 | + } |
557 | + } |
558 | updateField(form['field.cvs_root'], rcs_type === 'CVS'); |
559 | updateField(form['field.cvs_module'], rcs_type === 'CVS'); |
560 | updateField(form['field.svn_branch_url'], rcs_type === 'BZR_SVN'); |