Merge lp:~thumper/launchpad/short-lp-name-for-private-branches into lp:launchpad

Proposed by Tim Penhey
Status: Merged
Approved by: Michael Hudson-Doyle
Approved revision: no longer in the source branch.
Merged at revision: 11516
Proposed branch: lp:~thumper/launchpad/short-lp-name-for-private-branches
Merge into: lp:launchpad
Prerequisite: lp:~thumper/launchpad/xmlrpc-lp-name-resolution
Diff against target: 288 lines (+18/-146)
6 files modified
lib/lp/code/doc/branch-xmlrpc.txt (+1/-117)
lib/lp/code/interfaces/branch.py (+1/-3)
lib/lp/code/model/tests/test_branch.py (+10/-20)
lib/lp/code/stories/branches/xx-private-branch-listings.txt (+2/-2)
lib/lp/code/tests/test_branch.py (+2/-2)
lib/lp/registry/stories/product/xx-product-development-focus.txt (+2/-2)
To merge this branch: bzr merge lp:~thumper/launchpad/short-lp-name-for-private-branches
Reviewer Review Type Date Requested Status
Michael Hudson-Doyle Approve
Review via email: mp+34509@code.launchpad.net

Commit message

Use short lp: alias names for projects with private trunks.

Description of the change

This branch is the final part of providing short lp name for private
branches that are linked to official series.

There is a little drive by clean up in the tests for imports and
removing unneeded syncUpdate calls.

I think we have got all the test failures here.

To post a comment you must log in.
Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

All looks fine. I like the way you fixed the doctest :-)

Cheers,
mwh

Revision history for this message
Michael Hudson-Doyle (mwhudson) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/code/doc/branch-xmlrpc.txt'
--- lib/lp/code/doc/branch-xmlrpc.txt 2010-02-19 03:06:12 +0000
+++ lib/lp/code/doc/branch-xmlrpc.txt 2010-09-03 11:26:07 +0000
@@ -338,120 +338,4 @@
338The URLs that are likely to be faster or provide write access appear338The URLs that are likely to be faster or provide write access appear
339earlier in the list.339earlier in the list.
340340
341341For more tests see `lp.code.xmlrpc.tests.test_branch.py`.
342lp:project
343==========
344
345If you specify a path with a single segment, then Launchpad treats that
346path as the name of a project, and returns URLs to the branch
347associated with the project's development focus series.
348
349 >>> results = branchset_api.resolve_lp_path('evolution')
350 >>> for url in results['urls']:
351 ... print url
352 bzr+ssh://bazaar.launchpad.dev/~vcs-imports/evolution/main
353 http://bazaar.launchpad.dev/~vcs-imports/evolution/main
354
355
356Launchpad returns a fault if the development focus doesn't have branch
357associated with it.
358
359 >>> branchset_api.resolve_lp_path('firefox')
360 Traceback (most recent call last):
361 ...
362 Fault: <Fault 170: 'Mozilla Firefox has no default branch.'>
363
364
365Launchpad also returns a fault if the project doesn't exist.
366
367 >>> branchset_api.resolve_lp_path('doesntexist')
368 Traceback (most recent call last):
369 ...
370 Fault: <Fault 10: 'No such project: doesntexist'>
371
372
373lp:project/series
374=================
375
376If you specify a path with two segments, Launchpad treats that as a
377reference to a particular series on a project.
378
379 >>> results = branchset_api.resolve_lp_path('evolution/trunk')
380 >>> for url in results['urls']:
381 ... print url
382 bzr+ssh://bazaar.launchpad.dev/~vcs-imports/evolution/main
383 http://bazaar.launchpad.dev/~vcs-imports/evolution/main
384
385
386If the series doesn't exist, then the server returns a fault.
387
388 >>> branchset_api.resolve_lp_path('firefox/doesntexist')
389 Traceback (most recent call last):
390 ...
391 Fault: <Fault 180: 'Project firefox has no series called "doesntexist"'>
392
393
394Similarly if the project doesn't exist:
395
396 >>> branchset_api.resolve_lp_path('doesntexist/trunk')
397 Traceback (most recent call last):
398 ...
399 Fault: <Fault 10: 'No such project: doesntexist'>
400
401
402lp:~owner/product/branch
403========================
404
405Anything longer than two segments is treated as a unique branch name
406followed by an arbitrary path:
407
408 >>> results = branchset_api.resolve_lp_path('~vcs-imports/evolution/main')
409 >>> for url in results['urls']:
410 ... print url
411 bzr+ssh://bazaar.launchpad.dev/~vcs-imports/evolution/main
412 http://bazaar.launchpad.dev/~vcs-imports/evolution/main
413
414
415Launchpad will still resolve the branch even if it doesn't exist:
416
417 >>> results = branchset_api.resolve_lp_path('~mark/+junk/doesntexist')
418 >>> for url in results['urls']:
419 ... print url
420 bzr+ssh://bazaar.launchpad.dev/~mark/%2Bjunk/doesntexist
421 http://bazaar.launchpad.dev/~mark/%2Bjunk/doesntexist
422
423
424But if the project or the user doesn't exist, Launchpad will return a fault:
425
426 >>> branchset_api.resolve_lp_path('~doesntexist/+junk/trunk')
427 Traceback (most recent call last):
428 ...
429 Fault: <Fault 200: 'No such person or team: doesntexist'>
430
431 >>> branchset_api.resolve_lp_path('~mark/doesntexist/trunk')
432 Traceback (most recent call last):
433 ...
434 Fault: <Fault 10: 'No such project: doesntexist'>
435
436
437Remote branches
438===============
439
440Some branches on Launchpad are 'remote' branches. These branches are
441not hosted on Launchpad and are only available (if at all) on remote
442sites. For these branches, resolve_lp_path returns only a single URL.
443
444 >>> from lp.code.enums import BranchType
445 >>> from lp.registry.interfaces.person import IPersonSet
446 >>> arbitrary_person = getUtility(IPersonSet).getByName('name12')
447 >>> from lp.code.interfaces.branchnamespace import (
448 ... get_branch_namespace)
449 >>> namespace = get_branch_namespace(arbitrary_person)
450 >>> namespace.createBranch(
451 ... branch_type=BranchType.REMOTE, name='remote',
452 ... registrant=arbitrary_person,
453 ... url='http://example.com/remote_branch')
454 <Branch u'~name12/+junk/remote' (...)>
455 >>> results = branchset_api.resolve_lp_path('~name12/+junk/remote')
456 >>> results['urls']
457 ['http://example.com/remote_branch']
458342
=== modified file 'lib/lp/code/interfaces/branch.py'
--- lib/lp/code/interfaces/branch.py 2010-08-27 02:11:36 +0000
+++ lib/lp/code/interfaces/branch.py 2010-09-03 11:26:07 +0000
@@ -1303,9 +1303,7 @@
1303 def branchIdentities(self):1303 def branchIdentities(self):
1304 """See `IBranch`."""1304 """See `IBranch`."""
1305 lp_prefix = config.codehosting.bzr_lp_prefix1305 lp_prefix = config.codehosting.bzr_lp_prefix
1306 if self.private or not self.target.supports_short_identites:1306 if not self.target.supports_short_identites:
1307 # XXX: thumper 2010-04-08, bug 261609
1308 # We have to get around to fixing this
1309 identities = []1307 identities = []
1310 else:1308 else:
1311 identities = [1309 identities = [
13121310
=== modified file 'lib/lp/code/model/tests/test_branch.py'
--- lib/lp/code/model/tests/test_branch.py 2010-08-20 20:31:18 +0000
+++ lib/lp/code/model/tests/test_branch.py 2010-09-03 11:26:07 +0000
@@ -28,13 +28,6 @@
28from canonical.config import config28from canonical.config import config
29from canonical.database.constants import UTC_NOW29from canonical.database.constants import UTC_NOW
30from canonical.launchpad import _30from canonical.launchpad import _
31from canonical.launchpad.ftests import (
32 ANONYMOUS,
33 login,
34 login_person,
35 logout,
36 syncUpdate,
37 )
38from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities31from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities
39from canonical.launchpad.webapp.interfaces import IOpenLaunchBag32from canonical.launchpad.webapp.interfaces import IOpenLaunchBag
40from canonical.testing import (33from canonical.testing import (
@@ -120,6 +113,11 @@
120from lp.registry.model.sourcepackage import SourcePackage113from lp.registry.model.sourcepackage import SourcePackage
121from lp.services.osutils import override_environ114from lp.services.osutils import override_environ
122from lp.testing import (115from lp.testing import (
116 ANONYMOUS,
117 celebrity_logged_in,
118 login,
119 login_person,
120 logout,
123 person_logged_in,121 person_logged_in,
124 run_with_login,122 run_with_login,
125 TestCase,123 TestCase,
@@ -904,16 +902,12 @@
904 self.assertBzrIdentity(branch, linked_branch.bzr_path)902 self.assertBzrIdentity(branch, linked_branch.bzr_path)
905903
906 def test_private_linked_to_product(self):904 def test_private_linked_to_product(self):
907 # If a branch is private, then the bzr identity is the unique name,905 # Private branches also have a short lp:url.
908 # even if it's linked to a product. Of course, you have to be able to
909 # see the branch at all.
910 branch = self.factory.makeProductBranch(private=True)906 branch = self.factory.makeProductBranch(private=True)
911 owner = removeSecurityProxy(branch).owner907 with celebrity_logged_in('admin'):
912 login_person(owner)908 product = branch.product
913 self.addCleanup(logout)909 ICanHasLinkedBranch(product).setBranch(branch)
914 product = removeSecurityProxy(branch.product)910 self.assertBzrIdentity(branch, product.name)
915 ICanHasLinkedBranch(product).setBranch(branch)
916 self.assertBzrIdentity(branch, branch.unique_name)
917911
918 def test_linked_to_series_and_dev_focus(self):912 def test_linked_to_series_and_dev_focus(self):
919 # If a branch is the development focus branch for a product and the913 # If a branch is the development focus branch for a product and the
@@ -1048,7 +1042,6 @@
1048 deleted.1042 deleted.
1049 """1043 """
1050 self.product.development_focus.branch = self.branch1044 self.product.development_focus.branch = self.branch
1051 syncUpdate(self.product.development_focus)
1052 self.assertEqual(self.branch.canBeDeleted(), False,1045 self.assertEqual(self.branch.canBeDeleted(), False,
1053 "A branch that is a user branch for a product series"1046 "A branch that is a user branch for a product series"
1054 " is not deletable.")1047 " is not deletable.")
@@ -1056,7 +1049,6 @@
10561049
1057 def test_productSeriesTranslationsBranchDisablesDeletion(self):1050 def test_productSeriesTranslationsBranchDisablesDeletion(self):
1058 self.product.development_focus.translations_branch = self.branch1051 self.product.development_focus.translations_branch = self.branch
1059 syncUpdate(self.product.development_focus)
1060 self.assertEqual(self.branch.canBeDeleted(), False,1052 self.assertEqual(self.branch.canBeDeleted(), False,
1061 "A branch that is a translations branch for a "1053 "A branch that is a translations branch for a "
1062 "product series is not deletable.")1054 "product series is not deletable.")
@@ -1219,7 +1211,6 @@
1219 # Disable this merge proposal, to allow creating a new identical one1211 # Disable this merge proposal, to allow creating a new identical one
1220 lp_admins = getUtility(ILaunchpadCelebrities).admin1212 lp_admins = getUtility(ILaunchpadCelebrities).admin
1221 merge_proposal1.rejectBranch(lp_admins, 'null:')1213 merge_proposal1.rejectBranch(lp_admins, 'null:')
1222 syncUpdate(merge_proposal1)
1223 merge_proposal2 = self.branch.addLandingTarget(1214 merge_proposal2 = self.branch.addLandingTarget(
1224 self.branch.owner, target_branch, prerequisite_branch)1215 self.branch.owner, target_branch, prerequisite_branch)
1225 return merge_proposal1, merge_proposal21216 return merge_proposal1, merge_proposal2
@@ -1603,7 +1594,6 @@
1603 proposal = self.source.addLandingTarget(1594 proposal = self.source.addLandingTarget(
1604 self.user, self.target, self.prerequisite)1595 self.user, self.target, self.prerequisite)
1605 proposal.rejectBranch(self.user, 'some_revision')1596 proposal.rejectBranch(self.user, 'some_revision')
1606 syncUpdate(proposal)
1607 self.source.addLandingTarget(1597 self.source.addLandingTarget(
1608 self.user, self.target, self.prerequisite)1598 self.user, self.target, self.prerequisite)
16091599
16101600
=== modified file 'lib/lp/code/stories/branches/xx-private-branch-listings.txt'
--- lib/lp/code/stories/branches/xx-private-branch-listings.txt 2009-11-17 09:08:17 +0000
+++ lib/lp/code/stories/branches/xx-private-branch-listings.txt 2010-09-03 11:26:07 +0000
@@ -244,14 +244,14 @@
244244
245 >>> print extract_text(245 >>> print extract_text(
246 ... find_tag_by_id(admin_browser.contents, 'branch-details'))246 ... find_tag_by_id(admin_browser.contents, 'branch-details'))
247 lp://dev/~landscape-developers/landscape/trunk - Landscape Developers ...247 lp://dev/landscape - Landscape Developers ...
248248
249Landscape developers can see it.249Landscape developers can see it.
250250
251 >>> landscape_dev_browser.open('http://launchpad.dev/landscape/trunk')251 >>> landscape_dev_browser.open('http://launchpad.dev/landscape/trunk')
252 >>> print extract_text(find_tag_by_id(252 >>> print extract_text(find_tag_by_id(
253 ... landscape_dev_browser.contents, 'branch-details'))253 ... landscape_dev_browser.contents, 'branch-details'))
254 lp://dev/~landscape-developers/landscape/trunk - Landscape Developers ...254 lp://dev/landscape - Landscape Developers ...
255255
256But normal people can't.256But normal people can't.
257257
258258
=== modified file 'lib/lp/code/tests/test_branch.py'
--- lib/lp/code/tests/test_branch.py 2010-08-20 20:31:18 +0000
+++ lib/lp/code/tests/test_branch.py 2010-09-03 11:26:07 +0000
@@ -16,8 +16,8 @@
16 BranchSubscriptionNotificationLevel,16 BranchSubscriptionNotificationLevel,
17 CodeReviewNotificationLevel,17 CodeReviewNotificationLevel,
18 )18 )
19from lp.code.interfaces.codehosting import SUPPORTED_SCHEMES
19from lp.code.tests.helpers import make_official_package_branch20from lp.code.tests.helpers import make_official_package_branch
20from lp.code.xmlrpc.branch import PublicCodehostingAPI
21from lp.soyuz.interfaces.archivepermission import IArchivePermissionSet21from lp.soyuz.interfaces.archivepermission import IArchivePermissionSet
22from lp.testing import (22from lp.testing import (
23 run_with_login,23 run_with_login,
@@ -347,7 +347,7 @@
347347
348 url_pattern = '%%s://bazaar.launchpad.dev/~%s/%s/%s' % (348 url_pattern = '%%s://bazaar.launchpad.dev/~%s/%s/%s' % (
349 branch.owner.name, branch.product.name, branch.name)349 branch.owner.name, branch.product.name, branch.name)
350 for scheme in PublicCodehostingAPI.supported_schemes:350 for scheme in SUPPORTED_SCHEMES:
351 public_url = branch.composePublicURL(scheme)351 public_url = branch.composePublicURL(scheme)
352 self.assertEqual(url_pattern % scheme, public_url)352 self.assertEqual(url_pattern % scheme, public_url)
353353
354354
=== modified file 'lib/lp/registry/stories/product/xx-product-development-focus.txt'
--- lib/lp/registry/stories/product/xx-product-development-focus.txt 2010-08-02 20:25:10 +0000
+++ lib/lp/registry/stories/product/xx-product-development-focus.txt 2010-09-03 11:26:07 +0000
@@ -161,13 +161,13 @@
161 >>> print_development_focus(owner_browser)161 >>> print_development_focus(owner_browser)
162 Development focus:162 Development focus:
163 trunk series Change details163 trunk series Change details
164 lp://dev/~eric/fooix/trunk Change branch164 lp://dev/fooix Change branch
165 View the branch content165 View the branch content
166 Links:166 Links:
167 trunk series (/fooix/trunk)167 trunk series (/fooix/trunk)
168 <span class="invisible-link">Change details</span>168 <span class="invisible-link">Change details</span>
169 (http://launchpad.dev/fooix/+edit)169 (http://launchpad.dev/fooix/+edit)
170 lp://dev/~eric/fooix/trunk (http://code.launchpad.dev/~eric/fooix/trunk)170 lp://dev/fooix (http://code.launchpad.dev/~eric/fooix/trunk)
171 <span class="invisible-link">Change branch</span>171 <span class="invisible-link">Change branch</span>
172 Change the branch for this series172 Change the branch for this series
173 (http://launchpad.dev/fooix/trunk/+linkbranch)173 (http://launchpad.dev/fooix/trunk/+linkbranch)