25
from urlparse import urlsplit, urlunsplit
25
28
from bzrlib import (
28
34
from bzrlib.transport import (
36
register_urlparse_netloc_protocol,
34
def launchpad_transport_indirect(base_url):
35
"""Uses Launchpad.net as a directory of open source software"""
36
if base_url.startswith('lp:///'):
37
real_url = 'http://code.launchpad.net/' + base_url[6:]
38
elif base_url.startswith('lp:') and base_url[3] != '/':
39
real_url = 'http://code.launchpad.net/' + base_url[3:]
41
raise errors.InvalidURL(path=base_url)
42
return get_transport(real_url)
40
from bzrlib.plugins.launchpad.lp_registration import (
41
LaunchpadService, ResolveLaunchpadPathRequest)
42
from bzrlib.plugins.launchpad.account import get_lp_login
45
# As bzrlib.transport.remote may not be loaded yet, make sure bzr+ssh
46
# is counted as a netloc protocol.
47
register_urlparse_netloc_protocol('bzr+ssh')
48
register_urlparse_netloc_protocol('lp')
51
class LaunchpadTransport(Transport):
52
"""lp:/// URL transport
54
This transport redirects requests to the real branch location
55
after resolving the URL via an XMLRPC request to Launchpad.
58
def __init__(self, base):
59
super(LaunchpadTransport, self).__init__(base)
60
# We only support URLs without a netloc
61
netloc = urlsplit(base)[1]
63
raise errors.InvalidURL(path=base)
65
def _requires_launchpad_login(self, scheme, netloc, path, query,
67
"""Does the URL require a Launchpad login in order to be reached?
69
The URL is specified by its parsed components, as returned from
72
return (scheme in ('bzr+ssh', 'sftp')
73
and (netloc.endswith('launchpad.net')
74
or netloc.endswith('launchpad.dev')))
76
def _resolve(self, abspath,
77
_request_factory=ResolveLaunchpadPathRequest,
79
"""Resolve the base URL for this transport."""
80
path = urlsplit(abspath)[2].lstrip('/')
81
# Perform an XMLRPC request to resolve the path
82
resolve = _request_factory(path)
83
service = LaunchpadService()
85
result = resolve.submit(service)
86
except xmlrpclib.Fault, fault:
87
raise errors.InvalidURL(
88
path=abspath, extra=fault.faultString)
90
if 'launchpad' in debug.debug_flags:
91
trace.mutter("resolve_lp_path(%r) == %r", path, result)
94
_lp_login = get_lp_login()
95
for url in result['urls']:
96
scheme, netloc, path, query, fragment = urlsplit(url)
97
if self._requires_launchpad_login(scheme, netloc, path, query,
99
# Only accept launchpad.net bzr+ssh URLs if we know
100
# the user's Launchpad login:
101
if _lp_login is None:
103
url = urlunsplit((scheme, '%s@%s' % (_lp_login, netloc),
104
path, query, fragment))
107
# Use the URL if we can create a transport for it.
110
except (errors.PathError, errors.TransportError):
115
raise errors.InvalidURL(path=abspath,
116
extra='no supported schemes')
119
def _request_redirect(self, relpath):
120
source = urlutils.join(self.base, relpath)
121
# Split the source location into the branch location, and the
122
# extra path components.
123
pos = source.find('/.bzr/')
125
branchpath = source[:pos]
130
target = self._resolve(branchpath) + extra
131
raise errors.RedirectRequested(
135
def get(self, relpath):
136
"""See Transport.get()."""
137
self._request_redirect(relpath)
139
def mkdir(self, relpath, mode=None):
140
"""See Transport.mkdir()."""
141
self._request_redirect(relpath)
45
144
def get_test_permutations():