Rev 2980: (robertc) Improved lp:/// URL support for the Launchpad plugin (James Henstridge). in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Mon Nov 12 21:23:11 GMT 2007
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 2980
revision-id: pqm at pqm.ubuntu.com-20071112212307-eusj64ymto8l9abk
parent: pqm at pqm.ubuntu.com-20071112195430-0xgqswqpc1j2pk2m
parent: james at jamesh.id.au-20071031232330-c9zuhvdhhvch9wly
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Mon 2007-11-12 21:23:07 +0000
message:
(robertc) Improved lp:/// URL support for the Launchpad plugin (James Henstridge).
modified:
bzrlib/plugins/launchpad/__init__.py __init__.py-20060315182712-2d5feebd2a1032dc
bzrlib/plugins/launchpad/lp_indirect.py lp_indirect.py-20070126012204-de5rugwlt22c7u7e-1
bzrlib/plugins/launchpad/lp_registration.py lp_registration.py-20060315190948-daa617eafe3a8d48
bzrlib/plugins/launchpad/test_lp_indirect.py test_lp_indirect.py-20070126002743-oyle362tzv9cd8mi-1
bzrlib/plugins/launchpad/test_register.py test_register.py-20060315182712-40f5dda945c829a8
------------------------------------------------------------
revno: 2898.4.17
merged: james at jamesh.id.au-20071031232330-c9zuhvdhhvch9wly
parent: james at jamesh.id.au-20071031231023-3m5adgrdgluedbm0
committer: James Henstridge <james at jamesh.id.au>
branch nick: bzr.lp-urls-bug-121200
timestamp: Wed 2007-10-31 19:23:30 -0400
message:
Add a test that the redirect actually occurs when opening an lp: URL.
------------------------------------------------------------
revno: 2898.4.16
merged: james at jamesh.id.au-20071031231023-3m5adgrdgluedbm0
parent: james at jamesh.id.au-20071031194745-u5nlc14tr74w7t3g
committer: James Henstridge <james at jamesh.id.au>
branch nick: bzr.lp-urls-bug-121200
timestamp: Wed 2007-10-31 19:10:23 -0400
message:
Small spelling errors pointed out by Ian.
------------------------------------------------------------
revno: 2898.4.15
merged: james at jamesh.id.au-20071031194745-u5nlc14tr74w7t3g
parent: james at jamesh.id.au-20071031164031-9v35bhm3bb6tpes7
committer: James Henstridge <james at jamesh.id.au>
branch nick: bzr.lp-urls-bug-121200
timestamp: Wed 2007-10-31 15:47:45 -0400
message:
Use get_transport() to decide whether Bazaar supports a given URL.
------------------------------------------------------------
revno: 2898.4.14
merged: james at jamesh.id.au-20071031164031-9v35bhm3bb6tpes7
parent: james at jamesh.id.au-20071030205501-hpkyk9zl43kubuea
committer: James Henstridge <james at jamesh.id.au>
branch nick: bzr.lp-urls-bug-121200
timestamp: Wed 2007-10-31 12:40:31 -0400
message:
* Use urlsplit() to process URLs.
* Log the result of the RPC call if the 'launchpad' debug flag is set.
------------------------------------------------------------
revno: 2898.4.13
merged: james at jamesh.id.au-20071030205501-hpkyk9zl43kubuea
parent: james at jamesh.id.au-20071030204623-57gtf0rwqp50cn13
committer: James Henstridge <james at jamesh.id.au>
branch nick: bzr.lp-urls-bug-121200
timestamp: Tue 2007-10-30 16:55:01 -0400
message:
Remove some transport methods that shouldn't be needed to process the
redirect.
------------------------------------------------------------
revno: 2898.4.12
merged: james at jamesh.id.au-20071030204623-57gtf0rwqp50cn13
parent: james at jamesh.id.au-20071030203505-ee7csno3ruhofal9
committer: James Henstridge <james at jamesh.id.au>
branch nick: bzr.lp-urls-bug-121200
timestamp: Tue 2007-10-30 16:46:23 -0400
message:
Add tests that redirects get issued by appropriate transport methods.
------------------------------------------------------------
revno: 2898.4.11
merged: james at jamesh.id.au-20071030203505-ee7csno3ruhofal9
parent: james at jamesh.id.au-20071018145455-sdli9rfh3y1z06b4
committer: James Henstridge <james at jamesh.id.au>
branch nick: bzr.lp-urls-bug-121200
timestamp: Tue 2007-10-30 16:35:05 -0400
message:
Switch back to RedirectRequested based implementation.
------------------------------------------------------------
revno: 2898.4.10
merged: james at jamesh.id.au-20071018145455-sdli9rfh3y1z06b4
parent: james at jamesh.id.au-20071018145412-i9rv84pmxkvojpup
parent: james at jamesh.id.au-20071018085819-zv64jvki41van9fq
committer: James Henstridge <james at jamesh.id.au>
branch nick: bzr.lp-urls-bug-121200
timestamp: Thu 2007-10-18 22:54:55 +0800
message:
Merge from bzr.lp-login branch, to pick up test fixes.
------------------------------------------------------------
revno: 2898.4.9
merged: james at jamesh.id.au-20071018145412-i9rv84pmxkvojpup
parent: james at jamesh.id.au-20071016072727-liemzmhq891upybl
committer: James Henstridge <james at jamesh.id.au>
branch nick: bzr.lp-urls-bug-121200
timestamp: Thu 2007-10-18 22:54:12 +0800
message:
Add some more tests for the bzr+ssh://bazaar.launchpad.net URL
rewriting (and fix the code to actually work).
------------------------------------------------------------
revno: 2898.4.8
merged: james at jamesh.id.au-20071016072727-liemzmhq891upybl
parent: james at jamesh.id.au-20071014095255-val0oiv5749km3vp
committer: James Henstridge <james at jamesh.id.au>
branch nick: bzr.lp-urls-bug-121200
timestamp: Tue 2007-10-16 20:27:27 +1300
message:
Switch lp: over to a pass-through transport, so that the XMLRPC gets
delayed to the point where the transport is actually used.
------------------------------------------------------------
revno: 2898.4.7
merged: james at jamesh.id.au-20071014095255-val0oiv5749km3vp
parent: james at jamesh.id.au-20071014095015-j97ewee17veci33b
committer: James Henstridge <james at jamesh.id.au>
branch nick: bzr.lp-urls-bug-121200
timestamp: Sun 2007-10-14 22:52:55 +1300
message:
Fix up tests.
------------------------------------------------------------
revno: 2898.4.6
merged: james at jamesh.id.au-20071014095015-j97ewee17veci33b
parent: james at jamesh.id.au-20071010055425-4ubwojz01blad91s
parent: james at jamesh.id.au-20071012044216-1aystcylm32fjb67
committer: James Henstridge <james at jamesh.id.au>
branch nick: bzr.lp-urls-bug-121200
timestamp: Sun 2007-10-14 22:50:15 +1300
message:
merge from launchpad-login branch
------------------------------------------------------------
revno: 2898.4.5
merged: james at jamesh.id.au-20071010055425-4ubwojz01blad91s
parent: james at jamesh.id.au-20071010052400-ufkjeee2zzlsli03
committer: James Henstridge <james at jamesh.id.au>
branch nick: bzr.lp-urls-bug-1200
timestamp: Wed 2007-10-10 18:54:25 +1300
message:
get rid of extra space in messages
------------------------------------------------------------
revno: 2898.4.4
merged: james at jamesh.id.au-20071010052400-ufkjeee2zzlsli03
parent: james at jamesh.id.au-20071010033447-3wjyvy4tlnhphwi7
committer: James Henstridge <james at jamesh.id.au>
branch nick: bzr.lp-urls-bug-1200
timestamp: Wed 2007-10-10 18:24:00 +1300
message:
Changes to account for modifications to the XMLRPC API.
------------------------------------------------------------
revno: 2898.4.3
merged: james at jamesh.id.au-20071010033447-3wjyvy4tlnhphwi7
parent: james at jamesh.id.au-20071010015711-u0uq2y7ldbqj3fmz
committer: James Henstridge <james at jamesh.id.au>
branch nick: bzr.lp-urls-bug-1200
timestamp: Wed 2007-10-10 16:34:47 +1300
message:
Make launchpad_transport_indirect() use XMLRPC to resolve the lp: URL.
------------------------------------------------------------
revno: 2898.4.2
merged: james at jamesh.id.au-20071010015711-u0uq2y7ldbqj3fmz
parent: james at jamesh.id.au-20071010012542-d0cq7ttawfhptlve
committer: James Henstridge <james at jamesh.id.au>
branch nick: bzr.lp-urls-bug-1200
timestamp: Wed 2007-10-10 14:57:11 +1300
message:
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
------------------------------------------------------------
revno: 2898.4.1
merged: james at jamesh.id.au-20071010012542-d0cq7ttawfhptlve
parent: pqm at pqm.ubuntu.com-20071009044446-uliu5z9a52bzmps8
committer: James Henstridge <james at jamesh.id.au>
branch nick: bzr.lp-urls-bug-1200
timestamp: Wed 2007-10-10 14:25:42 +1300
message:
Make it possible to make unauthenticated XML-RPC requests.
=== modified file 'bzrlib/plugins/launchpad/__init__.py'
--- a/bzrlib/plugins/launchpad/__init__.py 2007-10-24 08:12:18 +0000
+++ b/bzrlib/plugins/launchpad/__init__.py 2007-11-12 21:23:07 +0000
@@ -158,12 +158,12 @@
register_lazy_transport(
'lp:',
'bzrlib.plugins.launchpad.lp_indirect',
- 'launchpad_transport_indirect')
+ 'LaunchpadTransport')
register_lazy_transport(
'lp://',
'bzrlib.plugins.launchpad.lp_indirect',
- 'launchpad_transport_indirect')
+ 'LaunchpadTransport')
def test_suite():
"""Called by bzrlib to fetch tests for this plugin"""
=== modified file 'bzrlib/plugins/launchpad/lp_indirect.py'
--- a/bzrlib/plugins/launchpad/lp_indirect.py 2007-01-26 04:44:10 +0000
+++ b/bzrlib/plugins/launchpad/lp_indirect.py 2007-10-31 19:47:45 +0000
@@ -22,24 +22,112 @@
again.
"""
+from urlparse import urlsplit, urlunsplit
+import xmlrpclib
+
from bzrlib import (
+ debug,
errors,
+ trace,
+ urlutils,
)
from bzrlib.transport import (
get_transport,
+ register_urlparse_netloc_protocol,
Transport,
)
-
-def launchpad_transport_indirect(base_url):
- """Uses Launchpad.net as a directory of open source software"""
- if base_url.startswith('lp:///'):
- real_url = 'http://code.launchpad.net/' + base_url[6:]
- elif base_url.startswith('lp:') and base_url[3] != '/':
- real_url = 'http://code.launchpad.net/' + base_url[3:]
- else:
- raise errors.InvalidURL(path=base_url)
- return get_transport(real_url)
+from bzrlib.plugins.launchpad.lp_registration import (
+ LaunchpadService, ResolveLaunchpadPathRequest)
+from bzrlib.plugins.launchpad.account import get_lp_login
+
+
+# As bzrlib.transport.remote may not be loaded yet, make sure bzr+ssh
+# is counted as a netloc protocol.
+register_urlparse_netloc_protocol('bzr+ssh')
+register_urlparse_netloc_protocol('lp')
+
+
+class LaunchpadTransport(Transport):
+ """lp:/// URL transport
+
+ This transport redirects requests to the real branch location
+ after resolving the URL via an XMLRPC request to Launchpad.
+ """
+
+ def __init__(self, base):
+ super(LaunchpadTransport, self).__init__(base)
+ # We only support URLs without a netloc
+ netloc = urlsplit(base)[1]
+ if netloc != '':
+ raise errors.InvalidURL(path=base)
+
+ def _resolve(self, abspath,
+ _request_factory=ResolveLaunchpadPathRequest,
+ _lp_login=None):
+ """Resolve the base URL for this transport."""
+ path = urlsplit(abspath)[2].lstrip('/')
+ # Perform an XMLRPC request to resolve the path
+ resolve = _request_factory(path)
+ service = LaunchpadService()
+ try:
+ result = resolve.submit(service)
+ except xmlrpclib.Fault, fault:
+ raise errors.InvalidURL(
+ path=abspath, extra=fault.faultString)
+
+ if 'launchpad' in debug.debug_flags:
+ trace.mutter("resolve_lp_path(%r) == %r", path, result)
+
+ if _lp_login is None:
+ _lp_login = get_lp_login()
+ for url in result['urls']:
+ scheme, netloc, path, query, fragment = urlsplit(url)
+ if scheme == 'bzr+ssh' and (netloc.endswith('launchpad.net') or
+ netloc.endswith('launchpad.dev')):
+ # Only accept launchpad.net bzr+ssh URLs if we know
+ # the user's Launchpad login:
+ if _lp_login is None:
+ continue
+ url = urlunsplit((scheme, '%s@%s' % (_lp_login, netloc),
+ path, query, fragment))
+ break
+ else:
+ # Use the URL if we can create a transport for it.
+ try:
+ get_transport(url)
+ except (errors.PathError, errors.TransportError):
+ pass
+ else:
+ break
+ else:
+ raise errors.InvalidURL(path=abspath,
+ extra='no supported schemes')
+ return url
+
+ def _request_redirect(self, relpath):
+ source = urlutils.join(self.base, relpath)
+ # Split the source location into the branch location, and the
+ # extra path components.
+ pos = source.find('/.bzr/')
+ if pos >= 0:
+ branchpath = source[:pos]
+ extra = source[pos:]
+ else:
+ branchpath = source
+ extra = ''
+ target = self._resolve(branchpath) + extra
+ raise errors.RedirectRequested(
+ source=source,
+ target=target)
+
+ def get(self, relpath):
+ """See Transport.get()."""
+ self._request_redirect(relpath)
+
+ def mkdir(self, relpath, mode=None):
+ """See Transport.mkdir()."""
+ self._request_redirect(relpath)
def get_test_permutations():
=== modified file 'bzrlib/plugins/launchpad/lp_registration.py'
--- a/bzrlib/plugins/launchpad/lp_registration.py 2007-10-23 14:31:10 +0000
+++ b/bzrlib/plugins/launchpad/lp_registration.py 2007-11-12 21:23:07 +0000
@@ -72,25 +72,29 @@
else:
return self.DEFAULT_SERVICE_URL
- def get_proxy(self):
+ def get_proxy(self, authenticated):
"""Return the proxy for XMLRPC requests."""
- # auth info must be in url
- # TODO: if there's no registrant email perhaps we should just connect
- # anonymously?
- scheme, hostinfo, path = urlsplit(self.service_url)[:3]
- assert '@' not in hostinfo
- assert self.registrant_email is not None
- assert self.registrant_password is not None
- # TODO: perhaps fully quote the password to make it very slightly
- # obscured
- # TODO: can we perhaps add extra Authorization headers directly to the
- # request, rather than putting this into the url? perhaps a bit more
- # secure against accidentally revealing it. std66 s3.2.1 discourages putting
- # the password in the url.
- hostinfo = '%s:%s@%s' % (urllib.quote(self.registrant_email),
- urllib.quote(self.registrant_password),
- hostinfo)
- url = urlunsplit((scheme, hostinfo, path, '', ''))
+ if authenticated:
+ # auth info must be in url
+ # TODO: if there's no registrant email perhaps we should
+ # just connect anonymously?
+ scheme, hostinfo, path = urlsplit(self.service_url)[:3]
+ assert '@' not in hostinfo
+ assert self.registrant_email is not None
+ assert self.registrant_password is not None
+ # TODO: perhaps fully quote the password to make it very slightly
+ # obscured
+ # TODO: can we perhaps add extra Authorization headers
+ # directly to the request, rather than putting this into
+ # the url? perhaps a bit more secure against accidentally
+ # revealing it. std66 s3.2.1 discourages putting the
+ # password in the url.
+ hostinfo = '%s:%s@%s' % (urllib.quote(self.registrant_email),
+ urllib.quote(self.registrant_password),
+ hostinfo)
+ url = urlunsplit((scheme, hostinfo, path, '', ''))
+ else:
+ url = self.service_url
return xmlrpclib.ServerProxy(url, transport=self.transport)
def gather_user_credentials(self):
@@ -107,8 +111,8 @@
self.registrant_password = auth.get_password(scheme, hostinfo,
prompt=prompt)
- def send_request(self, method_name, method_params):
- proxy = self.get_proxy()
+ def send_request(self, method_name, method_params, authenticated):
+ proxy = self.get_proxy(authenticated)
assert method_name
method = getattr(proxy, method_name)
try:
@@ -134,6 +138,7 @@
# Set this to the XMLRPC method name.
_methodname = None
+ _authenticated = True
def _request_params(self):
"""Return the arguments to pass to the method"""
@@ -145,7 +150,8 @@
:param service: LaunchpadService indicating where to send
the request and the authentication credentials.
"""
- return service.send_request(self._methodname, self._request_params())
+ return service.send_request(self._methodname, self._request_params(),
+ self._authenticated)
class DryRunLaunchpadService(LaunchpadService):
@@ -154,7 +160,7 @@
The dummy service does not need authentication.
"""
- def send_request(self, method_name, method_params):
+ def send_request(self, method_name, method_params, authenticated):
pass
def gather_user_credentials(self):
@@ -216,3 +222,18 @@
# This must match the parameter tuple expected by Launchpad for this
# method
return (self.branch_url, self.bug_id, '')
+
+
+class ResolveLaunchpadPathRequest(BaseRequest):
+ """Request to resolve the path component of an lp: URL."""
+
+ _methodname = 'resolve_lp_path'
+ _authenticated = False
+
+ def __init__(self, path):
+ assert path
+ self.path = path
+
+ def _request_params(self):
+ """Return xmlrpc request parameters"""
+ return (self.path,)
=== modified file 'bzrlib/plugins/launchpad/test_lp_indirect.py'
--- a/bzrlib/plugins/launchpad/test_lp_indirect.py 2007-02-08 08:33:26 +0000
+++ b/bzrlib/plugins/launchpad/test_lp_indirect.py 2007-10-31 23:23:30 +0000
@@ -16,12 +16,31 @@
"""Tests for indirect branch urls through Launchpad.net"""
+import xmlrpclib
+
from bzrlib import (
errors,
- transport,
)
+from bzrlib.branch import Branch
+from bzrlib.tests import TestCase, TestCaseWithMemoryTransport
from bzrlib.transport import get_transport
-from bzrlib.tests import TestCase, TestSkipped
+from bzrlib.plugins.launchpad.lp_indirect import (
+ LaunchpadTransport)
+from bzrlib.plugins.launchpad.account import get_lp_login
+
+
+class FakeResolveFactory(object):
+ def __init__(self, test, expected_path, result):
+ self._test = test
+ self._expected_path = expected_path
+ self._result = result
+
+ def __call__(self, path):
+ self._test.assertEqual(self._expected_path, path)
+ return self
+
+ def submit(self, service):
+ return self._result
class IndirectUrlTests(TestCase):
@@ -29,22 +48,127 @@
def test_short_form(self):
"""A launchpad url should map to a http url"""
- url = 'lp:apt'
- t = get_transport(url)
- self.assertEquals(t.base, 'http://code.launchpad.net/apt/')
+ factory = FakeResolveFactory(
+ self, 'apt', dict(urls=[
+ 'http://bazaar.launchpad.net/~apt/apt/devel']))
+ transport = LaunchpadTransport('lp:///')
+ self.assertEquals('http://bazaar.launchpad.net/~apt/apt/devel',
+ transport._resolve('lp:apt', factory))
def test_indirect_through_url(self):
"""A launchpad url should map to a http url"""
- # These can change to use the smartserver protocol or something
- # else in the future.
- url = 'lp:///apt'
- t = get_transport(url)
- real_url = t.base
- self.assertEquals(real_url, 'http://code.launchpad.net/apt/')
+ factory = FakeResolveFactory(
+ self, 'apt', dict(urls=[
+ 'http://bazaar.launchpad.net/~apt/apt/devel']))
+ transport = LaunchpadTransport('lp:///')
+ self.assertEquals('http://bazaar.launchpad.net/~apt/apt/devel',
+ transport._resolve('lp:///apt', factory))
+
+ def test_indirect_skip_bad_schemes(self):
+ factory = FakeResolveFactory(
+ self, 'apt', dict(urls=[
+ 'bad-scheme://bazaar.launchpad.net/~apt/apt/devel',
+ 'http://bazaar.launchpad.net/~apt/apt/devel',
+ 'http://another/location']))
+ transport = LaunchpadTransport('lp:///')
+ self.assertEquals('http://bazaar.launchpad.net/~apt/apt/devel',
+ transport._resolve('lp:///apt', factory))
+
+ def test_indirect_no_matching_schemes(self):
+ # If the XMLRPC call does not return any protocols we support,
+ # invalidURL is raised.
+ factory = FakeResolveFactory(
+ self, 'apt', dict(urls=[
+ 'bad-scheme://bazaar.launchpad.net/~apt/apt/devel']))
+ transport = LaunchpadTransport('lp:///')
+ self.assertRaises(errors.InvalidURL,
+ transport._resolve, 'lp:///apt', factory)
+
+ def test_indirect_fault(self):
+ # Test that XMLRPC faults get converted to InvalidURL errors.
+ factory = FakeResolveFactory(self, 'apt', None)
+ def submit(service):
+ raise xmlrpclib.Fault(42, 'something went wrong')
+ factory.submit = submit
+ transport = LaunchpadTransport('lp:///')
+ self.assertRaises(errors.InvalidURL,
+ transport._resolve, 'lp:///apt', factory)
+
+ def test_skip_bzr_ssh_launchpad_net_when_anonymous(self):
+ # Test that bzr+ssh://bazaar.launchpad.net gets skipped if
+ # Bazaar does not know the user's Launchpad ID:
+ self.assertEqual(None, get_lp_login())
+ factory = FakeResolveFactory(
+ self, 'apt', dict(urls=[
+ 'bzr+ssh://bazaar.launchpad.net/~apt/apt/devel',
+ 'http://bazaar.launchpad.net/~apt/apt/devel']))
+ transport = LaunchpadTransport('lp:///')
+ self.assertEquals('http://bazaar.launchpad.net/~apt/apt/devel',
+ transport._resolve('lp:///apt', factory))
+
+ def test_rewrite_bzr_ssh_launchpad_net(self):
+ # Test that bzr+ssh URLs get rewritten to include the user's
+ # Launchpad ID (assuming we know the Launchpad ID).
+ factory = FakeResolveFactory(
+ self, 'apt', dict(urls=[
+ 'bzr+ssh://bazaar.launchpad.net/~apt/apt/devel',
+ 'http://bazaar.launchpad.net/~apt/apt/devel']))
+ transport = LaunchpadTransport('lp:///')
+ self.assertEquals(
+ 'bzr+ssh://username@bazaar.launchpad.net/~apt/apt/devel',
+ transport._resolve('lp:///apt', factory, _lp_login='username'))
+
+ def test_no_rewrite_of_other_bzr_ssh(self):
+ # Test that we don't rewrite bzr+ssh URLs for other
+ self.assertEqual(None, get_lp_login())
+ factory = FakeResolveFactory(
+ self, 'apt', dict(urls=[
+ 'bzr+ssh://example.com/~apt/apt/devel',
+ 'http://bazaar.launchpad.net/~apt/apt/devel']))
+ transport = LaunchpadTransport('lp:///')
+ self.assertEquals('bzr+ssh://example.com/~apt/apt/devel',
+ transport._resolve('lp:///apt', factory))
# TODO: check we get an error if the url is unreasonable
def test_error_for_bad_indirection(self):
self.assertRaises(errors.InvalidURL,
- get_transport,
- 'lp://ratotehunoahu')
-
+ LaunchpadTransport, 'lp://ratotehunoahu')
+
+ def catch_redirect(self, methodname, *args):
+ transport = LaunchpadTransport('lp:///apt')
+ def _resolve(abspath):
+ self.assertEqual('lp:///apt', abspath)
+ return 'http://example.com/~apt/apt/devel'
+ transport._resolve = _resolve
+ try:
+ getattr(transport, methodname)(*args)
+ except errors.RedirectRequested, exc:
+ return exc
+ else:
+ raise self.failException('RedirectRequested not raised')
+
+ def test_redirect_on_get(self):
+ exc = self.catch_redirect('get', '.bzr/branch-format')
+ self.assertEqual('lp:///apt/.bzr/branch-format', exc.source)
+ self.assertEqual(
+ 'http://example.com/~apt/apt/devel/.bzr/branch-format', exc.target)
+
+ def test_redirect_on_mkdir(self):
+ exc = self.catch_redirect('mkdir', '.')
+ self.assertEqual('lp:///apt', exc.source)
+ self.assertEqual(
+ 'http://example.com/~apt/apt/devel', exc.target)
+
+
+class IndirectOpenBranchTests(TestCaseWithMemoryTransport):
+
+ def test_indirect_open_branch(self):
+ # Test that opening an lp: branch redirects to the real location.
+ target_branch = self.make_branch('target')
+ transport = get_transport('lp:///apt')
+ def _resolve(abspath):
+ self.assertEqual('lp:///apt', abspath)
+ return target_branch.base.rstrip('/')
+ transport._resolve = _resolve
+ branch = Branch.open_from_transport(transport)
+ self.assertEqual(target_branch.base, branch.base)
=== modified file 'bzrlib/plugins/launchpad/test_register.py'
--- a/bzrlib/plugins/launchpad/test_register.py 2007-10-12 03:18:30 +0000
+++ b/bzrlib/plugins/launchpad/test_register.py 2007-10-14 09:52:55 +0000
@@ -26,6 +26,7 @@
BaseRequest,
BranchBugLinkRequest,
BranchRegistrationRequest,
+ ResolveLaunchpadPathRequest,
LaunchpadService,
)
@@ -74,19 +75,23 @@
# Python 2.5's xmlrpclib looks for this.
_use_datetime = False
- def __init__(self, testcase):
+ def __init__(self, testcase, expect_auth):
self.testcase = testcase
+ self.expect_auth = expect_auth
def make_connection(self, host):
host, http_headers, x509 = self.get_host_info(host)
test = self.testcase
self.connected_host = host
- auth_hdrs = [v for k,v in http_headers if k == 'Authorization']
- assert len(auth_hdrs) == 1
- authinfo = auth_hdrs[0]
- expected_auth = 'testuser at launchpad.net:testpassword'
- test.assertEquals(authinfo,
- 'Basic ' + base64.encodestring(expected_auth).strip())
+ if self.expect_auth:
+ auth_hdrs = [v for k,v in http_headers if k == 'Authorization']
+ assert len(auth_hdrs) == 1
+ authinfo = auth_hdrs[0]
+ expected_auth = 'testuser at launchpad.net:testpassword'
+ test.assertEquals(authinfo,
+ 'Basic ' + base64.encodestring(expected_auth).strip())
+ else:
+ assert not http_headers
return InstrumentedXMLRPCConnection(test)
def send_request(self, connection, handler_path, request_body):
@@ -110,10 +115,11 @@
class MockLaunchpadService(LaunchpadService):
- def send_request(self, method_name, method_params):
+ def send_request(self, method_name, method_params, authenticated):
"""Stash away the method details rather than sending them to a real server"""
self.called_method_name = method_name
self.called_method_params = method_params
+ self.called_authenticated = authenticated
class TestBranchRegistration(TestCase):
@@ -145,7 +151,7 @@
def test_onto_transport(self):
"""Test how the request is sent by transmitting across a mock Transport"""
# use a real transport, but intercept at the http/xml layer
- transport = InstrumentedXMLRPCTransport(self)
+ transport = InstrumentedXMLRPCTransport(self, expect_auth=True)
service = LaunchpadService(transport)
service.registrant_email = 'testuser at launchpad.net'
service.registrant_password = 'testpassword'
@@ -167,6 +173,17 @@
'product'))
self.assertTrue(transport.got_request)
+ def test_onto_transport_unauthenticated(self):
+ """Test how an unauthenticated request is transmitted across a mock Transport"""
+ transport = InstrumentedXMLRPCTransport(self, expect_auth=False)
+ service = LaunchpadService(transport)
+ resolve = ResolveLaunchpadPathRequest('bzr')
+ resolve.submit(service)
+ self.assertEquals(transport.connected_host, 'xmlrpc.launchpad.net')
+ self.assertEquals(len(transport.sent_params), 1)
+ self.assertEquals(transport.sent_params, ('bzr', ))
+ self.assertTrue(transport.got_request)
+
def test_subclass_request(self):
"""Define a new type of xmlrpc request"""
class DummyRequest(BaseRequest):
@@ -186,10 +203,11 @@
"""Send registration to mock server"""
test_case = self
class MockRegistrationService(MockLaunchpadService):
- def send_request(self, method_name, method_params):
+ def send_request(self, method_name, method_params, authenticated):
test_case.assertEquals(method_name, "register_branch")
test_case.assertEquals(list(method_params),
['url', 'name', 'title', 'description', 'email', 'name'])
+ test_case.assertEquals(authenticated, True)
return 'result'
service = MockRegistrationService()
rego = BranchRegistrationRequest('url', 'name', 'title',
@@ -201,10 +219,11 @@
"""Send registration to mock server"""
test_case = self
class MockRegistrationService(MockLaunchpadService):
- def send_request(self, method_name, method_params):
+ def send_request(self, method_name, method_params, authenticated):
test_case.assertEquals(method_name, "register_branch")
test_case.assertEquals(list(method_params),
['http://server/branch', 'branch', '', '', '', ''])
+ test_case.assertEquals(authenticated, True)
return 'result'
service = MockRegistrationService()
rego = BranchRegistrationRequest('http://server/branch')
@@ -215,12 +234,35 @@
"""Send bug-branch link to mock server"""
test_case = self
class MockService(MockLaunchpadService):
- def send_request(self, method_name, method_params):
+ def send_request(self, method_name, method_params, authenticated):
test_case.assertEquals(method_name, "link_branch_to_bug")
test_case.assertEquals(list(method_params),
['http://server/branch', 1234, ''])
+ test_case.assertEquals(authenticated, True)
return 'http://launchpad.net/bug/1234'
service = MockService()
rego = BranchBugLinkRequest('http://server/branch', 1234)
result = rego.submit(service)
self.assertEquals(result, 'http://launchpad.net/bug/1234')
+
+ def test_mock_resolve_lp_url(self):
+ test_case = self
+ class MockService(MockLaunchpadService):
+ def send_request(self, method_name, method_params, authenticated):
+ test_case.assertEquals(method_name, "resolve_lp_path")
+ test_case.assertEquals(list(method_params), ['bzr'])
+ test_case.assertEquals(authenticated, False)
+ return dict(urls=[
+ 'bzr+ssh://bazaar.launchpad.net~bzr/bzr/trunk',
+ 'sftp://bazaar.launchpad.net~bzr/bzr/trunk',
+ 'bzr+http://bazaar.launchpad.net~bzr/bzr/trunk',
+ 'http://bazaar.launchpad.net~bzr/bzr/trunk'])
+ service = MockService()
+ resolve = ResolveLaunchpadPathRequest('bzr')
+ result = resolve.submit(service)
+ self.assertTrue('urls' in result)
+ self.assertEquals(result['urls'], [
+ 'bzr+ssh://bazaar.launchpad.net~bzr/bzr/trunk',
+ 'sftp://bazaar.launchpad.net~bzr/bzr/trunk',
+ 'bzr+http://bazaar.launchpad.net~bzr/bzr/trunk',
+ 'http://bazaar.launchpad.net~bzr/bzr/trunk'])
More information about the bazaar-commits
mailing list