/usr/lib/python2.7/dist-packages/bzrlib/plugins/launchpad/lp_directory.py is in python-bzrlib 2.7.0-2ubuntu3.1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | # Copyright (C) 2007-2011 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
"""Directory lookup that uses Launchpad."""
from __future__ import absolute_import
from urlparse import urlsplit
import xmlrpclib
from bzrlib import (
debug,
errors,
trace,
transport,
)
from bzrlib.i18n import gettext
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.
transport.register_urlparse_netloc_protocol('bzr+ssh')
transport.register_urlparse_netloc_protocol('lp')
_ubuntu_series_shortcuts = {
'n': 'natty',
'm': 'maverick',
'l': 'lucid',
'k': 'karmic',
'j': 'jaunty',
'h': 'hardy',
'd': 'dapper',
}
class LaunchpadDirectory(object):
def _requires_launchpad_login(self, scheme, netloc, path, query,
fragment):
"""Does the URL require a Launchpad login in order to be reached?
The URL is specified by its parsed components, as returned from
urlsplit.
"""
return (scheme in ('bzr+ssh', 'sftp')
and (netloc.endswith('launchpad.net')
or netloc.endswith('launchpad.dev')))
def look_up(self, name, url):
"""See DirectoryService.look_up"""
return self._resolve(url)
def _resolve_locally(self, path, url, _request_factory):
# This is the best I could work out about XMLRPC. If an lp: url
# includes ~user, then it is specially validated. Otherwise, it is just
# sent to +branch/$path.
_, netloc, _, _, _ = urlsplit(url)
if netloc == '':
netloc = LaunchpadService.DEFAULT_INSTANCE
base_url = LaunchpadService.LAUNCHPAD_DOMAINS[netloc]
base = 'bzr+ssh://bazaar.%s/' % (base_url,)
maybe_invalid = False
if path.startswith('~'):
# A ~user style path, validate it a bit.
# If a path looks fishy, fall back to asking XMLRPC to
# resolve it for us. That way we still get their nicer error
# messages.
parts = path.split('/')
if (len(parts) < 3
or (parts[1] in ('ubuntu', 'debian') and len(parts) < 5)):
# This special case requires 5-parts to be valid.
maybe_invalid = True
else:
base += '+branch/'
if maybe_invalid:
return self._resolve_via_xmlrpc(path, url, _request_factory)
return {'urls': [base + path]}
def _resolve_via_xmlrpc(self, path, url, _request_factory):
service = LaunchpadService.for_url(url)
resolve = _request_factory(path)
try:
result = resolve.submit(service)
except xmlrpclib.Fault, fault:
raise errors.InvalidURL(
path=url, extra=fault.faultString)
return result
def _update_url_scheme(self, url):
# Do ubuntu: and debianlp: expansions.
scheme, netloc, path, query, fragment = urlsplit(url)
if scheme in ('ubuntu', 'debianlp'):
if scheme == 'ubuntu':
distro = 'ubuntu'
distro_series = _ubuntu_series_shortcuts
elif scheme == 'debianlp':
distro = 'debian'
# No shortcuts for Debian distroseries.
distro_series = {}
else:
raise AssertionError('scheme should be ubuntu: or debianlp:')
# Split the path. It's either going to be 'project' or
# 'series/project', but recognize that it may be a series we don't
# know about.
path_parts = path.split('/')
if len(path_parts) == 1:
# It's just a project name.
lp_url_template = 'lp:%(distro)s/%(project)s'
project = path_parts[0]
series = None
elif len(path_parts) == 2:
# It's a series and project.
lp_url_template = 'lp:%(distro)s/%(series)s/%(project)s'
series, project = path_parts
else:
# There are either 0 or > 2 path parts, neither of which is
# supported for these schemes.
raise errors.InvalidURL('Bad path: %s' % url)
# Expand any series shortcuts, but keep unknown series.
series = distro_series.get(series, series)
# Hack the url and let the following do the final resolution.
url = lp_url_template % dict(
distro=distro,
series=series,
project=project)
scheme, netloc, path, query, fragment = urlsplit(url)
return url, path
def _expand_user(self, path, url, lp_login):
if path.startswith('~/'):
if lp_login is None:
raise errors.InvalidURL(path=url,
extra='Cannot resolve "~" to your username.'
' See "bzr help launchpad-login"')
path = '~' + lp_login + path[1:]
return path
def _resolve(self, url,
_request_factory=ResolveLaunchpadPathRequest,
_lp_login=None):
"""Resolve the base URL for this transport."""
url, path = self._update_url_scheme(url)
if _lp_login is None:
_lp_login = get_lp_login()
path = path.strip('/')
path = self._expand_user(path, url, _lp_login)
if _lp_login is not None:
result = self._resolve_locally(path, url, _request_factory)
if 'launchpad' in debug.debug_flags:
local_res = result
result = self._resolve_via_xmlrpc(path, url, _request_factory)
trace.note(gettext(
'resolution for {0}\n local: {1}\n remote: {2}').format(
url, local_res['urls'], result['urls']))
else:
result = self._resolve_via_xmlrpc(path, url, _request_factory)
if 'launchpad' in debug.debug_flags:
trace.mutter("resolve_lp_path(%r) == %r", url, result)
_warned_login = False
for url in result['urls']:
scheme, netloc, path, query, fragment = urlsplit(url)
if self._requires_launchpad_login(scheme, netloc, path, query,
fragment):
# Only accept launchpad.net bzr+ssh URLs if we know
# the user's Launchpad login:
if _lp_login is not None:
break
if _lp_login is None:
if not _warned_login:
trace.warning(
'You have not informed bzr of your Launchpad ID, and you must do this to\n'
'write to Launchpad or access private data. See "bzr help launchpad-login".')
_warned_login = True
else:
# Use the URL if we can create a transport for it.
try:
transport.get_transport(url)
except (errors.PathError, errors.TransportError):
pass
else:
break
else:
raise errors.InvalidURL(path=url, extra='no supported schemes')
return url
def get_test_permutations():
# Since this transport doesn't do anything once opened, it's not subjected
# to the usual transport tests.
return []
|