13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
"""Directory lookup that uses Launchpad."""
20
from urlparse import urlsplit
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
"""Transport indirection that uses Launchpad as a directory lookup.
20
When the transport is opened, it immediately redirects to a url
21
on Launchpad, which can then either serve the branch itself or redirect
25
from urlparse import urlsplit, urlunsplit
23
28
from bzrlib import (
28
34
from bzrlib.transport import (
30
36
register_urlparse_netloc_protocol,
33
40
from bzrlib.plugins.launchpad.lp_registration import (
41
48
register_urlparse_netloc_protocol('lp')
44
class LaunchpadDirectory(object):
46
def _requires_launchpad_login(self, scheme, netloc, path, query,
48
"""Does the URL require a Launchpad login in order to be reached?
50
The URL is specified by its parsed components, as returned from
53
return (scheme in ('bzr+ssh', 'sftp')
54
and (netloc.endswith('launchpad.net')
55
or netloc.endswith('launchpad.dev')))
57
def look_up(self, name, url):
58
"""See DirectoryService.look_up"""
59
return self._resolve(url)
61
def _resolve(self, url,
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 _resolve(self, abspath,
62
66
_request_factory=ResolveLaunchpadPathRequest,
64
68
"""Resolve the base URL for this transport."""
65
service = LaunchpadService.for_url(url)
66
result = urlsplit(url)
67
resolve = _request_factory(result[2].strip('/'))
69
path = urlsplit(abspath)[2].lstrip('/')
70
# Perform an XMLRPC request to resolve the path
71
resolve = _request_factory(path)
72
service = LaunchpadService()
69
74
result = resolve.submit(service)
70
75
except xmlrpclib.Fault, fault:
71
76
raise errors.InvalidURL(
72
path=url, extra=fault.faultString)
77
path=abspath, extra=fault.faultString)
74
79
if 'launchpad' in debug.debug_flags:
75
trace.mutter("resolve_lp_path(%r) == %r", url, result)
80
trace.mutter("resolve_lp_path(%r) == %r", path, result)
77
82
if _lp_login is None:
78
83
_lp_login = get_lp_login()
80
84
for url in result['urls']:
81
85
scheme, netloc, path, query, fragment = urlsplit(url)
82
if self._requires_launchpad_login(scheme, netloc, path, query,
86
if scheme == 'bzr+ssh' and (netloc.endswith('launchpad.net') or
87
netloc.endswith('launchpad.dev')):
84
88
# Only accept launchpad.net bzr+ssh URLs if we know
85
89
# the user's Launchpad login:
86
if _lp_login is not None:
88
90
if _lp_login is None:
91
'You have not informed bzr of your Launchpad ID, and you must do this to\n'
92
'write to Launchpad or access private data. See "bzr help launchpad-login".')
92
url = urlunsplit((scheme, '%s@%s' % (_lp_login, netloc),
93
path, query, fragment))
95
96
# Use the URL if we can create a transport for it.
103
raise errors.InvalidURL(path=url, extra='no supported schemes')
104
raise errors.InvalidURL(path=abspath,
105
extra='no supported schemes')
108
def _request_redirect(self, relpath):
109
source = urlutils.join(self.base, relpath)
110
# Split the source location into the branch location, and the
111
# extra path components.
112
pos = source.find('/.bzr/')
114
branchpath = source[:pos]
119
target = self._resolve(branchpath) + extra
120
raise errors.RedirectRequested(
124
def get(self, relpath):
125
"""See Transport.get()."""
126
self._request_redirect(relpath)
128
def mkdir(self, relpath, mode=None):
129
"""See Transport.mkdir()."""
130
self._request_redirect(relpath)
107
133
def get_test_permutations():
108
134
# Since this transport doesn't do anything once opened, it's not subjected