/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
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
38
from .lp_registration import (
6729.6.1 by Jelmer Vernooij
Move urlutils errors.
39
    InvalidURL,
40
    LaunchpadService,
41
    ResolveLaunchpadPathRequest,
42
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
43
from .account import get_lp_login
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
44
45
46
# 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
47
# 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
48
transport.register_urlparse_netloc_protocol('bzr+ssh')
49
transport.register_urlparse_netloc_protocol('lp')
2898.4.9 by James Henstridge
Add some more tests for the bzr+ssh://bazaar.launchpad.net URL
50
5462.4.5 by Barry Warsaw
We only need to include distroseries shortcuts.
51
_ubuntu_series_shortcuts = {
5462.4.3 by Barry Warsaw
* Add back Ubuntu distroseries shortcuts.
52
    'n': 'natty',
53
    'm': 'maverick',
54
    'l': 'lucid',
55
    'k': 'karmic',
56
    'j': 'jaunty',
57
    'h': 'hardy',
58
    'd': 'dapper',
5462.4.1 by Barry Warsaw
Added support for ubuntu: and debianlp: schemes, accessing the relevant
59
    }
60
2898.4.9 by James Henstridge
Add some more tests for the bzr+ssh://bazaar.launchpad.net URL
61
3251.4.1 by Aaron Bentley
Convert LP transport into directory service
62
class LaunchpadDirectory(object):
2898.4.8 by James Henstridge
Switch lp: over to a pass-through transport, so that the XMLRPC gets
63
3031.2.4 by jml at canonical
Only split the URL once.
64
    def _requires_launchpad_login(self, scheme, netloc, path, query,
65
                                  fragment):
66
        """Does the URL require a Launchpad login in order to be reached?
67
68
        The URL is specified by its parsed components, as returned from
69
        urlsplit.
70
        """
3031.2.3 by jml at canonical
Make the test pass -- don't include sftp URLs if there's no lp login.
71
        return (scheme in ('bzr+ssh', 'sftp')
72
                and (netloc.endswith('launchpad.net')
73
                     or netloc.endswith('launchpad.dev')))
3031.2.1 by jml at canonical
Factor out the method that determines if a URL is a LP url.
74
3251.4.1 by Aaron Bentley
Convert LP transport into directory service
75
    def look_up(self, name, url):
3251.4.5 by Aaron Bentley
Add docstring
76
        """See DirectoryService.look_up"""
3251.4.1 by Aaron Bentley
Convert LP transport into directory service
77
        return self._resolve(url)
78
5609.24.9 by John Arbash Meinel
A bunch more tests and bug fixes for the local resolution.
79
    def _resolve_locally(self, path, url, _request_factory):
80
        # This is the best I could work out about XMLRPC. If an lp: url
81
        # includes ~user, then it is specially validated. Otherwise, it is just
82
        # sent to +branch/$path.
83
        _, netloc, _, _, _ = urlsplit(url)
84
        if netloc == '':
85
            netloc = LaunchpadService.DEFAULT_INSTANCE
86
        base_url = LaunchpadService.LAUNCHPAD_DOMAINS[netloc]
87
        base = 'bzr+ssh://bazaar.%s/' % (base_url,)
88
        maybe_invalid = False
89
        if path.startswith('~'):
90
            # A ~user style path, validate it a bit.
91
            # If a path looks fishy, fall back to asking XMLRPC to
92
            # resolve it for us. That way we still get their nicer error
93
            # messages.
94
            parts = path.split('/')
95
            if (len(parts) < 3
96
                or (parts[1] in ('ubuntu', 'debian') and len(parts) < 5)):
97
                # This special case requires 5-parts to be valid.
98
                maybe_invalid = True
99
        else:
100
            base += '+branch/'
101
        if maybe_invalid:
102
            return self._resolve_via_xmlrpc(path, url, _request_factory)
103
        return {'urls': [base + path]}
5609.24.7 by John Arbash Meinel
Fix bug #397739. Avoid doing an XMLRPC lookup if a user
104
105
    def _resolve_via_xmlrpc(self, path, url, _request_factory):
106
        service = LaunchpadService.for_url(url)
107
        resolve = _request_factory(path)
108
        try:
109
            result = resolve.submit(service)
7027.7.1 by Jelmer Vernooij
Fix launchpad plugin tests on python 3.
110
        except Fault as fault:
6729.6.1 by Jelmer Vernooij
Move urlutils errors.
111
            raise InvalidURL(
5609.24.7 by John Arbash Meinel
Fix bug #397739. Avoid doing an XMLRPC lookup if a user
112
                path=url, extra=fault.faultString)
113
        return result
114
115
    def _update_url_scheme(self, url):
5462.4.1 by Barry Warsaw
Added support for ubuntu: and debianlp: schemes, accessing the relevant
116
        # Do ubuntu: and debianlp: expansions.
5462.4.10 by Vincent Ladeuil
Fix python2.4 compatibility.
117
        scheme, netloc, path, query, fragment = urlsplit(url)
118
        if scheme in ('ubuntu', 'debianlp'):
119
            if scheme == 'ubuntu':
5462.4.1 by Barry Warsaw
Added support for ubuntu: and debianlp: schemes, accessing the relevant
120
                distro = 'ubuntu'
5462.4.5 by Barry Warsaw
We only need to include distroseries shortcuts.
121
                distro_series = _ubuntu_series_shortcuts
5462.4.10 by Vincent Ladeuil
Fix python2.4 compatibility.
122
            elif scheme == 'debianlp':
5462.4.1 by Barry Warsaw
Added support for ubuntu: and debianlp: schemes, accessing the relevant
123
                distro = 'debian'
5462.4.5 by Barry Warsaw
We only need to include distroseries shortcuts.
124
                # No shortcuts for Debian distroseries.
125
                distro_series = {}
5462.4.1 by Barry Warsaw
Added support for ubuntu: and debianlp: schemes, accessing the relevant
126
            else:
127
                raise AssertionError('scheme should be ubuntu: or debianlp:')
5462.4.3 by Barry Warsaw
* Add back Ubuntu distroseries shortcuts.
128
            # Split the path.  It's either going to be 'project' or
129
            # 'series/project', but recognize that it may be a series we don't
130
            # know about.
5462.4.10 by Vincent Ladeuil
Fix python2.4 compatibility.
131
            path_parts = path.split('/')
5462.4.3 by Barry Warsaw
* Add back Ubuntu distroseries shortcuts.
132
            if len(path_parts) == 1:
133
                # It's just a project name.
5462.4.1 by Barry Warsaw
Added support for ubuntu: and debianlp: schemes, accessing the relevant
134
                lp_url_template = 'lp:%(distro)s/%(project)s'
135
                project = path_parts[0]
5462.4.3 by Barry Warsaw
* Add back Ubuntu distroseries shortcuts.
136
                series = None
137
            elif len(path_parts) == 2:
138
                # It's a series and project.
5462.4.1 by Barry Warsaw
Added support for ubuntu: and debianlp: schemes, accessing the relevant
139
                lp_url_template = 'lp:%(distro)s/%(series)s/%(project)s'
5462.4.3 by Barry Warsaw
* Add back Ubuntu distroseries shortcuts.
140
                series, project = path_parts
141
            else:
142
                # There are either 0 or > 2 path parts, neither of which is
143
                # supported for these schemes.
6729.6.1 by Jelmer Vernooij
Move urlutils errors.
144
                raise InvalidURL('Bad path: %s' % url)
5462.4.3 by Barry Warsaw
* Add back Ubuntu distroseries shortcuts.
145
            # Expand any series shortcuts, but keep unknown series.
146
            series = distro_series.get(series, series)
5462.4.1 by Barry Warsaw
Added support for ubuntu: and debianlp: schemes, accessing the relevant
147
            # Hack the url and let the following do the final resolution.
148
            url = lp_url_template % dict(
149
                distro=distro,
150
                series=series,
151
                project=project)
5462.4.10 by Vincent Ladeuil
Fix python2.4 compatibility.
152
            scheme, netloc, path, query, fragment = urlsplit(url)
5609.24.7 by John Arbash Meinel
Fix bug #397739. Avoid doing an XMLRPC lookup if a user
153
        return url, path
154
5609.24.8 by John Arbash Meinel
Fix the launchpad-login tests. And fix a bad commit typo.
155
    def _expand_user(self, path, url, lp_login):
5361.1.1 by John Arbash Meinel
Handle a simple ~ in lp: urls.
156
        if path.startswith('~/'):
5609.24.7 by John Arbash Meinel
Fix bug #397739. Avoid doing an XMLRPC lookup if a user
157
            if lp_login is None:
6729.6.1 by Jelmer Vernooij
Move urlutils errors.
158
                raise InvalidURL(path=url,
5361.1.1 by John Arbash Meinel
Handle a simple ~ in lp: urls.
159
                    extra='Cannot resolve "~" to your username.'
160
                          ' See "bzr help launchpad-login"')
5609.24.7 by John Arbash Meinel
Fix bug #397739. Avoid doing an XMLRPC lookup if a user
161
            path = '~' + lp_login + path[1:]
162
        return path
163
164
    def _resolve(self, url,
165
                 _request_factory=ResolveLaunchpadPathRequest,
166
                 _lp_login=None):
167
        """Resolve the base URL for this transport."""
168
        url, path = self._update_url_scheme(url)
169
        if _lp_login is None:
170
            _lp_login = get_lp_login()
171
        path = path.strip('/')
5609.24.8 by John Arbash Meinel
Fix the launchpad-login tests. And fix a bad commit typo.
172
        path = self._expand_user(path, url, _lp_login)
5609.24.7 by John Arbash Meinel
Fix bug #397739. Avoid doing an XMLRPC lookup if a user
173
        if _lp_login is not None:
5609.24.9 by John Arbash Meinel
A bunch more tests and bug fixes for the local resolution.
174
            result = self._resolve_locally(path, url, _request_factory)
175
            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.
176
                local_res = result
177
                result = self._resolve_via_xmlrpc(path, url, _request_factory)
6150.3.4 by Jonathan Riddell
more launchpad plugin gettext()ing
178
                trace.note(gettext(
179
                    'resolution for {0}\n  local: {1}\n remote: {2}').format(
6150.3.11 by Jonathan Riddell
syntax fixes
180
                           url, local_res['urls'], result['urls']))
5609.24.7 by John Arbash Meinel
Fix bug #397739. Avoid doing an XMLRPC lookup if a user
181
        else:
182
            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
183
2898.4.14 by James Henstridge
* Use urlsplit() to process URLs.
184
        if 'launchpad' in debug.debug_flags:
4505.6.2 by Jonathan Lange
Extract a method that gets a service from a URL.
185
            trace.mutter("resolve_lp_path(%r) == %r", url, result)
2898.4.14 by James Henstridge
* Use urlsplit() to process URLs.
186
3270.4.1 by James Westby
Warn the user when resolving lp: URLs if they haven't set their login.
187
        _warned_login = False
2898.4.8 by James Henstridge
Switch lp: over to a pass-through transport, so that the XMLRPC gets
188
        for url in result['urls']:
189
            scheme, netloc, path, query, fragment = urlsplit(url)
3031.2.4 by jml at canonical
Only split the URL once.
190
            if self._requires_launchpad_login(scheme, netloc, path, query,
191
                                              fragment):
2898.4.8 by James Henstridge
Switch lp: over to a pass-through transport, so that the XMLRPC gets
192
                # Only accept launchpad.net bzr+ssh URLs if we know
193
                # the user's Launchpad login:
3777.1.21 by Aaron Bentley
Stop including usernames in resolved lp: urls
194
                if _lp_login is not None:
195
                    break
2898.4.9 by James Henstridge
Add some more tests for the bzr+ssh://bazaar.launchpad.net URL
196
                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.
197
                    if not _warned_login:
3834.1.2 by Martin Pool
Better message when launchpad-login is needed
198
                        trace.warning(
3834.1.3 by Martin Pool
Shorter message about launchpad-login
199
'You have not informed bzr of your Launchpad ID, and you must do this to\n'
200
'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.
201
                        _warned_login = True
2898.4.15 by James Henstridge
Use get_transport() to decide whether Bazaar supports a given URL.
202
            else:
203
                # Use the URL if we can create a transport for it.
204
                try:
5609.9.1 by Martin
Blindly change all users of get_transport to address the function via the transport module
205
                    transport.get_transport(url)
2898.4.15 by James Henstridge
Use get_transport() to decide whether Bazaar supports a given URL.
206
                except (errors.PathError, errors.TransportError):
207
                    pass
208
                else:
209
                    break
2898.4.8 by James Henstridge
Switch lp: over to a pass-through transport, so that the XMLRPC gets
210
        else:
6729.6.1 by Jelmer Vernooij
Move urlutils errors.
211
            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
212
        return url
213
2245.8.3 by Martin Pool
Start adding indirection transport
214
215
def get_test_permutations():
216
    # Since this transport doesn't do anything once opened, it's not subjected
217
    # to the usual transport tests.
218
    return []