/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/transport/http/__init__.py

  • Committer: Robert Collins
  • Date: 2007-07-25 00:52:21 UTC
  • mfrom: (2650 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2651.
  • Revision ID: robertc@robertcollins.net-20070725005221-0ysm6il5mqnme3wz
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
import urllib
27
27
import sys
28
28
 
29
 
from bzrlib import errors, ui
 
29
from bzrlib import (
 
30
    errors,
 
31
    ui,
 
32
    urlutils,
 
33
    )
30
34
from bzrlib.smart import medium
31
35
from bzrlib.symbol_versioning import (
32
36
        deprecated_method,
34
38
        )
35
39
from bzrlib.trace import mutter
36
40
from bzrlib.transport import (
 
41
    ConnectedTransport,
37
42
    _CoalescedOffset,
38
43
    Transport,
39
44
    )
40
45
 
41
 
 
42
46
# TODO: This is not used anymore by HttpTransport_urllib
43
47
# (extracting the auth info and prompting the user for a password
44
48
# have been split), only the tests still use it. It should be
117
121
    return m
118
122
 
119
123
 
120
 
class HttpTransportBase(Transport, medium.SmartClientMedium):
 
124
class HttpTransportBase(ConnectedTransport, medium.SmartClientMedium):
121
125
    """Base class for http implementations.
122
126
 
123
127
    Does URL parsing, etc, but not any network IO.
126
130
    implementation.
127
131
    """
128
132
 
129
 
    # _proto: "http" or "https"
130
 
    # _qualified_proto: may have "+pycurl", etc
 
133
    # _unqualified_scheme: "http" or "https"
 
134
    # _scheme: may have "+pycurl", etc
131
135
 
132
 
    def __init__(self, base, from_transport=None):
 
136
    def __init__(self, base, _from_transport=None):
133
137
        """Set the base path where files will be stored."""
134
138
        proto_match = re.match(r'^(https?)(\+\w+)?://', base)
135
139
        if not proto_match:
136
140
            raise AssertionError("not a http url: %r" % base)
137
 
        self._proto = proto_match.group(1)
 
141
        self._unqualified_scheme = proto_match.group(1)
138
142
        impl_name = proto_match.group(2)
139
143
        if impl_name:
140
144
            impl_name = impl_name[1:]
141
145
        self._impl_name = impl_name
142
 
        if base[-1] != '/':
143
 
            base = base + '/'
144
 
        super(HttpTransportBase, self).__init__(base)
145
 
        (apparent_proto, self._host,
146
 
            self._path, self._parameters,
147
 
            self._query, self._fragment) = urlparse.urlparse(self.base)
148
 
        self._qualified_proto = apparent_proto
 
146
        super(HttpTransportBase, self).__init__(base,
 
147
                                                _from_transport=_from_transport)
149
148
        # range hint is handled dynamically throughout the life
150
149
        # of the transport object. We start by trying multi-range
151
150
        # requests and if the server returns bogus results, we
153
152
        # forget about range if the server really can't
154
153
        # understand. Once acquired, this piece of info is
155
154
        # propagated to clones.
156
 
        if from_transport is not None:
157
 
            self._range_hint = from_transport._range_hint
 
155
        if _from_transport is not None:
 
156
            self._range_hint = _from_transport._range_hint
158
157
        else:
159
158
            self._range_hint = 'multi'
160
159
 
161
 
    def abspath(self, relpath):
162
 
        """Return the full url to the given relative path.
163
 
 
164
 
        This can be supplied with a string or a list.
165
 
 
166
 
        The URL returned always has the protocol scheme originally used to 
167
 
        construct the transport, even if that includes an explicit
168
 
        implementation qualifier.
169
 
        """
170
 
        assert isinstance(relpath, basestring)
171
 
        if isinstance(relpath, unicode):
172
 
            raise errors.InvalidURL(relpath, 'paths must not be unicode.')
173
 
        if isinstance(relpath, basestring):
174
 
            relpath_parts = relpath.split('/')
175
 
        else:
176
 
            # TODO: Don't call this with an array - no magic interfaces
177
 
            relpath_parts = relpath[:]
178
 
        if relpath.startswith('/'):
179
 
            basepath = []
180
 
        else:
181
 
            # Except for the root, no trailing slashes are allowed
182
 
            if len(relpath_parts) > 1 and relpath_parts[-1] == '':
183
 
                raise ValueError(
184
 
                    "path %r within branch %r seems to be a directory"
185
 
                    % (relpath, self._path))
186
 
            basepath = self._path.split('/')
187
 
            if len(basepath) > 0 and basepath[-1] == '':
188
 
                basepath = basepath[:-1]
189
 
 
190
 
        for p in relpath_parts:
191
 
            if p == '..':
192
 
                if len(basepath) == 0:
193
 
                    # In most filesystems, a request for the parent
194
 
                    # of root, just returns root.
195
 
                    continue
196
 
                basepath.pop()
197
 
            elif p == '.' or p == '':
198
 
                continue # No-op
199
 
            else:
200
 
                basepath.append(p)
201
 
        # Possibly, we could use urlparse.urljoin() here, but
202
 
        # I'm concerned about when it chooses to strip the last
203
 
        # portion of the path, and when it doesn't.
204
 
        path = '/'.join(basepath)
205
 
        if path == '':
206
 
            path = '/'
207
 
        result = urlparse.urlunparse((self._qualified_proto,
208
 
                                    self._host, path, '', '', ''))
209
 
        return result
210
 
 
211
 
    def _real_abspath(self, relpath):
212
 
        """Produce absolute path, adjusting protocol if needed"""
213
 
        abspath = self.abspath(relpath)
214
 
        qp = self._qualified_proto
215
 
        rp = self._proto
216
 
        if self._qualified_proto != self._proto:
217
 
            abspath = rp + abspath[len(qp):]
218
 
        if not isinstance(abspath, str):
219
 
            # escaping must be done at a higher level
220
 
            abspath = abspath.encode('ascii')
221
 
        return abspath
 
160
    def _remote_path(self, relpath):
 
161
        """Produce absolute path, adjusting protocol."""
 
162
        relative = urlutils.unescape(relpath).encode('utf-8')
 
163
        path = self._combine_paths(self._path, relative)
 
164
        return self._unsplit_url(self._unqualified_scheme,
 
165
                                 self._user, self._password,
 
166
                                 self._host, self._port,
 
167
                                 path)
222
168
 
223
169
    def has(self, relpath):
224
170
        raise NotImplementedError("has() is abstract on %r" % self)
439
385
        """Delete the item at relpath"""
440
386
        raise errors.TransportNotPossible('http does not support delete()')
441
387
 
 
388
    def external_url(self):
 
389
        """See bzrlib.transport.Transport.external_url."""
 
390
        # HTTP URL's are externally usable.
 
391
        return self.base
 
392
 
442
393
    def is_readonly(self):
443
394
        """See Transport.is_readonly."""
444
395
        return True