~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: John Arbash Meinel
  • Date: 2006-10-16 01:25:46 UTC
  • mfrom: (2071 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2080.
  • Revision ID: john@arbash-meinel.com-20061016012546-d01a0740671b4d73
[merge] bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007 Canonical Ltd
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
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
 
 
17
 
 
18
 
"""Transport indirection that uses Launchpad as a directory lookup.
19
 
 
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
22
 
again.
23
 
"""
24
 
 
25
 
from urlparse import urlsplit, urlunsplit
26
 
import xmlrpclib
27
 
 
28
 
from bzrlib import (
29
 
    debug,
30
 
    errors,
31
 
    trace,
32
 
    urlutils,
33
 
    )
34
 
from bzrlib.transport import (
35
 
    get_transport,
36
 
    register_urlparse_netloc_protocol,
37
 
    Transport,
38
 
    )
39
 
 
40
 
from bzrlib.plugins.launchpad.lp_registration import (
41
 
    LaunchpadService, ResolveLaunchpadPathRequest)
42
 
from bzrlib.plugins.launchpad.account import get_lp_login
43
 
 
44
 
 
45
 
# As bzrlib.transport.remote may not be loaded yet, make sure bzr+ssh
46
 
# is counted as a netloc protocol.
47
 
register_urlparse_netloc_protocol('bzr+ssh')
48
 
register_urlparse_netloc_protocol('lp')
49
 
 
50
 
 
51
 
class LaunchpadTransport(Transport):
52
 
    """lp:/// URL transport
53
 
 
54
 
    This transport redirects requests to the real branch location
55
 
    after resolving the URL via an XMLRPC request to Launchpad.
56
 
    """
57
 
 
58
 
    def __init__(self, base):
59
 
        super(LaunchpadTransport, self).__init__(base)
60
 
        # We only support URLs without a netloc
61
 
        netloc = urlsplit(base)[1]
62
 
        if netloc != '':
63
 
            raise errors.InvalidURL(path=base)
64
 
 
65
 
    def _requires_launchpad_login(self, scheme, netloc, path, query,
66
 
                                  fragment):
67
 
        """Does the URL require a Launchpad login in order to be reached?
68
 
 
69
 
        The URL is specified by its parsed components, as returned from
70
 
        urlsplit.
71
 
        """
72
 
        return (scheme in ('bzr+ssh', 'sftp')
73
 
                and (netloc.endswith('launchpad.net')
74
 
                     or netloc.endswith('launchpad.dev')))
75
 
 
76
 
    def _resolve(self, abspath,
77
 
                 _request_factory=ResolveLaunchpadPathRequest,
78
 
                 _lp_login=None):
79
 
        """Resolve the base URL for this transport."""
80
 
        path = urlsplit(abspath)[2].lstrip('/')
81
 
        # Perform an XMLRPC request to resolve the path
82
 
        resolve = _request_factory(path)
83
 
        service = LaunchpadService()
84
 
        try:
85
 
            result = resolve.submit(service)
86
 
        except xmlrpclib.Fault, fault:
87
 
            raise errors.InvalidURL(
88
 
                path=abspath, extra=fault.faultString)
89
 
 
90
 
        if 'launchpad' in debug.debug_flags:
91
 
            trace.mutter("resolve_lp_path(%r) == %r", path, result)
92
 
 
93
 
        if _lp_login is None:
94
 
            _lp_login = get_lp_login()
95
 
        for url in result['urls']:
96
 
            scheme, netloc, path, query, fragment = urlsplit(url)
97
 
            if self._requires_launchpad_login(scheme, netloc, path, query,
98
 
                                              fragment):
99
 
                # Only accept launchpad.net bzr+ssh URLs if we know
100
 
                # the user's Launchpad login:
101
 
                if _lp_login is None:
102
 
                    continue
103
 
                url = urlunsplit((scheme, '%s@%s' % (_lp_login, netloc),
104
 
                                  path, query, fragment))
105
 
                break
106
 
            else:
107
 
                # Use the URL if we can create a transport for it.
108
 
                try:
109
 
                    get_transport(url)
110
 
                except (errors.PathError, errors.TransportError):
111
 
                    pass
112
 
                else:
113
 
                    break
114
 
        else:
115
 
            raise errors.InvalidURL(path=abspath,
116
 
                                    extra='no supported schemes')
117
 
        return url
118
 
 
119
 
    def _request_redirect(self, relpath):
120
 
        source = urlutils.join(self.base, relpath)
121
 
        # Split the source location into the branch location, and the
122
 
        # extra path components.
123
 
        pos = source.find('/.bzr/')
124
 
        if pos >= 0:
125
 
            branchpath = source[:pos]
126
 
            extra = source[pos:]
127
 
        else:
128
 
            branchpath = source
129
 
            extra = ''
130
 
        target = self._resolve(branchpath) + extra
131
 
        raise errors.RedirectRequested(
132
 
            source=source,
133
 
            target=target)
134
 
 
135
 
    def get(self, relpath):
136
 
        """See Transport.get()."""
137
 
        self._request_redirect(relpath)
138
 
 
139
 
    def mkdir(self, relpath, mode=None):
140
 
        """See Transport.mkdir()."""
141
 
        self._request_redirect(relpath)
142
 
 
143
 
 
144
 
def get_test_permutations():
145
 
    # Since this transport doesn't do anything once opened, it's not subjected
146
 
    # to the usual transport tests.
147
 
    return []