/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5609.24.7 by John Arbash Meinel
Fix bug #397739. Avoid doing an XMLRPC lookup if a user
1
# Copyright (C) 2007-2011 Canonical Ltd
2245.8.3 by Martin Pool
Start adding indirection transport
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2245.8.3 by Martin Pool
Start adding indirection transport
16
6379.6.7 by Jelmer Vernooij
Move importing from future until after doc string, otherwise the doc string will disappear.
17
"""Directory lookup that uses Launchpad."""
18
6379.6.3 by Jelmer Vernooij
Use absolute_import.
19
from __future__ import absolute_import
2245.8.3 by Martin Pool
Start adding indirection transport
20
6791.2.3 by Jelmer Vernooij
Fix more imports.
21
try:
22
    from urllib.parse import urlsplit
23
except ImportError:  # python < 3
24
    from urlparse import urlsplit
7027.7.1 by Jelmer Vernooij
Fix launchpad plugin tests on python 3.
25
try:
26
    from xmlrpc.client import Fault
7045.5.6 by Jelmer Vernooij
Fix launchpad tests.
27
except ImportError:  # Python < 3
7027.7.1 by Jelmer Vernooij
Fix launchpad plugin tests on python 3.
28
    from xmlrpclib import Fault
2898.4.4 by James Henstridge
Changes to account for modifications to the XMLRPC API.
29
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
30
from ... import (
2898.4.14 by James Henstridge
* Use urlsplit() to process URLs.
31
    debug,
2245.8.4 by Martin Pool
lp:/// indirection works
32
    errors,
2898.4.14 by James Henstridge
* Use urlsplit() to process URLs.
33
    trace,
5609.9.1 by Martin
Blindly change all users of get_transport to address the function via the transport module
34
    transport,
2245.8.4 by Martin Pool
lp:/// indirection works
35
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
36
from ...i18n import gettext
2245.8.4 by Martin Pool
lp:/// indirection works
37
7290.35.1 by Jelmer Vernooij
Allow running tests without launchpadlib installed.
38
from .uris import (
7240.5.7 by Jelmer Vernooij
Move DEFAULT_INSTANCE.
39
    DEFAULT_INSTANCE,
40
    LAUNCHPAD_DOMAINS,
41
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
42
from .lp_registration import (
6729.6.1 by Jelmer Vernooij
Move urlutils errors.
43
    InvalidURL,
44
    LaunchpadService,
45
    ResolveLaunchpadPathRequest,
46
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
47
from .account import get_lp_login
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
48
49
50
# As breezy.transport.remote may not be loaded yet, make sure bzr+ssh
2898.4.9 by James Henstridge
Add some more tests for the bzr+ssh://bazaar.launchpad.net URL
51
# is counted as a netloc protocol.
5609.9.1 by Martin
Blindly change all users of get_transport to address the function via the transport module
52
transport.register_urlparse_netloc_protocol('bzr+ssh')
53
transport.register_urlparse_netloc_protocol('lp')
7240.11.1 by Jelmer Vernooij
Add support for lp+bzr.
54
transport.register_urlparse_netloc_protocol('lp+bzr')
2898.4.9 by James Henstridge
Add some more tests for the bzr+ssh://bazaar.launchpad.net URL
55
56
7240.5.8 by Jelmer Vernooij
Factor out methods.
57
def _requires_launchpad_login(scheme, netloc, path, query,
58
                              fragment):
59
    """Does the URL require a Launchpad login in order to be reached?
60
61
    The URL is specified by its parsed components, as returned from
62
    urlsplit.
63
    """
64
    return (scheme in ('bzr+ssh', 'sftp')
65
            and (netloc.endswith('launchpad.net') or
7302.1.1 by Colin Watson
Handle renaming of launchpad.dev to launchpad.test.
66
                 netloc.endswith('launchpad.test')))
7240.5.8 by Jelmer Vernooij
Factor out methods.
67
68
69
def _expand_user(path, url, lp_login):
70
    if path.startswith('~/'):
71
        if lp_login is None:
72
            raise InvalidURL(path=url,
73
                             extra='Cannot resolve "~" to your username.'
74
                             ' See "bzr help launchpad-login"')
75
        path = '~' + lp_login + path[1:]
76
    return path
77
78
79
def _update_url_scheme(url):
80
    # Do ubuntu: and debianlp: expansions.
81
    scheme, netloc, path, query, fragment = urlsplit(url)
82
    if scheme in ('ubuntu', 'debianlp'):
83
        if scheme == 'ubuntu':
84
            distro = 'ubuntu'
85
        elif scheme == 'debianlp':
86
            distro = 'debian'
87
            # No shortcuts for Debian distroseries.
88
        else:
89
            raise AssertionError('scheme should be ubuntu: or debianlp:')
90
        # Split the path.  It's either going to be 'project' or
91
        # 'series/project', but recognize that it may be a series we don't
92
        # know about.
93
        path_parts = path.split('/')
94
        if len(path_parts) == 1:
95
            # It's just a project name.
96
            lp_url_template = 'lp:%(distro)s/%(project)s'
97
            project = path_parts[0]
98
            series = None
99
        elif len(path_parts) == 2:
100
            # It's a series and project.
101
            lp_url_template = 'lp:%(distro)s/%(series)s/%(project)s'
102
            series, project = path_parts
103
        else:
104
            # There are either 0 or > 2 path parts, neither of which is
105
            # supported for these schemes.
106
            raise InvalidURL('Bad path: %s' % url)
107
        # Hack the url and let the following do the final resolution.
108
        url = lp_url_template % dict(
109
            distro=distro,
110
            series=series,
111
            project=project)
112
        scheme, netloc, path, query, fragment = urlsplit(url)
7240.11.2 by Jelmer Vernooij
Merge trunk.
113
    elif scheme == 'lp+bzr':
114
        scheme = 'lp'
7240.5.8 by Jelmer Vernooij
Factor out methods.
115
    return url, path
116
117
3251.4.1 by Aaron Bentley
Convert LP transport into directory service
118
class LaunchpadDirectory(object):
2898.4.8 by James Henstridge
Switch lp: over to a pass-through transport, so that the XMLRPC gets
119
7268.11.2 by Jelmer Vernooij
Add purpose argument.
120
    def look_up(self, name, url, purpose=None):
3251.4.5 by Aaron Bentley
Add docstring
121
        """See DirectoryService.look_up"""
3251.4.1 by Aaron Bentley
Convert LP transport into directory service
122
        return self._resolve(url)
123
5609.24.9 by John Arbash Meinel
A bunch more tests and bug fixes for the local resolution.
124
    def _resolve_locally(self, path, url, _request_factory):
125
        # This is the best I could work out about XMLRPC. If an lp: url
126
        # includes ~user, then it is specially validated. Otherwise, it is just
127
        # sent to +branch/$path.
128
        _, netloc, _, _, _ = urlsplit(url)
129
        if netloc == '':
7240.5.7 by Jelmer Vernooij
Move DEFAULT_INSTANCE.
130
            netloc = DEFAULT_INSTANCE
7240.5.4 by Jelmer Vernooij
Fix last one.
131
        base_url = LAUNCHPAD_DOMAINS[netloc]
5609.24.9 by John Arbash Meinel
A bunch more tests and bug fixes for the local resolution.
132
        base = 'bzr+ssh://bazaar.%s/' % (base_url,)
133
        maybe_invalid = False
134
        if path.startswith('~'):
135
            # A ~user style path, validate it a bit.
136
            # If a path looks fishy, fall back to asking XMLRPC to
137
            # resolve it for us. That way we still get their nicer error
138
            # messages.
139
            parts = path.split('/')
140
            if (len(parts) < 3
7143.15.2 by Jelmer Vernooij
Run autopep8.
141
                    or (parts[1] in ('ubuntu', 'debian') and len(parts) < 5)):
5609.24.9 by John Arbash Meinel
A bunch more tests and bug fixes for the local resolution.
142
                # This special case requires 5-parts to be valid.
143
                maybe_invalid = True
144
        else:
145
            base += '+branch/'
146
        if maybe_invalid:
147
            return self._resolve_via_xmlrpc(path, url, _request_factory)
148
        return {'urls': [base + path]}
5609.24.7 by John Arbash Meinel
Fix bug #397739. Avoid doing an XMLRPC lookup if a user
149
150
    def _resolve_via_xmlrpc(self, path, url, _request_factory):
151
        service = LaunchpadService.for_url(url)
152
        resolve = _request_factory(path)
153
        try:
154
            result = resolve.submit(service)
7027.7.1 by Jelmer Vernooij
Fix launchpad plugin tests on python 3.
155
        except Fault as fault:
6729.6.1 by Jelmer Vernooij
Move urlutils errors.
156
            raise InvalidURL(
5609.24.7 by John Arbash Meinel
Fix bug #397739. Avoid doing an XMLRPC lookup if a user
157
                path=url, extra=fault.faultString)
158
        return result
159
160
    def _resolve(self, url,
161
                 _request_factory=ResolveLaunchpadPathRequest,
162
                 _lp_login=None):
163
        """Resolve the base URL for this transport."""
7240.5.8 by Jelmer Vernooij
Factor out methods.
164
        url, path = _update_url_scheme(url)
5609.24.7 by John Arbash Meinel
Fix bug #397739. Avoid doing an XMLRPC lookup if a user
165
        if _lp_login is None:
166
            _lp_login = get_lp_login()
167
        path = path.strip('/')
7240.5.8 by Jelmer Vernooij
Factor out methods.
168
        path = _expand_user(path, url, _lp_login)
5609.24.7 by John Arbash Meinel
Fix bug #397739. Avoid doing an XMLRPC lookup if a user
169
        if _lp_login is not None:
5609.24.9 by John Arbash Meinel
A bunch more tests and bug fixes for the local resolution.
170
            result = self._resolve_locally(path, url, _request_factory)
171
            if 'launchpad' in debug.debug_flags:
5609.24.11 by John Arbash Meinel
If someone uses -Dlaunchpad, use the 'official' URL instead of the local one.
172
                local_res = result
173
                result = self._resolve_via_xmlrpc(path, url, _request_factory)
6150.3.4 by Jonathan Riddell
more launchpad plugin gettext()ing
174
                trace.note(gettext(
175
                    'resolution for {0}\n  local: {1}\n remote: {2}').format(
7143.15.2 by Jelmer Vernooij
Run autopep8.
176
                    url, local_res['urls'], result['urls']))
5609.24.7 by John Arbash Meinel
Fix bug #397739. Avoid doing an XMLRPC lookup if a user
177
        else:
178
            result = self._resolve_via_xmlrpc(path, url, _request_factory)
2898.4.8 by James Henstridge
Switch lp: over to a pass-through transport, so that the XMLRPC gets
179
2898.4.14 by James Henstridge
* Use urlsplit() to process URLs.
180
        if 'launchpad' in debug.debug_flags:
4505.6.2 by Jonathan Lange
Extract a method that gets a service from a URL.
181
            trace.mutter("resolve_lp_path(%r) == %r", url, result)
2898.4.14 by James Henstridge
* Use urlsplit() to process URLs.
182
3270.4.1 by James Westby
Warn the user when resolving lp: URLs if they haven't set their login.
183
        _warned_login = False
2898.4.8 by James Henstridge
Switch lp: over to a pass-through transport, so that the XMLRPC gets
184
        for url in result['urls']:
185
            scheme, netloc, path, query, fragment = urlsplit(url)
7240.5.8 by Jelmer Vernooij
Factor out methods.
186
            if _requires_launchpad_login(scheme, netloc, path, query,
187
                                         fragment):
2898.4.8 by James Henstridge
Switch lp: over to a pass-through transport, so that the XMLRPC gets
188
                # Only accept launchpad.net bzr+ssh URLs if we know
189
                # the user's Launchpad login:
3777.1.21 by Aaron Bentley
Stop including usernames in resolved lp: urls
190
                if _lp_login is not None:
191
                    break
2898.4.9 by James Henstridge
Add some more tests for the bzr+ssh://bazaar.launchpad.net URL
192
                if _lp_login is None:
3270.4.1 by James Westby
Warn the user when resolving lp: URLs if they haven't set their login.
193
                    if not _warned_login:
3834.1.2 by Martin Pool
Better message when launchpad-login is needed
194
                        trace.warning(
7143.15.2 by Jelmer Vernooij
Run autopep8.
195
                            'You have not informed bzr of your Launchpad ID, and you must do this to\n'
196
                            'write to Launchpad or access private data.  See "bzr help launchpad-login".')
3270.4.1 by James Westby
Warn the user when resolving lp: URLs if they haven't set their login.
197
                        _warned_login = True
2898.4.15 by James Henstridge
Use get_transport() to decide whether Bazaar supports a given URL.
198
            else:
199
                # Use the URL if we can create a transport for it.
200
                try:
5609.9.1 by Martin
Blindly change all users of get_transport to address the function via the transport module
201
                    transport.get_transport(url)
2898.4.15 by James Henstridge
Use get_transport() to decide whether Bazaar supports a given URL.
202
                except (errors.PathError, errors.TransportError):
203
                    pass
204
                else:
205
                    break
2898.4.8 by James Henstridge
Switch lp: over to a pass-through transport, so that the XMLRPC gets
206
        else:
6729.6.1 by Jelmer Vernooij
Move urlutils errors.
207
            raise InvalidURL(path=url, extra='no supported schemes')
2898.4.8 by James Henstridge
Switch lp: over to a pass-through transport, so that the XMLRPC gets
208
        return url
209
2245.8.3 by Martin Pool
Start adding indirection transport
210
211
def get_test_permutations():
212
    # Since this transport doesn't do anything once opened, it's not subjected
213
    # to the usual transport tests.
214
    return []