~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/plugins/launchpad/lp_directory.py

  • Committer: Vincent Ladeuil
  • Date: 2017-01-17 13:48:10 UTC
  • mfrom: (6615.3.6 merges)
  • mto: This revision was merged to the branch mainline in revision 6620.
  • Revision ID: v.ladeuil+lp@free.fr-20170117134810-j9p3lidfy6pfyfsc
Merge 2.7, resolving conflicts

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007-2010 Canonical Ltd
 
1
# Copyright (C) 2007-2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
 
18
17
"""Directory lookup that uses Launchpad."""
19
18
 
 
19
from __future__ import absolute_import
 
20
 
20
21
from urlparse import urlsplit
21
22
import xmlrpclib
22
23
 
24
25
    debug,
25
26
    errors,
26
27
    trace,
27
 
    )
28
 
from bzrlib.transport import (
29
 
    get_transport,
30
 
    register_urlparse_netloc_protocol,
31
 
    )
 
28
    transport,
 
29
    )
 
30
from bzrlib.i18n import gettext
32
31
 
33
32
from bzrlib.plugins.launchpad.lp_registration import (
34
33
    LaunchpadService, ResolveLaunchpadPathRequest)
37
36
 
38
37
# As bzrlib.transport.remote may not be loaded yet, make sure bzr+ssh
39
38
# is counted as a netloc protocol.
40
 
register_urlparse_netloc_protocol('bzr+ssh')
41
 
register_urlparse_netloc_protocol('lp')
 
39
transport.register_urlparse_netloc_protocol('bzr+ssh')
 
40
transport.register_urlparse_netloc_protocol('lp')
 
41
 
 
42
_ubuntu_series_shortcuts = {
 
43
    'n': 'natty',
 
44
    'm': 'maverick',
 
45
    'l': 'lucid',
 
46
    'k': 'karmic',
 
47
    'j': 'jaunty',
 
48
    'h': 'hardy',
 
49
    'd': 'dapper',
 
50
    }
42
51
 
43
52
 
44
53
class LaunchpadDirectory(object):
58
67
        """See DirectoryService.look_up"""
59
68
        return self._resolve(url)
60
69
 
61
 
    def _resolve(self, url,
62
 
                 _request_factory=ResolveLaunchpadPathRequest,
63
 
                 _lp_login=None):
64
 
        """Resolve the base URL for this transport."""
 
70
    def _resolve_locally(self, path, url, _request_factory):
 
71
        # This is the best I could work out about XMLRPC. If an lp: url
 
72
        # includes ~user, then it is specially validated. Otherwise, it is just
 
73
        # sent to +branch/$path.
 
74
        _, netloc, _, _, _ = urlsplit(url)
 
75
        if netloc == '':
 
76
            netloc = LaunchpadService.DEFAULT_INSTANCE
 
77
        base_url = LaunchpadService.LAUNCHPAD_DOMAINS[netloc]
 
78
        base = 'bzr+ssh://bazaar.%s/' % (base_url,)
 
79
        maybe_invalid = False
 
80
        if path.startswith('~'):
 
81
            # A ~user style path, validate it a bit.
 
82
            # If a path looks fishy, fall back to asking XMLRPC to
 
83
            # resolve it for us. That way we still get their nicer error
 
84
            # messages.
 
85
            parts = path.split('/')
 
86
            if (len(parts) < 3
 
87
                or (parts[1] in ('ubuntu', 'debian') and len(parts) < 5)):
 
88
                # This special case requires 5-parts to be valid.
 
89
                maybe_invalid = True
 
90
        else:
 
91
            base += '+branch/'
 
92
        if maybe_invalid:
 
93
            return self._resolve_via_xmlrpc(path, url, _request_factory)
 
94
        return {'urls': [base + path]}
 
95
 
 
96
    def _resolve_via_xmlrpc(self, path, url, _request_factory):
65
97
        service = LaunchpadService.for_url(url)
66
 
        result = urlsplit(url)
67
 
        if _lp_login is None:
68
 
            _lp_login = get_lp_login()
69
 
        path = result[2].strip('/')
70
 
        if path.startswith('~/'):
71
 
            if _lp_login is None:
72
 
                raise errors.InvalidURL(path=url,
73
 
                    extra='Cannot resolve "~" to your username.'
74
 
                          ' See "bzr help launchpad-login"')
75
 
            path = '~' + _lp_login + path[1:]
76
98
        resolve = _request_factory(path)
77
99
        try:
78
100
            result = resolve.submit(service)
79
101
        except xmlrpclib.Fault, fault:
80
102
            raise errors.InvalidURL(
81
103
                path=url, extra=fault.faultString)
 
104
        return result
 
105
 
 
106
    def _update_url_scheme(self, url):
 
107
        # Do ubuntu: and debianlp: expansions.
 
108
        scheme, netloc, path, query, fragment = urlsplit(url)
 
109
        if scheme in ('ubuntu', 'debianlp'):
 
110
            if scheme == 'ubuntu':
 
111
                distro = 'ubuntu'
 
112
                distro_series = _ubuntu_series_shortcuts
 
113
            elif scheme == 'debianlp':
 
114
                distro = 'debian'
 
115
                # No shortcuts for Debian distroseries.
 
116
                distro_series = {}
 
117
            else:
 
118
                raise AssertionError('scheme should be ubuntu: or debianlp:')
 
119
            # Split the path.  It's either going to be 'project' or
 
120
            # 'series/project', but recognize that it may be a series we don't
 
121
            # know about.
 
122
            path_parts = path.split('/')
 
123
            if len(path_parts) == 1:
 
124
                # It's just a project name.
 
125
                lp_url_template = 'lp:%(distro)s/%(project)s'
 
126
                project = path_parts[0]
 
127
                series = None
 
128
            elif len(path_parts) == 2:
 
129
                # It's a series and project.
 
130
                lp_url_template = 'lp:%(distro)s/%(series)s/%(project)s'
 
131
                series, project = path_parts
 
132
            else:
 
133
                # There are either 0 or > 2 path parts, neither of which is
 
134
                # supported for these schemes.
 
135
                raise errors.InvalidURL('Bad path: %s' % url)
 
136
            # Expand any series shortcuts, but keep unknown series.
 
137
            series = distro_series.get(series, series)
 
138
            # Hack the url and let the following do the final resolution.
 
139
            url = lp_url_template % dict(
 
140
                distro=distro,
 
141
                series=series,
 
142
                project=project)
 
143
            scheme, netloc, path, query, fragment = urlsplit(url)
 
144
        return url, path
 
145
 
 
146
    def _expand_user(self, path, url, lp_login):
 
147
        if path.startswith('~/'):
 
148
            if lp_login is None:
 
149
                raise errors.InvalidURL(path=url,
 
150
                    extra='Cannot resolve "~" to your username.'
 
151
                          ' See "bzr help launchpad-login"')
 
152
            path = '~' + lp_login + path[1:]
 
153
        return path
 
154
 
 
155
    def _resolve(self, url,
 
156
                 _request_factory=ResolveLaunchpadPathRequest,
 
157
                 _lp_login=None):
 
158
        """Resolve the base URL for this transport."""
 
159
        url, path = self._update_url_scheme(url)
 
160
        if _lp_login is None:
 
161
            _lp_login = get_lp_login()
 
162
        path = path.strip('/')
 
163
        path = self._expand_user(path, url, _lp_login)
 
164
        if _lp_login is not None:
 
165
            result = self._resolve_locally(path, url, _request_factory)
 
166
            if 'launchpad' in debug.debug_flags:
 
167
                local_res = result
 
168
                result = self._resolve_via_xmlrpc(path, url, _request_factory)
 
169
                trace.note(gettext(
 
170
                    'resolution for {0}\n  local: {1}\n remote: {2}').format(
 
171
                           url, local_res['urls'], result['urls']))
 
172
        else:
 
173
            result = self._resolve_via_xmlrpc(path, url, _request_factory)
82
174
 
83
175
        if 'launchpad' in debug.debug_flags:
84
176
            trace.mutter("resolve_lp_path(%r) == %r", url, result)
101
193
            else:
102
194
                # Use the URL if we can create a transport for it.
103
195
                try:
104
 
                    get_transport(url)
 
196
                    transport.get_transport(url)
105
197
                except (errors.PathError, errors.TransportError):
106
198
                    pass
107
199
                else: