/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2245.8.2 by Martin Pool
doc
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.11.19 by John Arbash Meinel
Testing put and append, also testing agaist file-like objects as well as strings.
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1185.11.19 by John Arbash Meinel
Testing put and append, also testing agaist file-like objects as well as strings.
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.11.19 by John Arbash Meinel
Testing put and append, also testing agaist file-like objects as well as strings.
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
1540.3.1 by Martin Pool
First-cut implementation of pycurl. Substantially faster than using urllib.
16
1185.11.19 by John Arbash Meinel
Testing put and append, also testing agaist file-like objects as well as strings.
17
"""Transport is an abstraction layer to handle file access.
18
19
The abstraction is to allow access from the local filesystem, as well
20
as remote (such as http or sftp).
1540.3.12 by Martin Pool
Multiple transports can be registered for any protocol, and they are
21
22
Transports are constructed from a string, being a URL or (as a degenerate
23
case) a local filesystem path.  This is typically the top directory of
24
a bzrdir, repository, or similar object we are interested in working with.
25
The Transport returned has methods to read, write and manipulate files within
26
it.
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
27
"""
28
1996.3.6 by John Arbash Meinel
Find a few places that weren't importing their dependencies.
29
from cStringIO import StringIO
30
import re
31
import sys
32
33
from bzrlib.lazy_import import lazy_import
34
lazy_import(globals(), """
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
35
import errno
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
36
from stat import S_ISDIR
1685.1.70 by Wouter van Heyst
working on get_parent, set_parent and relative urls, broken
37
import urllib
1636.1.1 by Robert Collins
Fix calling relpath() and abspath() on transports at their root.
38
import urlparse
1530.1.1 by Robert Collins
Minimal infrastructure to test TransportTestProviderAdapter.
39
1955.3.6 by John Arbash Meinel
Lots of deprecation warnings, but no errors
40
from bzrlib import (
41
    errors,
42
    osutils,
43
    symbol_versioning,
44
    urlutils,
45
    )
1996.3.6 by John Arbash Meinel
Find a few places that weren't importing their dependencies.
46
""")
47
1955.3.6 by John Arbash Meinel
Lots of deprecation warnings, but no errors
48
from bzrlib.symbol_versioning import (
49
        deprecated_method,
50
        deprecated_function,
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
51
        DEPRECATED_PARAMETER,
3241.1.6 by Andrew Bennetts
Deprecate Transport.get_smart_client and errors.NoSmartServer, as these are now unused.
52
        one_four,
2687.2.1 by Martin Pool
Rename upcoming release from 0.19 to 0.90
53
        zero_ninety,
1955.3.6 by John Arbash Meinel
Lots of deprecation warnings, but no errors
54
        )
2164.2.21 by Vincent Ladeuil
Take bundles into account.
55
from bzrlib.trace import (
56
    mutter,
57
    )
2241.2.1 by ghigo
Add the TransportRegistry class
58
from bzrlib import registry
2018.5.104 by Andrew Bennetts
Completely rework chrooted transports.
59
60
2671.3.2 by Robert Collins
Start open_file_stream logic.
61
# a dictionary of open file streams. Keys are absolute paths, values are
62
# transport defined.
63
_file_streams = {}
64
65
1530.1.11 by Robert Collins
Push the transport permutations list into each transport module allowing for automatic testing of new modules that are registered as transports.
66
def _get_protocol_handlers():
1540.3.12 by Martin Pool
Multiple transports can be registered for any protocol, and they are
67
    """Return a dictionary of {urlprefix: [factory]}"""
2241.2.3 by ghigo
removed the the registration of the 'None' transport, instead we use the set_default_transport function
68
    return transport_list_registry
1530.1.11 by Robert Collins
Push the transport permutations list into each transport module allowing for automatic testing of new modules that are registered as transports.
69
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
70
1530.1.11 by Robert Collins
Push the transport permutations list into each transport module allowing for automatic testing of new modules that are registered as transports.
71
def _set_protocol_handlers(new_handlers):
72
    """Replace the current protocol handlers dictionary.
73
74
    WARNING this will remove all build in protocols. Use with care.
75
    """
2241.2.3 by ghigo
removed the the registration of the 'None' transport, instead we use the set_default_transport function
76
    global transport_list_registry
77
    transport_list_registry = new_handlers
1530.1.11 by Robert Collins
Push the transport permutations list into each transport module allowing for automatic testing of new modules that are registered as transports.
78
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
79
1540.3.12 by Martin Pool
Multiple transports can be registered for any protocol, and they are
80
def _clear_protocol_handlers():
2241.2.3 by ghigo
removed the the registration of the 'None' transport, instead we use the set_default_transport function
81
    global transport_list_registry
82
    transport_list_registry = TransportListRegistry()
1540.3.12 by Martin Pool
Multiple transports can be registered for any protocol, and they are
83
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
84
1530.1.11 by Robert Collins
Push the transport permutations list into each transport module allowing for automatic testing of new modules that are registered as transports.
85
def _get_transport_modules():
86
    """Return a list of the modules providing transports."""
87
    modules = set()
2241.2.3 by ghigo
removed the the registration of the 'None' transport, instead we use the set_default_transport function
88
    for prefix, factory_list in transport_list_registry.iteritems():
1540.3.12 by Martin Pool
Multiple transports can be registered for any protocol, and they are
89
        for factory in factory_list:
2241.2.2 by ghigo
Create the TransportList class
90
            if hasattr(factory, "_module_name"):
91
                modules.add(factory._module_name)
1540.3.12 by Martin Pool
Multiple transports can be registered for any protocol, and they are
92
            else:
2241.2.2 by ghigo
Create the TransportList class
93
                modules.add(factory._obj.__module__)
2745.5.3 by Robert Collins
* Move transport logging into a new transport class
94
    # Add chroot directly, because there is no handler registered for it.
2018.5.104 by Andrew Bennetts
Completely rework chrooted transports.
95
    modules.add('bzrlib.transport.chroot')
1530.1.19 by Robert Collins
Make transport test adapter tests reliable.
96
    result = list(modules)
97
    result.sort()
98
    return result
1530.1.11 by Robert Collins
Push the transport permutations list into each transport module allowing for automatic testing of new modules that are registered as transports.
99
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
100
2241.2.3 by ghigo
removed the the registration of the 'None' transport, instead we use the set_default_transport function
101
class TransportListRegistry(registry.Registry):
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
102
    """A registry which simplifies tracking available Transports.
103
104
    A registration of a new protocol requires two step:
105
    1) register the prefix with the function register_transport( )
106
    2) register the protocol provider with the function
107
    register_transport_provider( ) ( and the "lazy" variant )
108
2485.8.38 by Vincent Ladeuil
Finish sftp refactoring. Test suite passing.
109
    This is needed because:
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
110
    a) a single provider can support multple protcol ( like the ftp
2485.8.38 by Vincent Ladeuil
Finish sftp refactoring. Test suite passing.
111
    provider which supports both the ftp:// and the aftp:// protocols )
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
112
    b) a single protocol can have multiple providers ( like the http://
2485.8.38 by Vincent Ladeuil
Finish sftp refactoring. Test suite passing.
113
    protocol which is supported by both the urllib and pycurl provider )
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
114
    """
115
2241.2.3 by ghigo
removed the the registration of the 'None' transport, instead we use the set_default_transport function
116
    def register_transport_provider(self, key, obj):
117
        self.get(key).insert(0, registry._ObjectGetter(obj))
118
119
    def register_lazy_transport_provider(self, key, module_name, member_name):
2745.5.3 by Robert Collins
* Move transport logging into a new transport class
120
        self.get(key).insert(0,
2241.2.1 by ghigo
Add the TransportRegistry class
121
                registry._LazyObjectGetter(module_name, member_name))
122
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
123
    def register_transport(self, key, help=None):
124
        self.register(key, [], help)
2241.2.1 by ghigo
Add the TransportRegistry class
125
126
    def set_default_transport(self, key=None):
127
        """Return either 'key' or the default key if key is None"""
128
        self._default_key = key
129
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
130
2745.5.3 by Robert Collins
* Move transport logging into a new transport class
131
transport_list_registry = TransportListRegistry()
2241.2.1 by ghigo
Add the TransportRegistry class
132
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
133
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
134
def register_transport_proto(prefix, help=None, info=None,
2919.2.1 by John Arbash Meinel
Register netloc protocols as soon as the protocol is registered.
135
                             register_netloc=False):
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
136
    transport_list_registry.register_transport(prefix, help)
2919.2.1 by John Arbash Meinel
Register netloc protocols as soon as the protocol is registered.
137
    if register_netloc:
138
        assert prefix.endswith('://')
139
        register_urlparse_netloc_protocol(prefix[:-3])
2241.2.1 by ghigo
Add the TransportRegistry class
140
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
141
2241.2.1 by ghigo
Add the TransportRegistry class
142
def register_lazy_transport(prefix, module, classname):
2241.2.3 by ghigo
removed the the registration of the 'None' transport, instead we use the set_default_transport function
143
    if not prefix in transport_list_registry:
2241.2.2 by ghigo
Create the TransportList class
144
        register_transport_proto(prefix)
2241.2.3 by ghigo
removed the the registration of the 'None' transport, instead we use the set_default_transport function
145
    transport_list_registry.register_lazy_transport_provider(prefix, module, classname)
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
146
147
2241.2.1 by ghigo
Add the TransportRegistry class
148
def register_transport(prefix, klass, override=DEPRECATED_PARAMETER):
2241.2.3 by ghigo
removed the the registration of the 'None' transport, instead we use the set_default_transport function
149
    if not prefix in transport_list_registry:
2241.2.2 by ghigo
Create the TransportList class
150
        register_transport_proto(prefix)
2241.2.3 by ghigo
removed the the registration of the 'None' transport, instead we use the set_default_transport function
151
    transport_list_registry.register_transport_provider(prefix, klass)
2241.2.1 by ghigo
Add the TransportRegistry class
152
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
153
1636.1.2 by Robert Collins
More review fixen to the relpath at '/' fixes.
154
def register_urlparse_netloc_protocol(protocol):
1636.1.1 by Robert Collins
Fix calling relpath() and abspath() on transports at their root.
155
    """Ensure that protocol is setup to be used with urlparse netloc parsing."""
156
    if protocol not in urlparse.uses_netloc:
157
        urlparse.uses_netloc.append(protocol)
158
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
159
2485.8.61 by Vincent Ladeuil
From review comments, use a private scheme for testing.
160
def _unregister_urlparse_netloc_protocol(protocol):
161
    """Remove protocol from urlparse netloc parsing.
162
163
    Except for tests, you should never use that function. Using it with 'http',
164
    for example, will break all http transports.
165
    """
166
    if protocol in urlparse.uses_netloc:
167
        urlparse.uses_netloc.remove(protocol)
168
169
2241.3.5 by ghigo
update to the latest bzr.dev
170
def unregister_transport(scheme, factory):
171
    """Unregister a transport."""
172
    l = transport_list_registry.get(scheme)
173
    for i in l:
174
        o = i.get_obj( )
175
        if o == factory:
176
            transport_list_registry.get(scheme).remove(i)
177
            break
178
    if len(l) == 0:
179
        transport_list_registry.remove(scheme)
180
181
182
2687.2.1 by Martin Pool
Rename upcoming release from 0.19 to 0.90
183
@deprecated_function(zero_ninety)
1707.3.4 by John Arbash Meinel
Moved most of sftp.split_url into a Transport function.
184
def split_url(url):
1685.1.69 by Wouter van Heyst
merge bzr.dev 1740
185
    # TODO: jam 20060606 urls should only be ascii, or they should raise InvalidURL
1707.3.4 by John Arbash Meinel
Moved most of sftp.split_url into a Transport function.
186
    if isinstance(url, unicode):
187
        url = url.encode('utf-8')
188
    (scheme, netloc, path, params,
189
     query, fragment) = urlparse.urlparse(url, allow_fragments=False)
190
    username = password = host = port = None
191
    if '@' in netloc:
192
        username, host = netloc.split('@', 1)
193
        if ':' in username:
194
            username, password = username.split(':', 1)
195
            password = urllib.unquote(password)
196
        username = urllib.unquote(username)
197
    else:
198
        host = netloc
199
200
    if ':' in host:
201
        host, port = host.rsplit(':', 1)
202
        try:
203
            port = int(port)
204
        except ValueError:
205
            # TODO: Should this be ConnectionError?
1910.15.8 by Andrew Bennetts
Put url in 'invalid port number' message on a new line.
206
            raise errors.TransportError(
207
                'invalid port number %s in url:\n%s' % (port, url))
1707.3.4 by John Arbash Meinel
Moved most of sftp.split_url into a Transport function.
208
    host = urllib.unquote(host)
209
210
    path = urllib.unquote(path)
211
212
    return (scheme, username, password, host, port, path)
213
214
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
215
class _CoalescedOffset(object):
216
    """A data container for keeping track of coalesced offsets."""
217
218
    __slots__ = ['start', 'length', 'ranges']
219
220
    def __init__(self, start, length, ranges):
221
        self.start = start
222
        self.length = length
223
        self.ranges = ranges
224
225
    def __cmp__(self, other):
226
        return cmp((self.start, self.length, self.ranges),
227
                   (other.start, other.length, other.ranges))
228
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
229
    def __repr__(self):
230
        return '%s(%r, %r, %r)' % (self.__class__.__name__,
231
            self.start, self.length, self.ranges)
232
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
233
2052.6.1 by Robert Collins
``Transport.get`` has had its interface made more clear for ease of use.
234
class LateReadError(object):
235
    """A helper for transports which pretends to be a readable file.
236
237
    When read() is called, errors.ReadError is raised.
238
    """
239
240
    def __init__(self, path):
241
        self._path = path
242
243
    def close(self):
244
        """a no-op - do nothing."""
245
2052.6.2 by Robert Collins
Merge bzr.dev.
246
    def _fail(self):
2052.6.1 by Robert Collins
``Transport.get`` has had its interface made more clear for ease of use.
247
        """Raise ReadError."""
248
        raise errors.ReadError(self._path)
249
2052.6.2 by Robert Collins
Merge bzr.dev.
250
    def __iter__(self):
251
        self._fail()
252
253
    def read(self, count=-1):
254
        self._fail()
255
256
    def readlines(self):
257
        self._fail()
258
2052.6.1 by Robert Collins
``Transport.get`` has had its interface made more clear for ease of use.
259
2671.3.6 by Robert Collins
Review feedback.
260
class FileStream(object):
261
    """Base class for FileStreams."""
262
263
    def __init__(self, transport, relpath):
264
        """Create a FileStream for relpath on transport."""
265
        self.transport = transport
266
        self.relpath = relpath
267
268
    def _close(self):
269
        """A hook point for subclasses that need to take action on close."""
270
271
    def close(self):
272
        self._close()
273
        del _file_streams[self.transport.abspath(self.relpath)]
274
275
276
class FileFileStream(FileStream):
2671.3.9 by Robert Collins
Review feedback and fix VFat emulated transports to not claim to have unix permissions.
277
    """A file stream object returned by open_write_stream.
2671.3.6 by Robert Collins
Review feedback.
278
    
279
    This version uses a file like object to perform writes.
280
    """
281
282
    def __init__(self, transport, relpath, file_handle):
283
        FileStream.__init__(self, transport, relpath)
284
        self.file_handle = file_handle
285
286
    def _close(self):
287
        self.file_handle.close()
288
289
    def write(self, bytes):
290
        self.file_handle.write(bytes)
291
292
293
class AppendBasedFileStream(FileStream):
2671.3.9 by Robert Collins
Review feedback and fix VFat emulated transports to not claim to have unix permissions.
294
    """A file stream object returned by open_write_stream.
2671.3.6 by Robert Collins
Review feedback.
295
    
296
    This version uses append on a transport to perform writes.
297
    """
298
299
    def write(self, bytes):
300
        self.transport.append_bytes(self.relpath, bytes)
301
302
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
303
class Transport(object):
304
    """This class encapsulates methods for retrieving or putting a file
305
    from/to a storage location.
306
307
    Most functions have a _multi variant, which allows you to queue up
308
    multiple requests. They generally have a dumb base implementation 
309
    which just iterates over the arguments, but smart Transport
310
    implementations can do pipelining.
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
311
    In general implementations should support having a generator or a list
312
    as an argument (ie always iterate, never index)
1910.7.17 by Andrew Bennetts
Various cosmetic changes.
313
314
    :ivar base: Base URL for the transport; should always end in a slash.
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
315
    """
316
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
317
    # implementations can override this if it is more efficient
318
    # for them to combine larger read chunks together
1864.5.4 by John Arbash Meinel
play around with tuning the partial reads.
319
    _max_readv_combine = 50
1864.5.3 by John Arbash Meinel
Allow collapsing ranges even if they are just 'close'
320
    # It is better to read this much more data in order, rather
321
    # than doing another seek. Even for the local filesystem,
322
    # there is a benefit in just reading.
323
    # TODO: jam 20060714 Do some real benchmarking to figure out
324
    #       where the biggest benefit between combining reads and
1864.5.8 by John Arbash Meinel
Cleanup and NEWS
325
    #       and seeking is. Consider a runtime auto-tune.
1864.5.4 by John Arbash Meinel
play around with tuning the partial reads.
326
    _bytes_to_read_before_seek = 0
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
327
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
328
    def __init__(self, base):
907.1.50 by John Arbash Meinel
Removed encode/decode from Transport.put/get, added more exceptions that can be thrown.
329
        super(Transport, self).__init__()
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
330
        self.base = base
331
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
332
    def _translate_error(self, e, path, raise_generic=True):
333
        """Translate an IOError or OSError into an appropriate bzr error.
334
335
        This handles things like ENOENT, ENOTDIR, EEXIST, and EACCESS
336
        """
1963.2.6 by Robey Pointer
pychecker is on crack; go back to using 'is None'.
337
        if getattr(e, 'errno', None) is not None:
3146.4.1 by Aaron Bentley
Python 2.5 on win32 can emit errno.EINVAL when listing a non-directory
338
            if e.errno in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL):
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
339
                raise errors.NoSuchFile(path, extra=e)
1185.31.58 by John Arbash Meinel
Updating for new transport tests so that they pass on win32
340
            # I would rather use errno.EFOO, but there doesn't seem to be
341
            # any matching for 267
342
            # This is the error when doing a listdir on a file:
343
            # WindowsError: [Errno 267] The directory name is invalid
344
            if sys.platform == 'win32' and e.errno in (errno.ESRCH, 267):
345
                raise errors.NoSuchFile(path, extra=e)
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
346
            if e.errno == errno.EEXIST:
347
                raise errors.FileExists(path, extra=e)
348
            if e.errno == errno.EACCES:
349
                raise errors.PermissionDenied(path, extra=e)
1553.5.10 by Martin Pool
New DirectoryNotEmpty exception, and raise this from local and memory
350
            if e.errno == errno.ENOTEMPTY:
351
                raise errors.DirectoryNotEmpty(path, extra=e)
1558.10.1 by Aaron Bentley
Handle lockdirs over NFS properly
352
            if e.errno == errno.EBUSY:
353
                raise errors.ResourceBusy(path, extra=e)
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
354
        if raise_generic:
355
            raise errors.TransportError(orig_error=e)
356
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
357
    def clone(self, offset=None):
358
        """Return a new Transport object, cloned from the current location,
1185.11.6 by John Arbash Meinel
Made HttpTransport handle a request for a parent directory differently.
359
        using a subdirectory or parent directory. This allows connections 
360
        to be pooled, rather than a new one needed for each subdir.
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
361
        """
1540.3.1 by Martin Pool
First-cut implementation of pycurl. Substantially faster than using urllib.
362
        raise NotImplementedError(self.clone)
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
363
2475.3.2 by John Arbash Meinel
Add Transport.ensure_base()
364
    def ensure_base(self):
365
        """Ensure that the directory this transport references exists.
366
367
        This will create a directory if it doesn't exist.
368
        :return: True if the directory was created, False otherwise.
369
        """
370
        # The default implementation just uses "Easier to ask for forgiveness
371
        # than permission". We attempt to create the directory, and just
2805.3.1 by Martin Pool
Transport.ensure_base should ignore PermissionDenied when trying to create the directory (Axel Kollmorgen)
372
        # suppress FileExists and PermissionDenied (for Windows) exceptions.
2475.3.2 by John Arbash Meinel
Add Transport.ensure_base()
373
        try:
374
            self.mkdir('.')
2805.3.1 by Martin Pool
Transport.ensure_base should ignore PermissionDenied when trying to create the directory (Axel Kollmorgen)
375
        except (errors.FileExists, errors.PermissionDenied):
2475.3.2 by John Arbash Meinel
Add Transport.ensure_base()
376
            return False
377
        else:
378
            return True
379
2634.1.1 by Robert Collins
(robertc) Reinstate the accidentally backed out external_url patch.
380
    def external_url(self):
381
        """Return a URL for self that can be given to an external process.
382
383
        There is no guarantee that the URL can be accessed from a different
384
        machine - e.g. file:/// urls are only usable on the local machine,
385
        sftp:/// urls when the server is only bound to localhost are only
386
        usable from localhost etc.
387
388
        NOTE: This method may remove security wrappers (e.g. on chroot
389
        transports) and thus should *only* be used when the result will not
390
        be used to obtain a new transport within bzrlib. Ideally chroot
391
        transports would know enough to cause the external url to be the exact
392
        one used that caused the chrooting in the first place, but that is not
393
        currently the case.
394
395
        :return: A URL that can be given to another process.
396
        :raises InProcessTransport: If the transport is one that cannot be
397
            accessed out of the current process (e.g. a MemoryTransport)
398
            then InProcessTransport is raised.
399
        """
400
        raise NotImplementedError(self.external_url)
401
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
402
    def _pump(self, from_file, to_file):
403
        """Most children will need to copy from one file-like 
404
        object or string to another one.
405
        This just gives them something easy to call.
406
        """
1955.3.11 by John Arbash Meinel
Clean up the rest of the api calls to deprecated functions in the test suite, and make sure Transport._pump is only accepting files, not strings
407
        assert not isinstance(from_file, basestring), \
408
            '_pump should only be called on files not %s' % (type(from_file,))
2745.5.2 by Robert Collins
* ``bzrlib.transport.Transport.put_file`` now returns the number of bytes
409
        return osutils.pumpfile(from_file, to_file)
1948.3.8 by Vincent LADEUIL
_pump accepts strings finally :)
410
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
411
    def _get_total(self, multi):
412
        """Try to figure out how many entries are in multi,
413
        but if not possible, return None.
414
        """
415
        try:
416
            return len(multi)
417
        except TypeError: # We can't tell how many, because relpaths is a generator
418
            return None
419
420
    def _update_pb(self, pb, msg, count, total):
421
        """Update the progress bar based on the current count
422
        and total available, total may be None if it was
423
        not possible to determine.
424
        """
907.1.14 by John Arbash Meinel
Handling some transport functions which take only a single argument.
425
        if pb is None:
426
            return
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
427
        if total is None:
428
            pb.update(msg, count, count+1)
429
        else:
430
            pb.update(msg, count, total)
431
907.1.14 by John Arbash Meinel
Handling some transport functions which take only a single argument.
432
    def _iterate_over(self, multi, func, pb, msg, expand=True):
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
433
        """Iterate over all entries in multi, passing them to func,
434
        and update the progress bar as you go along.
907.1.14 by John Arbash Meinel
Handling some transport functions which take only a single argument.
435
436
        :param expand:  If True, the entries will be passed to the function
437
                        by expanding the tuple. If False, it will be passed
438
                        as a single parameter.
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
439
        """
440
        total = self._get_total(multi)
1563.2.3 by Robert Collins
Change the return signature of transport.append and append_multi to return the length of the pre-append content.
441
        result = []
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
442
        count = 0
443
        for entry in multi:
444
            self._update_pb(pb, msg, count, total)
907.1.14 by John Arbash Meinel
Handling some transport functions which take only a single argument.
445
            if expand:
1563.2.3 by Robert Collins
Change the return signature of transport.append and append_multi to return the length of the pre-append content.
446
                result.append(func(*entry))
907.1.14 by John Arbash Meinel
Handling some transport functions which take only a single argument.
447
            else:
1563.2.3 by Robert Collins
Change the return signature of transport.append and append_multi to return the length of the pre-append content.
448
                result.append(func(entry))
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
449
            count += 1
1563.2.3 by Robert Collins
Change the return signature of transport.append and append_multi to return the length of the pre-append content.
450
        return tuple(result)
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
451
907.1.34 by John Arbash Meinel
Fixing append(), cleaning up function locations.
452
    def abspath(self, relpath):
453
        """Return the full url to the given relative path.
1910.16.6 by Andrew Bennetts
Update Transport.abspath docstring.
454
455
        :param relpath: a string of a relative path
1910.16.2 by Andrew Bennetts
Reduce transport code duplication by creating a '_combine_paths' method to Transport.
456
        """
1442.1.44 by Robert Collins
Many transport related tweaks:
457
1910.16.2 by Andrew Bennetts
Reduce transport code duplication by creating a '_combine_paths' method to Transport.
458
        # XXX: Robert Collins 20051016 - is this really needed in the public
459
        # interface ?
1540.3.1 by Martin Pool
First-cut implementation of pycurl. Substantially faster than using urllib.
460
        raise NotImplementedError(self.abspath)
907.1.34 by John Arbash Meinel
Fixing append(), cleaning up function locations.
461
1910.16.2 by Andrew Bennetts
Reduce transport code duplication by creating a '_combine_paths' method to Transport.
462
    def _combine_paths(self, base_path, relpath):
463
        """Transform a Transport-relative path to a remote absolute path.
464
465
        This does not handle substitution of ~ but does handle '..' and '.'
466
        components.
467
468
        Examples::
469
1996.3.20 by John Arbash Meinel
[merge] bzr.dev 2063
470
            t._combine_paths('/home/sarah', 'project/foo')
471
                => '/home/sarah/project/foo'
472
            t._combine_paths('/home/sarah', '../../etc')
473
                => '/etc'
2070.3.2 by Andrew Bennetts
Merge from bzr.dev
474
            t._combine_paths('/home/sarah', '/etc')
475
                => '/etc'
1910.16.2 by Andrew Bennetts
Reduce transport code duplication by creating a '_combine_paths' method to Transport.
476
477
        :param base_path: urlencoded path for the transport root; typically a 
478
             URL but need not contain scheme/host/etc.
479
        :param relpath: relative url string for relative part of remote path.
480
        :return: urlencoded string for final path.
481
        """
482
        if not isinstance(relpath, str):
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
483
            raise errors.InvalidURL(relpath)
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
484
        if relpath.startswith('/'):
485
            base_parts = []
486
        else:
487
            base_parts = base_path.split('/')
1910.16.2 by Andrew Bennetts
Reduce transport code duplication by creating a '_combine_paths' method to Transport.
488
        if len(base_parts) > 0 and base_parts[-1] == '':
489
            base_parts = base_parts[:-1]
490
        for p in relpath.split('/'):
491
            if p == '..':
492
                if len(base_parts) == 0:
493
                    # In most filesystems, a request for the parent
494
                    # of root, just returns root.
495
                    continue
496
                base_parts.pop()
497
            elif p == '.':
498
                continue # No-op
499
            elif p != '':
500
                base_parts.append(p)
501
        path = '/'.join(base_parts)
2070.3.1 by Andrew Bennetts
Fix memory_transport.abspath('/foo')
502
        if not path.startswith('/'):
503
            path = '/' + path
1910.16.2 by Andrew Bennetts
Reduce transport code duplication by creating a '_combine_paths' method to Transport.
504
        return path
505
2671.3.1 by Robert Collins
* New method ``bzrlib.transport.Transport.get_recommended_page_size``.
506
    def recommended_page_size(self):
507
        """Return the recommended page size for this transport.
508
509
        This is potentially different for every path in a given namespace.
510
        For example, local transports might use an operating system call to 
511
        get the block size for a given path, which can vary due to mount
512
        points.
513
514
        :return: The page size in bytes.
515
        """
516
        return 4 * 1024
517
907.1.34 by John Arbash Meinel
Fixing append(), cleaning up function locations.
518
    def relpath(self, abspath):
519
        """Return the local path portion from a given absolute path.
1442.1.44 by Robert Collins
Many transport related tweaks:
520
521
        This default implementation is not suitable for filesystems with
522
        aliasing, such as that given by symlinks, where a path may not 
523
        start with our base, but still be a relpath once aliasing is 
524
        resolved.
907.1.34 by John Arbash Meinel
Fixing append(), cleaning up function locations.
525
        """
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
526
        # TODO: This might want to use bzrlib.osutils.relpath
527
        #       but we have to watch out because of the prefix issues
1530.1.3 by Robert Collins
transport implementations now tested consistently.
528
        if not (abspath == self.base[:-1] or abspath.startswith(self.base)):
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
529
            raise errors.PathNotChild(abspath, self.base)
1442.1.44 by Robert Collins
Many transport related tweaks:
530
        pl = len(self.base)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
531
        return abspath[pl:].strip('/')
907.1.34 by John Arbash Meinel
Fixing append(), cleaning up function locations.
532
1685.1.9 by John Arbash Meinel
Updated LocalTransport so that it's base is now a URL rather than a local path. This helps consistency with all other functions. To do so, I added local_abspath() which returns the local path, and local_path_to/from_url
533
    def local_abspath(self, relpath):
534
        """Return the absolute path on the local filesystem.
535
536
        This function will only be defined for Transports which have a
537
        physical local filesystem representation.
538
        """
2018.18.4 by Martin Pool
Change Transport.local_abspath to raise NotLocalUrl, and test.
539
        raise errors.NotLocalUrl(self.abspath(relpath))
1685.1.9 by John Arbash Meinel
Updated LocalTransport so that it's base is now a URL rather than a local path. This helps consistency with all other functions. To do so, I added local_abspath() which returns the local path, and local_path_to/from_url
540
541
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
542
    def has(self, relpath):
1442.1.44 by Robert Collins
Many transport related tweaks:
543
        """Does the file relpath exist?
544
        
545
        Note that some transports MAY allow querying on directories, but this
1553.5.66 by Martin Pool
doc
546
        is not part of the protocol.  In other words, the results of 
1786.1.8 by John Arbash Meinel
[merge] Johan Rydberg test updates
547
        t.has("a_directory_name") are undefined.
1910.7.17 by Andrew Bennetts
Various cosmetic changes.
548
549
        :rtype: bool
1442.1.44 by Robert Collins
Many transport related tweaks:
550
        """
1540.3.1 by Martin Pool
First-cut implementation of pycurl. Substantially faster than using urllib.
551
        raise NotImplementedError(self.has)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
552
907.1.36 by John Arbash Meinel
Moving the multi-get functionality higher up into the Branch class.
553
    def has_multi(self, relpaths, pb=None):
907.1.34 by John Arbash Meinel
Fixing append(), cleaning up function locations.
554
        """Return True/False for each entry in relpaths"""
555
        total = self._get_total(relpaths)
556
        count = 0
557
        for relpath in relpaths:
907.1.36 by John Arbash Meinel
Moving the multi-get functionality higher up into the Branch class.
558
            self._update_pb(pb, 'has', count, total)
907.1.34 by John Arbash Meinel
Fixing append(), cleaning up function locations.
559
            yield self.has(relpath)
560
            count += 1
561
1185.16.155 by John Arbash Meinel
Added a has_any function to the Transport API
562
    def has_any(self, relpaths):
563
        """Return True if any of the paths exist."""
564
        for relpath in relpaths:
565
            if self.has(relpath):
566
                return True
567
        return False
568
1442.1.44 by Robert Collins
Many transport related tweaks:
569
    def iter_files_recursive(self):
570
        """Iter the relative paths of files in the transports sub-tree.
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
571
572
        *NOTE*: This only lists *files*, not subdirectories!
1442.1.44 by Robert Collins
Many transport related tweaks:
573
        
574
        As with other listing functions, only some transports implement this,.
575
        you may check via is_listable to determine if it will.
576
        """
1530.1.4 by Robert Collins
integrate Memory tests into transport interface tests.
577
        raise errors.TransportNotPossible("This transport has not "
1530.1.21 by Robert Collins
Review feedback fixes.
578
                                          "implemented iter_files_recursive "
1530.1.4 by Robert Collins
integrate Memory tests into transport interface tests.
579
                                          "(but must claim to be listable "
580
                                          "to trigger this error).")
1442.1.44 by Robert Collins
Many transport related tweaks:
581
2164.2.15 by Vincent Ladeuil
Http redirections are not followed by default. Do not use hints
582
    def get(self, relpath):
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
583
        """Get the file at the given relative path.
907.1.20 by John Arbash Meinel
Removed Transport.open(), making get + put encode/decode to utf-8
584
2052.6.1 by Robert Collins
``Transport.get`` has had its interface made more clear for ease of use.
585
        This may fail in a number of ways:
586
         - HTTP servers may return content for a directory. (unexpected
587
           content failure)
588
         - FTP servers may indicate NoSuchFile for a directory.
589
         - SFTP servers may give a file handle for a directory that will
590
           fail on read().
591
592
        For correct use of the interface, be sure to catch errors.PathError
593
        when calling it and catch errors.ReadError when reading from the
594
        returned object.
595
907.1.20 by John Arbash Meinel
Removed Transport.open(), making get + put encode/decode to utf-8
596
        :param relpath: The relative path to the file
1910.19.2 by Andrew Bennetts
Add a new method ``Transport.get_smart_client()``. This is provided to allow
597
        :rtype: File-like object.
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
598
        """
1540.3.1 by Martin Pool
First-cut implementation of pycurl. Substantially faster than using urllib.
599
        raise NotImplementedError(self.get)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
600
1955.3.3 by John Arbash Meinel
Implement and test 'get_bytes'
601
    def get_bytes(self, relpath):
602
        """Get a raw string of the bytes for a file at the given location.
603
604
        :param relpath: The relative path to the file
605
        """
606
        return self.get(relpath).read()
607
3241.1.6 by Andrew Bennetts
Deprecate Transport.get_smart_client and errors.NoSmartServer, as these are now unused.
608
    @deprecated_method(one_four)
1910.19.2 by Andrew Bennetts
Add a new method ``Transport.get_smart_client()``. This is provided to allow
609
    def get_smart_client(self):
610
        """Return a smart client for this transport if possible.
611
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
612
        A smart client doesn't imply the presence of a smart server: it implies
613
        that the smart protocol can be tunnelled via this transport.
614
1910.19.2 by Andrew Bennetts
Add a new method ``Transport.get_smart_client()``. This is provided to allow
615
        :raises NoSmartServer: if no smart server client is available.
616
        """
617
        raise errors.NoSmartServer(self.base)
618
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
619
    def get_smart_medium(self):
620
        """Return a smart client medium for this transport if possible.
621
622
        A smart medium doesn't imply the presence of a smart server: it implies
623
        that the smart protocol can be tunnelled via this transport.
624
625
        :raises NoSmartMedium: if no smart server medium is available.
626
        """
627
        raise errors.NoSmartMedium(self)
628
3313.2.3 by Andrew Bennetts
Deprecate Transport.get_shared_medium.
629
    @deprecated_method(one_four)
2485.8.54 by Vincent Ladeuil
Refactor medium uses by making a distinction betweem shared and real medium.
630
    def get_shared_medium(self):
631
        """Return a smart client shared medium for this transport if possible.
632
633
        A smart medium doesn't imply the presence of a smart server: it implies
634
        that the smart protocol can be tunnelled via this transport.
635
636
        :raises NoSmartMedium: if no smart server medium is available.
637
        """
638
        raise errors.NoSmartMedium(self)
639
2745.5.3 by Robert Collins
* Move transport logging into a new transport class
640
    def readv(self, relpath, offsets, adjust_for_latency=False,
641
        upper_limit=None):
2745.5.1 by Robert Collins
* New parameter on ``bzrlib.transport.Transport.readv``
642
        """Get parts of the file at the given relative path.
643
644
        :param relpath: The path to read data from.
645
        :param offsets: A list of (offset, size) tuples.
3024.2.1 by Vincent Ladeuil
Fix 165061 by using the correct _max_readv_combine attribute.
646
        :param adjust_for_latency: Adjust the requested offsets to accomodate
2745.5.1 by Robert Collins
* New parameter on ``bzrlib.transport.Transport.readv``
647
            transport latency. This may re-order the offsets, expand them to
648
            grab adjacent data when there is likely a high cost to requesting
649
            data relative to delivering it.
2745.5.3 by Robert Collins
* Move transport logging into a new transport class
650
        :param upper_limit: When adjust_for_latency is True setting upper_limit
651
            allows the caller to tell the transport about the length of the
652
            file, so that requests are not issued for ranges beyond the end of
653
            the file. This matters because some servers and/or transports error
654
            in such a case rather than just satisfying the available ranges.
655
            upper_limit should always be provided when adjust_for_latency is
656
            True, and should be the size of the file in bytes.
2745.5.1 by Robert Collins
* New parameter on ``bzrlib.transport.Transport.readv``
657
        :return: A list or generator of (offset, data) tuples
658
        """
659
        if adjust_for_latency:
2890.1.3 by Robert Collins
Review feedback and discussion with Martin - split out the readv offset adjustment into a new helper and document where the design might/should go next.
660
            # Design note: We may wish to have different algorithms for the
661
            # expansion of the offsets per-transport. E.g. for local disk to
3024.2.1 by Vincent Ladeuil
Fix 165061 by using the correct _max_readv_combine attribute.
662
            # use page-aligned expansion. If that is the case consider the
663
            # following structure:
664
            #  - a test that transport.readv uses self._offset_expander or some
665
            #    similar attribute, to do the expansion
666
            #  - a test for each transport that it has some known-good offset
667
            #    expander
2890.1.3 by Robert Collins
Review feedback and discussion with Martin - split out the readv offset adjustment into a new helper and document where the design might/should go next.
668
            #  - unit tests for each offset expander
669
            #  - a set of tests for the offset expander interface, giving
670
            #    baseline behaviour (which the current transport
671
            #    adjust_for_latency tests could be repurposed to).
672
            offsets = self._sort_expand_and_combine(offsets, upper_limit)
2745.5.1 by Robert Collins
* New parameter on ``bzrlib.transport.Transport.readv``
673
        return self._readv(relpath, offsets)
674
675
    def _readv(self, relpath, offsets):
1594.2.5 by Robert Collins
Readv patch from Johan Rydberg giving knits partial download support.
676
        """Get parts of the file at the given relative path.
677
2745.5.3 by Robert Collins
* Move transport logging into a new transport class
678
        :param relpath: The path to read.
679
        :param offsets: A list of (offset, size) tuples.
1594.2.5 by Robert Collins
Readv patch from Johan Rydberg giving knits partial download support.
680
        :return: A list or generator of (offset, data) tuples
681
        """
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
682
        if not offsets:
1594.2.16 by Robert Collins
Coalesce readv requests on file based transports.
683
            return
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
684
1864.5.7 by John Arbash Meinel
remove disable prefetch support
685
        fp = self.get(relpath)
2001.3.2 by John Arbash Meinel
Force all transports to raise ShortReadvError if they can
686
        return self._seek_and_read(fp, offsets, relpath)
1864.5.11 by John Arbash Meinel
Factor out the workhorse of Transport.readv() into a helper function, and re-use that function in sftp but with a non-prefetch file.
687
2001.3.2 by John Arbash Meinel
Force all transports to raise ShortReadvError if they can
688
    def _seek_and_read(self, fp, offsets, relpath='<unknown>'):
1864.5.11 by John Arbash Meinel
Factor out the workhorse of Transport.readv() into a helper function, and re-use that function in sftp but with a non-prefetch file.
689
        """An implementation of readv that uses fp.seek and fp.read.
690
691
        This uses _coalesce_offsets to issue larger reads and fewer seeks.
692
693
        :param fp: A file-like object that supports seek() and read(size)
694
        :param offsets: A list of offsets to be read from the given file.
695
        :return: yield (pos, data) tuples for each request
696
        """
1864.5.2 by John Arbash Meinel
always read in sorted order, and return in requested order, but only cache what is currently out of order
697
        # We are going to iterate multiple times, we need a list
698
        offsets = list(offsets)
699
        sorted_offsets = sorted(offsets)
700
701
        # turn the list of offsets into a stack
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
702
        offset_stack = iter(offsets)
703
        cur_offset_and_size = offset_stack.next()
1864.5.2 by John Arbash Meinel
always read in sorted order, and return in requested order, but only cache what is currently out of order
704
        coalesced = self._coalesce_offsets(sorted_offsets,
1864.5.3 by John Arbash Meinel
Allow collapsing ranges even if they are just 'close'
705
                               limit=self._max_readv_combine,
706
                               fudge_factor=self._bytes_to_read_before_seek)
1864.5.2 by John Arbash Meinel
always read in sorted order, and return in requested order, but only cache what is currently out of order
707
708
        # Cache the results, but only until they have been fulfilled
709
        data_map = {}
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
710
        for c_offset in coalesced:
1864.5.11 by John Arbash Meinel
Factor out the workhorse of Transport.readv() into a helper function, and re-use that function in sftp but with a non-prefetch file.
711
            # TODO: jam 20060724 it might be faster to not issue seek if 
712
            #       we are already at the right location. This should be
713
            #       benchmarked.
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
714
            fp.seek(c_offset.start)
715
            data = fp.read(c_offset.length)
2001.3.2 by John Arbash Meinel
Force all transports to raise ShortReadvError if they can
716
            if len(data) < c_offset.length:
717
                raise errors.ShortReadvError(relpath, c_offset.start,
2001.3.3 by John Arbash Meinel
review feedback: add the actual count written to ShortReadvError
718
                            c_offset.length, actual=len(data))
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
719
            for suboffset, subsize in c_offset.ranges:
720
                key = (c_offset.start+suboffset, subsize)
721
                data_map[key] = data[suboffset:suboffset+subsize]
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
722
1864.5.8 by John Arbash Meinel
Cleanup and NEWS
723
            # Now that we've read some data, see if we can yield anything back
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
724
            while cur_offset_and_size in data_map:
725
                this_data = data_map.pop(cur_offset_and_size)
726
                yield cur_offset_and_size[0], this_data
727
                cur_offset_and_size = offset_stack.next()
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
728
2890.1.3 by Robert Collins
Review feedback and discussion with Martin - split out the readv offset adjustment into a new helper and document where the design might/should go next.
729
    def _sort_expand_and_combine(self, offsets, upper_limit):
730
        """Helper for readv.
731
732
        :param offsets: A readv vector - (offset, length) tuples.
733
        :param upper_limit: The highest byte offset that may be requested.
734
        :return: A readv vector that will read all the regions requested by
735
            offsets, in start-to-end order, with no duplicated regions,
736
            expanded by the transports recommended page size.
737
        """
738
        offsets = sorted(offsets)
739
        # short circuit empty requests
740
        if len(offsets) == 0:
741
            def empty_yielder():
742
                # Quick thunk to stop this function becoming a generator
743
                # itself, rather we return a generator that has nothing to
744
                # yield.
745
                if False:
746
                    yield None
747
            return empty_yielder()
748
        # expand by page size at either end
749
        maximum_expansion = self.recommended_page_size()
750
        new_offsets = []
751
        for offset, length in offsets:
752
            expansion = maximum_expansion - length
753
            if expansion < 0:
754
                # we're asking for more than the minimum read anyway.
755
                expansion = 0
756
            reduction = expansion / 2
757
            new_offset = offset - reduction
758
            new_length = length + expansion
759
            if new_offset < 0:
760
                # don't ask for anything < 0
761
                new_offset = 0
762
            if (upper_limit is not None and
763
                new_offset + new_length > upper_limit):
764
                new_length = upper_limit - new_offset
765
            new_offsets.append((new_offset, new_length))
766
        # combine the expanded offsets
767
        offsets = []
768
        current_offset, current_length = new_offsets[0]
769
        current_finish = current_length + current_offset
770
        for offset, length in new_offsets[1:]:
771
            finish = offset + length
772
            if offset > current_finish:
773
                # there is a gap, output the current accumulator and start
774
                # a new one for the region we're examining.
775
                offsets.append((current_offset, current_length))
776
                current_offset = offset
777
                current_length = length
778
                current_finish = finish
779
                continue
780
            if finish > current_finish:
781
                # extend the current accumulator to the end of the region
782
                # we're examining.
783
                current_finish = finish
784
                current_length = finish - current_offset
785
        offsets.append((current_offset, current_length))
786
        return offsets
787
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
788
    @staticmethod
3059.2.17 by Vincent Ladeuil
Limit GET requests by body size instead of number of ranges.
789
    def _coalesce_offsets(offsets, limit=0, fudge_factor=0, max_size=0):
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
790
        """Yield coalesced offsets.
791
792
        With a long list of neighboring requests, combine them
793
        into a single large request, while retaining the original
794
        offsets.
795
        Turns  [(15, 10), (25, 10)] => [(15, 20, [(0, 10), (10, 10)])]
796
797
        :param offsets: A list of (start, length) pairs
3059.2.17 by Vincent Ladeuil
Limit GET requests by body size instead of number of ranges.
798
799
        :param limit: Only combine a maximum of this many pairs Some transports
800
                penalize multiple reads more than others, and sometimes it is
801
                better to return early.
802
                0 means no limit
803
1864.5.3 by John Arbash Meinel
Allow collapsing ranges even if they are just 'close'
804
        :param fudge_factor: All transports have some level of 'it is
805
                better to read some more data and throw it away rather 
806
                than seek', so collapse if we are 'close enough'
3059.2.17 by Vincent Ladeuil
Limit GET requests by body size instead of number of ranges.
807
808
        :param max_size: Create coalesced offsets no bigger than this size.
809
                When a single offset is bigger than 'max_size', it will keep
810
                its size and be alone in the coalesced offset.
811
                0 means no maximum size.
812
2520.2.1 by Vincent Ladeuil
First step to fix #115209 use _coalesce_offsets like other transports.
813
        :return: yield _CoalescedOffset objects, which have members for where
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
814
                to start, how much to read, and how to split those 
815
                chunks back up
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
816
        """
817
        last_end = None
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
818
        cur = _CoalescedOffset(None, None, [])
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
819
820
        for start, size in offsets:
821
            end = start + size
3059.2.17 by Vincent Ladeuil
Limit GET requests by body size instead of number of ranges.
822
            if (last_end is not None
1864.5.3 by John Arbash Meinel
Allow collapsing ranges even if they are just 'close'
823
                and start <= last_end + fudge_factor
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
824
                and start >= cur.start
3059.2.17 by Vincent Ladeuil
Limit GET requests by body size instead of number of ranges.
825
                and (limit <= 0 or len(cur.ranges) < limit)
826
                and (max_size <= 0 or end - cur.start <= max_size)):
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
827
                cur.length = end - cur.start
828
                cur.ranges.append((start-cur.start, size))
1594.2.16 by Robert Collins
Coalesce readv requests on file based transports.
829
            else:
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
830
                if cur.start is not None:
831
                    yield cur
832
                cur = _CoalescedOffset(start, size, [(0, size)])
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
833
            last_end = end
834
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
835
        if cur.start is not None:
836
            yield cur
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
837
838
        return
1594.2.5 by Robert Collins
Readv patch from Johan Rydberg giving knits partial download support.
839
907.1.50 by John Arbash Meinel
Removed encode/decode from Transport.put/get, added more exceptions that can be thrown.
840
    def get_multi(self, relpaths, pb=None):
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
841
        """Get a list of file-like objects, one for each entry in relpaths.
842
843
        :param relpaths: A list of relative paths.
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
844
        :param pb:  An optional ProgressBar for indicating percent done.
845
        :return: A list or generator of file-like objects
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
846
        """
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
847
        # TODO: Consider having this actually buffer the requests,
848
        # in the default mode, it probably won't give worse performance,
849
        # and all children wouldn't have to implement buffering
907.1.16 by John Arbash Meinel
Fixing a few cut&paste typos.
850
        total = self._get_total(relpaths)
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
851
        count = 0
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
852
        for relpath in relpaths:
907.1.16 by John Arbash Meinel
Fixing a few cut&paste typos.
853
            self._update_pb(pb, 'get', count, total)
907.1.50 by John Arbash Meinel
Removed encode/decode from Transport.put/get, added more exceptions that can be thrown.
854
            yield self.get(relpath)
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
855
            count += 1
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
856
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
857
    def put_bytes(self, relpath, bytes, mode=None):
858
        """Atomically put the supplied bytes into the given location.
859
860
        :param relpath: The location to put the contents, relative to the
861
            transport base.
862
        :param bytes: A bytestring of data.
863
        :param mode: Create the file with the given mode.
864
        :return: None
865
        """
2414.1.3 by Andrew Bennetts
Fix test failures under 'python2.4 -O' ('python2.5 -O' was already passing).
866
        if not isinstance(bytes, str):
867
            raise AssertionError(
868
                'bytes must be a plain string, not %s' % type(bytes))
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
869
        return self.put_file(relpath, StringIO(bytes), mode=mode)
870
871
    def put_bytes_non_atomic(self, relpath, bytes, mode=None,
1946.2.12 by John Arbash Meinel
Add ability to pass a directory mode to non_atomic_put
872
                             create_parent_dir=False,
873
                             dir_mode=None):
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
874
        """Copy the string into the target location.
875
876
        This function is not strictly safe to use. See 
877
        Transport.put_bytes_non_atomic for more information.
878
879
        :param relpath: The remote location to put the contents.
880
        :param bytes:   A string object containing the raw bytes to write into
881
                        the target file.
882
        :param mode:    Possible access permissions for new file.
883
                        None means do not set remote permissions.
884
        :param create_parent_dir: If we cannot create the target file because
885
                        the parent directory does not exist, go ahead and
886
                        create it, and then try again.
1946.2.12 by John Arbash Meinel
Add ability to pass a directory mode to non_atomic_put
887
        :param dir_mode: Possible access permissions for new directories.
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
888
        """
2414.1.3 by Andrew Bennetts
Fix test failures under 'python2.4 -O' ('python2.5 -O' was already passing).
889
        if not isinstance(bytes, str):
890
            raise AssertionError(
891
                'bytes must be a plain string, not %s' % type(bytes))
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
892
        self.put_file_non_atomic(relpath, StringIO(bytes), mode=mode,
1946.2.12 by John Arbash Meinel
Add ability to pass a directory mode to non_atomic_put
893
                                 create_parent_dir=create_parent_dir,
894
                                 dir_mode=dir_mode)
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
895
1955.3.6 by John Arbash Meinel
Lots of deprecation warnings, but no errors
896
    def put_file(self, relpath, f, mode=None):
897
        """Copy the file-like object into the location.
898
899
        :param relpath: Location to put the contents, relative to base.
900
        :param f:       File-like object.
901
        :param mode: The mode for the newly created file,
902
                     None means just use the default.
2745.5.2 by Robert Collins
* ``bzrlib.transport.Transport.put_file`` now returns the number of bytes
903
        :return: The length of the file that was written.
1955.3.6 by John Arbash Meinel
Lots of deprecation warnings, but no errors
904
        """
905
        # We would like to mark this as NotImplemented, but most likely
906
        # transports have defined it in terms of the old api.
907
        symbol_versioning.warn('Transport %s should implement put_file,'
908
                               ' rather than implementing put() as of'
909
                               ' version 0.11.'
910
                               % (self.__class__.__name__,),
911
                               DeprecationWarning)
912
        return self.put(relpath, f, mode=mode)
913
        #raise NotImplementedError(self.put_file)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
914
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
915
    def put_file_non_atomic(self, relpath, f, mode=None,
1946.2.12 by John Arbash Meinel
Add ability to pass a directory mode to non_atomic_put
916
                            create_parent_dir=False,
917
                            dir_mode=None):
1946.1.1 by John Arbash Meinel
Stub out the test and basic implementation for 'non_atomic_put'
918
        """Copy the file-like object into the target location.
919
920
        This function is not strictly safe to use. It is only meant to
921
        be used when you already know that the target does not exist.
922
        It is not safe, because it will open and truncate the remote
923
        file. So there may be a time when the file has invalid contents.
924
925
        :param relpath: The remote location to put the contents.
926
        :param f:       File-like object.
927
        :param mode:    Possible access permissions for new file.
928
                        None means do not set remote permissions.
1946.1.8 by John Arbash Meinel
Update non_atomic_put to have a create_parent_dir flag
929
        :param create_parent_dir: If we cannot create the target file because
930
                        the parent directory does not exist, go ahead and
931
                        create it, and then try again.
1946.2.12 by John Arbash Meinel
Add ability to pass a directory mode to non_atomic_put
932
        :param dir_mode: Possible access permissions for new directories.
1946.1.1 by John Arbash Meinel
Stub out the test and basic implementation for 'non_atomic_put'
933
        """
934
        # Default implementation just does an atomic put.
1946.1.8 by John Arbash Meinel
Update non_atomic_put to have a create_parent_dir flag
935
        try:
1955.3.19 by John Arbash Meinel
rename non_atomic_put => non_atomic_put_file
936
            return self.put_file(relpath, f, mode=mode)
1946.1.8 by John Arbash Meinel
Update non_atomic_put to have a create_parent_dir flag
937
        except errors.NoSuchFile:
938
            if not create_parent_dir:
939
                raise
940
            parent_dir = osutils.dirname(relpath)
941
            if parent_dir:
1946.2.12 by John Arbash Meinel
Add ability to pass a directory mode to non_atomic_put
942
                self.mkdir(parent_dir, mode=dir_mode)
1955.3.19 by John Arbash Meinel
rename non_atomic_put => non_atomic_put_file
943
                return self.put_file(relpath, f, mode=mode)
1946.1.1 by John Arbash Meinel
Stub out the test and basic implementation for 'non_atomic_put'
944
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
945
    def mkdir(self, relpath, mode=None):
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
946
        """Create a directory at the given path."""
1540.3.1 by Martin Pool
First-cut implementation of pycurl. Substantially faster than using urllib.
947
        raise NotImplementedError(self.mkdir)
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
948
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
949
    def mkdir_multi(self, relpaths, mode=None, pb=None):
907.1.47 by John Arbash Meinel
Created mkdir_multi, modified branch to use _multi forms when initializing a branch, creating a full test routine for transports
950
        """Create a group of directories"""
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
951
        def mkdir(path):
952
            self.mkdir(path, mode=mode)
1563.2.3 by Robert Collins
Change the return signature of transport.append and append_multi to return the length of the pre-append content.
953
        return len(self._iterate_over(relpaths, mkdir, pb, 'mkdir', expand=False))
907.1.47 by John Arbash Meinel
Created mkdir_multi, modified branch to use _multi forms when initializing a branch, creating a full test routine for transports
954
2671.3.9 by Robert Collins
Review feedback and fix VFat emulated transports to not claim to have unix permissions.
955
    def open_write_stream(self, relpath, mode=None):
956
        """Open a writable file stream at relpath.
2671.3.2 by Robert Collins
Start open_file_stream logic.
957
2671.3.9 by Robert Collins
Review feedback and fix VFat emulated transports to not claim to have unix permissions.
958
        A file stream is a file like object with a write() method that accepts
959
        bytes to write.. Buffering may occur internally until the stream is
960
        closed with stream.close().  Calls to readv or the get_* methods will
961
        be synchronised with any internal buffering that may be present.
2671.3.2 by Robert Collins
Start open_file_stream logic.
962
963
        :param relpath: The relative path to the file.
2671.3.3 by Robert Collins
Add mode parameter to Transport.open_file_stream.
964
        :param mode: The mode for the newly created file, 
965
                     None means just use the default
2671.3.6 by Robert Collins
Review feedback.
966
        :return: A FileStream. FileStream objects have two methods, write() and
967
            close(). There is no guarantee that data is committed to the file
968
            if close() has not been called (even if get() is called on the same
969
            path).
2671.3.2 by Robert Collins
Start open_file_stream logic.
970
        """
2671.3.9 by Robert Collins
Review feedback and fix VFat emulated transports to not claim to have unix permissions.
971
        raise NotImplementedError(self.open_write_stream)
2671.3.2 by Robert Collins
Start open_file_stream logic.
972
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
973
    def append_file(self, relpath, f, mode=None):
1910.7.18 by Andrew Bennetts
Merge from bzr.dev
974
        """Append bytes from a file-like object to a file at relpath.
975
976
        The file is created if it does not already exist.
977
978
        :param f: a file-like object of the bytes to append.
979
        :param mode: Unix mode for newly created files.  This is not used for
980
            existing files.
981
982
        :returns: the length of relpath before the content was written to it.
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
983
        """
984
        symbol_versioning.warn('Transport %s should implement append_file,'
985
                               ' rather than implementing append() as of'
986
                               ' version 0.11.'
987
                               % (self.__class__.__name__,),
988
                               DeprecationWarning)
989
        return self.append(relpath, f, mode=mode)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
990
1955.3.2 by John Arbash Meinel
Implement and test 'Transport.append_bytes', cleanup the tests of plain append
991
    def append_bytes(self, relpath, bytes, mode=None):
1910.7.18 by Andrew Bennetts
Merge from bzr.dev
992
        """Append bytes to a file at relpath.
993
994
        The file is created if it does not already exist.
995
996
        :type f: str
997
        :param f: a string of the bytes to append.
998
        :param mode: Unix mode for newly created files.  This is not used for
999
            existing files.
1000
1001
        :returns: the length of relpath before the content was written to it.
1955.3.2 by John Arbash Meinel
Implement and test 'Transport.append_bytes', cleanup the tests of plain append
1002
        """
1003
        assert isinstance(bytes, str), \
1004
            'bytes must be a plain string, not %s' % type(bytes)
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
1005
        return self.append_file(relpath, StringIO(bytes), mode=mode)
1955.3.2 by John Arbash Meinel
Implement and test 'Transport.append_bytes', cleanup the tests of plain append
1006
1185.11.19 by John Arbash Meinel
Testing put and append, also testing agaist file-like objects as well as strings.
1007
    def append_multi(self, files, pb=None):
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
1008
        """Append the text in each file-like or string object to
1009
        the supplied location.
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
1010
1011
        :param files: A set of (path, f) entries
1012
        :param pb:  An optional ProgressBar for indicating percent done.
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
1013
        """
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
1014
        return self._iterate_over(files, self.append_file, pb, 'append', expand=True)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
1015
1016
    def copy(self, rel_from, rel_to):
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1017
        """Copy the item at rel_from to the location at rel_to.
1018
        
1019
        Override this for efficiency if a specific transport can do it 
1020
        faster than this default implementation.
1021
        """
1955.3.11 by John Arbash Meinel
Clean up the rest of the api calls to deprecated functions in the test suite, and make sure Transport._pump is only accepting files, not strings
1022
        self.put_file(rel_to, self.get(rel_from))
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
1023
907.1.28 by John Arbash Meinel
Added pb to function that were missing, implemented a basic double-dispatch copy_to function.
1024
    def copy_multi(self, relpaths, pb=None):
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
1025
        """Copy a bunch of entries.
1026
        
1027
        :param relpaths: A list of tuples of the form [(from, to), (from, to),...]
1028
        """
1029
        # This is the non-pipelined implementation, so that
1030
        # implementors don't have to implement everything.
907.1.14 by John Arbash Meinel
Handling some transport functions which take only a single argument.
1031
        return self._iterate_over(relpaths, self.copy, pb, 'copy', expand=True)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
1032
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
1033
    def copy_to(self, relpaths, other, mode=None, pb=None):
907.1.28 by John Arbash Meinel
Added pb to function that were missing, implemented a basic double-dispatch copy_to function.
1034
        """Copy a set of entries from self into another Transport.
1035
1036
        :param relpaths: A list/generator of entries to be copied.
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
1037
        :param mode: This is the target mode for the newly created files
1185.16.156 by John Arbash Meinel
Adding a note about changing copy_to's interface
1038
        TODO: This interface needs to be updated so that the target location
1039
              can be different from the source location.
907.1.28 by John Arbash Meinel
Added pb to function that were missing, implemented a basic double-dispatch copy_to function.
1040
        """
1041
        # The dummy implementation just does a simple get + put
1042
        def copy_entry(path):
1955.3.11 by John Arbash Meinel
Clean up the rest of the api calls to deprecated functions in the test suite, and make sure Transport._pump is only accepting files, not strings
1043
            other.put_file(path, self.get(path), mode=mode)
907.1.28 by John Arbash Meinel
Added pb to function that were missing, implemented a basic double-dispatch copy_to function.
1044
1563.2.3 by Robert Collins
Change the return signature of transport.append and append_multi to return the length of the pre-append content.
1045
        return len(self._iterate_over(relpaths, copy_entry, pb, 'copy_to', expand=False))
907.1.28 by John Arbash Meinel
Added pb to function that were missing, implemented a basic double-dispatch copy_to function.
1046
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
1047
    def copy_tree(self, from_relpath, to_relpath):
1048
        """Copy a subtree from one relpath to another.
1049
1050
        If a faster implementation is available, specific transports should 
1051
        implement it.
1052
        """
1053
        source = self.clone(from_relpath)
1054
        self.mkdir(to_relpath)
1055
        target = self.clone(to_relpath)
1056
        files = []
1057
        directories = ['.']
1058
        while directories:
1059
            dir = directories.pop()
1060
            if dir != '.':
1061
                target.mkdir(dir)
1062
            for path in source.list_dir(dir):
1063
                path = dir + '/' + path
1064
                stat = source.stat(path)
1065
                if S_ISDIR(stat.st_mode):
1066
                    directories.append(path)
1067
                else:
1068
                    files.append(path)
1069
        source.copy_to(files, target)
1070
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
1071
    def rename(self, rel_from, rel_to):
1072
        """Rename a file or directory.
1073
1074
        This *must* fail if the destination is a nonempty directory - it must
1075
        not automatically remove it.  It should raise DirectoryNotEmpty, or
1076
        some other PathError if the case can't be specifically detected.
1077
1078
        If the destination is an empty directory or a file this function may
1079
        either fail or succeed, depending on the underlying transport.  It
1080
        should not attempt to remove the destination if overwriting is not the
1081
        native transport behaviour.  If at all possible the transport should
1082
        ensure that the rename either completes or not, without leaving the
1083
        destination deleted and the new file not moved in place.
1084
1085
        This is intended mainly for use in implementing LockDir.
1086
        """
1087
        # transports may need to override this
1553.5.17 by Martin Pool
Transport.rename should be unimplemented in base class
1088
        raise NotImplementedError(self.rename)
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
1089
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
1090
    def move(self, rel_from, rel_to):
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1091
        """Move the item at rel_from to the location at rel_to.
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
1092
1093
        The destination is deleted if possible, even if it's a non-empty
1094
        directory tree.
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1095
        
1096
        If a transport can directly implement this it is suggested that
1097
        it do so for efficiency.
1098
        """
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
1099
        if S_ISDIR(self.stat(rel_from).st_mode):
1100
            self.copy_tree(rel_from, rel_to)
1101
            self.delete_tree(rel_from)
1102
        else:
1103
            self.copy(rel_from, rel_to)
1104
            self.delete(rel_from)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
1105
907.1.28 by John Arbash Meinel
Added pb to function that were missing, implemented a basic double-dispatch copy_to function.
1106
    def move_multi(self, relpaths, pb=None):
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
1107
        """Move a bunch of entries.
1108
        
1109
        :param relpaths: A list of tuples of the form [(from1, to1), (from2, to2),...]
1110
        """
907.1.14 by John Arbash Meinel
Handling some transport functions which take only a single argument.
1111
        return self._iterate_over(relpaths, self.move, pb, 'move', expand=True)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
1112
1113
    def move_multi_to(self, relpaths, rel_to):
1114
        """Move a bunch of entries to a single location.
1115
        This differs from move_multi in that you give a list of from, and
1116
        a single destination, rather than multiple destinations.
1117
1118
        :param relpaths: A list of relative paths [from1, from2, from3, ...]
1119
        :param rel_to: A directory where each entry should be placed.
1120
        """
1121
        # This is not implemented, because you need to do special tricks to
1122
        # extract the basename, and add it to rel_to
1540.3.1 by Martin Pool
First-cut implementation of pycurl. Substantially faster than using urllib.
1123
        raise NotImplementedError(self.move_multi_to)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
1124
1125
    def delete(self, relpath):
1126
        """Delete the item at relpath"""
1540.3.1 by Martin Pool
First-cut implementation of pycurl. Substantially faster than using urllib.
1127
        raise NotImplementedError(self.delete)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
1128
907.1.28 by John Arbash Meinel
Added pb to function that were missing, implemented a basic double-dispatch copy_to function.
1129
    def delete_multi(self, relpaths, pb=None):
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
1130
        """Queue up a bunch of deletes to be done.
1131
        """
907.1.14 by John Arbash Meinel
Handling some transport functions which take only a single argument.
1132
        return self._iterate_over(relpaths, self.delete, pb, 'delete', expand=False)
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
1133
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
1134
    def delete_tree(self, relpath):
1135
        """Delete an entire tree. This may require a listable transport."""
1136
        subtree = self.clone(relpath)
1137
        files = []
1138
        directories = ['.']
1139
        pending_rmdirs = []
1140
        while directories:
1141
            dir = directories.pop()
1142
            if dir != '.':
1143
                pending_rmdirs.append(dir)
1144
            for path in subtree.list_dir(dir):
1145
                path = dir + '/' + path
1146
                stat = subtree.stat(path)
1147
                if S_ISDIR(stat.st_mode):
1148
                    directories.append(path)
1149
                else:
1150
                    files.append(path)
1151
        subtree.delete_multi(files)
1152
        pending_rmdirs.reverse()
1153
        for dir in pending_rmdirs:
1154
            subtree.rmdir(dir)
1155
        self.rmdir(relpath)
1156
1534.5.7 by Robert Collins
Start factoring out the upgrade policy logic.
1157
    def __repr__(self):
1158
        return "<%s.%s url=%s>" % (self.__module__, self.__class__.__name__, self.base)
1159
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
1160
    def stat(self, relpath):
1161
        """Return the stat information for a file.
1162
        WARNING: This may not be implementable for all protocols, so use
1163
        sparingly.
1442.1.44 by Robert Collins
Many transport related tweaks:
1164
        NOTE: This returns an object with fields such as 'st_size'. It MAY
1165
        or MAY NOT return the literal result of an os.stat() call, so all
1166
        access should be via named fields.
1167
        ALSO NOTE: Stats of directories may not be supported on some 
1168
        transports.
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
1169
        """
1540.3.1 by Martin Pool
First-cut implementation of pycurl. Substantially faster than using urllib.
1170
        raise NotImplementedError(self.stat)
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
1171
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
1172
    def rmdir(self, relpath):
1173
        """Remove a directory at the given path."""
1174
        raise NotImplementedError
1175
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
1176
    def stat_multi(self, relpaths, pb=None):
1177
        """Stat multiple files and return the information.
1178
        """
1179
        #TODO:  Is it worth making this a generator instead of a
1180
        #       returning a list?
1181
        stats = []
1182
        def gather(path):
1183
            stats.append(self.stat(path))
1184
907.1.14 by John Arbash Meinel
Handling some transport functions which take only a single argument.
1185
        count = self._iterate_over(relpaths, gather, pb, 'stat', expand=False)
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
1186
        return stats
1187
1400.1.1 by Robert Collins
implement a basic test for the ui branch command from http servers
1188
    def listable(self):
1189
        """Return True if this store supports listing."""
1540.3.1 by Martin Pool
First-cut implementation of pycurl. Substantially faster than using urllib.
1190
        raise NotImplementedError(self.listable)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
1191
1192
    def list_dir(self, relpath):
1193
        """Return a list of all files at the given location.
1194
        WARNING: many transports do not support this, so trying avoid using
1195
        it if at all possible.
1196
        """
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
1197
        raise errors.TransportNotPossible("Transport %r has not "
1530.1.21 by Robert Collins
Review feedback fixes.
1198
                                          "implemented list_dir "
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1199
                                          "(but must claim to be listable "
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
1200
                                          "to trigger this error)."
1201
                                          % (self))
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
1202
907.1.24 by John Arbash Meinel
Remote functionality work.
1203
    def lock_read(self, relpath):
1204
        """Lock the given file for shared (read) access.
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
1205
1206
        WARNING: many transports do not support this, so trying avoid using it.
1207
        These methods may be removed in the future.
1208
1209
        Transports may raise TransportNotPossible if OS-level locks cannot be
1210
        taken over this transport.  
907.1.24 by John Arbash Meinel
Remote functionality work.
1211
1212
        :return: A lock object, which should contain an unlock() function.
1213
        """
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
1214
        raise errors.TransportNotPossible("transport locks not supported on %s" % self)
907.1.24 by John Arbash Meinel
Remote functionality work.
1215
1216
    def lock_write(self, relpath):
1217
        """Lock the given file for exclusive (write) access.
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
1218
1219
        WARNING: many transports do not support this, so trying avoid using it.
1220
        These methods may be removed in the future.
1221
1222
        Transports may raise TransportNotPossible if OS-level locks cannot be
1223
        taken over this transport.
907.1.24 by John Arbash Meinel
Remote functionality work.
1224
1225
        :return: A lock object, which should contain an unlock() function.
1226
        """
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
1227
        raise errors.TransportNotPossible("transport locks not supported on %s" % self)
907.1.24 by John Arbash Meinel
Remote functionality work.
1228
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1229
    def is_readonly(self):
1230
        """Return true if this connection cannot be written to."""
1231
        return False
1232
1608.2.7 by Martin Pool
Rename supports_unix_modebits to _can_roundtrip_unix_modebits for clarity
1233
    def _can_roundtrip_unix_modebits(self):
1608.2.5 by Martin Pool
Add Transport.supports_unix_modebits, so tests can
1234
        """Return true if this transport can store and retrieve unix modebits.
1235
1236
        (For example, 0700 to make a directory owner-private.)
1237
        
1238
        Note: most callers will not want to switch on this, but should rather 
1239
        just try and set permissions and let them be either stored or not.
1240
        This is intended mainly for the use of the test suite.
1241
        
1242
        Warning: this is not guaranteed to be accurate as sometimes we can't 
1243
        be sure: for example with vfat mounted on unix, or a windows sftp
1244
        server."""
1245
        # TODO: Perhaps return a e.g. TransportCharacteristics that can answer
1246
        # several questions about the transport.
1247
        return False
1248
2485.8.37 by Vincent Ladeuil
Fix merge multiple connections. Test suite *not* passing (sftp
1249
    def _reuse_for(self, other_base):
2485.8.43 by Vincent Ladeuil
Cleaning.
1250
        # This is really needed for ConnectedTransport only, but it's easier to
1251
        # have Transport refuses to be reused than testing that the reuse
1252
        # should be asked to ConnectedTransport only.
2485.8.37 by Vincent Ladeuil
Fix merge multiple connections. Test suite *not* passing (sftp
1253
        return None
907.1.24 by John Arbash Meinel
Remote functionality work.
1254
2485.8.54 by Vincent Ladeuil
Refactor medium uses by making a distinction betweem shared and real medium.
1255
2485.8.55 by Vincent Ladeuil
Cleanup connection accessors.
1256
class _SharedConnection(object):
1257
    """A connection shared between several transports."""
1258
3104.4.1 by Andrew Bennetts
Fix paths sent by bzr+http client to correctly adjust for shared medium.
1259
    def __init__(self, connection=None, credentials=None, base=None):
2485.8.55 by Vincent Ladeuil
Cleanup connection accessors.
1260
        """Constructor.
1261
1262
        :param connection: An opaque object specific to each transport.
1263
1264
        :param credentials: An opaque object containing the credentials used to
1265
            create the connection.
1266
        """
1267
        self.connection = connection
1268
        self.credentials = credentials
3104.4.1 by Andrew Bennetts
Fix paths sent by bzr+http client to correctly adjust for shared medium.
1269
        self.base = base
2485.8.55 by Vincent Ladeuil
Cleanup connection accessors.
1270
1271
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1272
class ConnectedTransport(Transport):
1273
    """A transport connected to a remote server.
1274
2485.8.28 by Vincent Ladeuil
Further simplifications and doc updates.
1275
    This class provide the basis to implement transports that need to connect
1276
    to a remote server.
1277
1278
    Host and credentials are available as private attributes, cloning preserves
1279
    them and share the underlying, protocol specific, connection.
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1280
    """
1281
2485.8.59 by Vincent Ladeuil
Update from review comments.
1282
    def __init__(self, base, _from_transport=None):
2485.8.28 by Vincent Ladeuil
Further simplifications and doc updates.
1283
        """Constructor.
1284
2485.8.62 by Vincent Ladeuil
From review comments, fix typos and deprecate some functions.
1285
        The caller should ensure that _from_transport points at the same host
1286
        as the new base.
1287
2485.8.28 by Vincent Ladeuil
Further simplifications and doc updates.
1288
        :param base: transport root URL
1289
2485.8.59 by Vincent Ladeuil
Update from review comments.
1290
        :param _from_transport: optional transport to build from. The built
2485.8.28 by Vincent Ladeuil
Further simplifications and doc updates.
1291
            transport will share the connection with this transport.
1292
        """
2485.8.59 by Vincent Ladeuil
Update from review comments.
1293
        if not base.endswith('/'):
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1294
            base += '/'
1295
        (self._scheme,
1296
         self._user, self._password,
1297
         self._host, self._port,
2485.8.47 by Vincent Ladeuil
Remove _initial_split_url hack.
1298
         self._path) = self._split_url(base)
2485.8.59 by Vincent Ladeuil
Update from review comments.
1299
        if _from_transport is not None:
2485.8.28 by Vincent Ladeuil
Further simplifications and doc updates.
1300
            # Copy the password as it does not appear in base and will be lost
2485.8.59 by Vincent Ladeuil
Update from review comments.
1301
            # otherwise. It can appear in the _split_url above if the user
1302
            # provided it on the command line. Otherwise, daughter classes will
1303
            # prompt the user for one when appropriate.
1304
            self._password = _from_transport._password
2485.8.25 by Vincent Ladeuil
Separate abspath from _remote_path, the intents are different.
1305
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1306
        base = self._unsplit_url(self._scheme,
1307
                                 self._user, self._password,
1308
                                 self._host, self._port,
2485.8.28 by Vincent Ladeuil
Further simplifications and doc updates.
1309
                                 self._path)
2485.8.25 by Vincent Ladeuil
Separate abspath from _remote_path, the intents are different.
1310
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1311
        super(ConnectedTransport, self).__init__(base)
2485.8.59 by Vincent Ladeuil
Update from review comments.
1312
        if _from_transport is None:
2485.8.55 by Vincent Ladeuil
Cleanup connection accessors.
1313
            self._shared_connection = _SharedConnection()
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1314
        else:
2485.8.59 by Vincent Ladeuil
Update from review comments.
1315
            self._shared_connection = _from_transport._shared_connection
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1316
2485.8.25 by Vincent Ladeuil
Separate abspath from _remote_path, the intents are different.
1317
    def clone(self, offset=None):
1318
        """Return a new transport with root at self.base + offset
1319
1320
        We leave the daughter classes take advantage of the hint
1321
        that it's a cloning not a raw creation.
1322
        """
1323
        if offset is None:
2485.8.59 by Vincent Ladeuil
Update from review comments.
1324
            return self.__class__(self.base, _from_transport=self)
2485.8.25 by Vincent Ladeuil
Separate abspath from _remote_path, the intents are different.
1325
        else:
2485.8.59 by Vincent Ladeuil
Update from review comments.
1326
            return self.__class__(self.abspath(offset), _from_transport=self)
2485.8.25 by Vincent Ladeuil
Separate abspath from _remote_path, the intents are different.
1327
2485.8.47 by Vincent Ladeuil
Remove _initial_split_url hack.
1328
    @staticmethod
1329
    def _split_url(url):
2485.8.28 by Vincent Ladeuil
Further simplifications and doc updates.
1330
        """
1331
        Extract the server address, the credentials and the path from the url.
1332
1333
        user, password, host and path should be quoted if they contain reserved
1334
        chars.
1335
1336
        :param url: an quoted url
1337
1338
        :return: (scheme, user, password, host, port, path) tuple, all fields
1339
            are unquoted.
1340
        """
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1341
        if isinstance(url, unicode):
1342
            raise errors.InvalidURL('should be ascii:\n%r' % url)
1343
        url = url.encode('utf-8')
1344
        (scheme, netloc, path, params,
1345
         query, fragment) = urlparse.urlparse(url, allow_fragments=False)
2485.8.25 by Vincent Ladeuil
Separate abspath from _remote_path, the intents are different.
1346
        user = password = host = port = None
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1347
        if '@' in netloc:
2485.8.25 by Vincent Ladeuil
Separate abspath from _remote_path, the intents are different.
1348
            user, host = netloc.split('@', 1)
1349
            if ':' in user:
1350
                user, password = user.split(':', 1)
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1351
                password = urllib.unquote(password)
2485.8.25 by Vincent Ladeuil
Separate abspath from _remote_path, the intents are different.
1352
            user = urllib.unquote(user)
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1353
        else:
1354
            host = netloc
1355
1356
        if ':' in host:
1357
            host, port = host.rsplit(':', 1)
1358
            try:
1359
                port = int(port)
1360
            except ValueError:
1361
                raise errors.InvalidURL('invalid port number %s in url:\n%s' %
1362
                                        (port, url))
2900.2.16 by Vincent Ladeuil
Make hhtp proxy aware of AuthenticationConfig (for password).
1363
        if host == '':
1364
            raise errors.InvalidURL('Host empty in: %s' % url)
1365
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1366
        host = urllib.unquote(host)
2485.8.28 by Vincent Ladeuil
Further simplifications and doc updates.
1367
        path = urllib.unquote(path)
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1368
2485.8.25 by Vincent Ladeuil
Separate abspath from _remote_path, the intents are different.
1369
        return (scheme, user, password, host, port, path)
1370
2485.8.47 by Vincent Ladeuil
Remove _initial_split_url hack.
1371
    @staticmethod
1372
    def _unsplit_url(scheme, user, password, host, port, path):
2485.8.28 by Vincent Ladeuil
Further simplifications and doc updates.
1373
        """
1374
        Build the full URL for the given already URL encoded path.
1375
1376
        user, password, host and path will be quoted if they contain reserved
1377
        chars.
1378
1379
        :param scheme: protocol
1380
1381
        :param user: login
1382
1383
        :param password: associated password
1384
1385
        :param host: the server address
1386
1387
        :param port: the associated port
1388
1389
        :param path: the absolute path on the server
1390
1391
        :return: The corresponding URL.
1392
        """
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1393
        netloc = urllib.quote(host)
1394
        if user is not None:
1395
            # Note that we don't put the password back even if we
1396
            # have one so that it doesn't get accidentally
1397
            # exposed.
1398
            netloc = '%s@%s' % (urllib.quote(user), netloc)
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
1399
        if port is not None:
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1400
            netloc = '%s:%d' % (netloc, port)
2485.8.28 by Vincent Ladeuil
Further simplifications and doc updates.
1401
        path = urllib.quote(path)
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1402
        return urlparse.urlunparse((scheme, netloc, path, None, None, None))
1403
1404
    def relpath(self, abspath):
2485.8.29 by Vincent Ladeuil
Cometic changes (and a typo).
1405
        """Return the local path portion from a given absolute path"""
1406
        scheme, user, password, host, port, path = self._split_url(abspath)
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1407
        error = []
1408
        if (scheme != self._scheme):
1409
            error.append('scheme mismatch')
1410
        if (user != self._user):
2485.8.25 by Vincent Ladeuil
Separate abspath from _remote_path, the intents are different.
1411
            error.append('user name mismatch')
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1412
        if (host != self._host):
1413
            error.append('host mismatch')
1414
        if (port != self._port):
1415
            error.append('port mismatch')
1416
        if not (path == self._path[:-1] or path.startswith(self._path)):
1417
            error.append('path mismatch')
1418
        if error:
1419
            extra = ', '.join(error)
1420
            raise errors.PathNotChild(abspath, self.base, extra=extra)
1421
        pl = len(self._path)
1422
        return path[pl:].strip('/')
1423
1424
    def abspath(self, relpath):
1425
        """Return the full url to the given relative path.
1426
        
1427
        :param relpath: the relative path urlencoded
2485.8.28 by Vincent Ladeuil
Further simplifications and doc updates.
1428
2485.8.25 by Vincent Ladeuil
Separate abspath from _remote_path, the intents are different.
1429
        :returns: the Unicode version of the absolute path for relpath.
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1430
        """
2485.8.25 by Vincent Ladeuil
Separate abspath from _remote_path, the intents are different.
1431
        relative = urlutils.unescape(relpath).encode('utf-8')
1432
        path = self._combine_paths(self._path, relative)
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1433
        return self._unsplit_url(self._scheme, self._user, self._password,
1434
                                 self._host, self._port,
2485.8.28 by Vincent Ladeuil
Further simplifications and doc updates.
1435
                                 path)
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1436
1437
    def _remote_path(self, relpath):
1438
        """Return the absolute path part of the url to the given relative path.
2485.8.28 by Vincent Ladeuil
Further simplifications and doc updates.
1439
1440
        This is the path that the remote server expect to receive in the
1441
        requests, daughter classes should redefine this method if needed and
1442
        use the result to build their requests.
1443
1444
        :param relpath: the path relative to the transport base urlencoded.
1445
1446
        :return: the absolute Unicode path on the server,
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1447
        """
1448
        relative = urlutils.unescape(relpath).encode('utf-8')
1449
        remote_path = self._combine_paths(self._path, relative)
1450
        return remote_path
1451
2485.8.54 by Vincent Ladeuil
Refactor medium uses by making a distinction betweem shared and real medium.
1452
    def _get_shared_connection(self):
1453
        """Get the object shared amongst cloned transports.
1454
1455
        This should be used only by classes that needs to extend the sharing
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
1456
        with objects other than transports.
2485.8.54 by Vincent Ladeuil
Refactor medium uses by making a distinction betweem shared and real medium.
1457
1458
        Use _get_connection to get the connection itself.
1459
        """
1460
        return self._shared_connection
2485.8.32 by Vincent Ladeuil
Keep credentials used at connection creation for reconnection purposes.
1461
1462
    def _set_connection(self, connection, credentials=None):
2485.8.34 by Vincent Ladeuil
Refactor mutiple connections detection and fix false positives. Only
1463
        """Record a newly created connection with its associated credentials.
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1464
2485.8.30 by Vincent Ladeuil
Implement reliable connection sharing.
1465
        Note: To ensure that connection is still shared after a temporary
1466
        failure and a new one needs to be created, daughter classes should
2485.8.34 by Vincent Ladeuil
Refactor mutiple connections detection and fix false positives. Only
1467
        always call this method to set the connection and do so each time a new
1468
        connection is created.
2485.8.32 by Vincent Ladeuil
Keep credentials used at connection creation for reconnection purposes.
1469
1470
        :param connection: An opaque object representing the connection used by
1471
            the daughter class.
1472
1473
        :param credentials: An opaque object representing the credentials
1474
            needed to create the connection.
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1475
        """
2485.8.55 by Vincent Ladeuil
Cleanup connection accessors.
1476
        self._shared_connection.connection = connection
1477
        self._shared_connection.credentials = credentials
2485.8.32 by Vincent Ladeuil
Keep credentials used at connection creation for reconnection purposes.
1478
1479
    def _get_connection(self):
2485.8.30 by Vincent Ladeuil
Implement reliable connection sharing.
1480
        """Returns the transport specific connection object."""
2485.8.55 by Vincent Ladeuil
Cleanup connection accessors.
1481
        return self._shared_connection.connection
2485.8.30 by Vincent Ladeuil
Implement reliable connection sharing.
1482
2485.8.32 by Vincent Ladeuil
Keep credentials used at connection creation for reconnection purposes.
1483
    def _get_credentials(self):
2485.8.34 by Vincent Ladeuil
Refactor mutiple connections detection and fix false positives. Only
1484
        """Returns the credentials used to establish the connection."""
2485.8.55 by Vincent Ladeuil
Cleanup connection accessors.
1485
        return self._shared_connection.credentials
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1486
2485.8.39 by Vincent Ladeuil
Add tests around connection reuse.
1487
    def _update_credentials(self, credentials):
1488
        """Update the credentials of the current connection.
1489
1490
        Some protocols can renegociate the credentials within a connection,
1491
        this method allows daughter classes to share updated credentials.
1492
        
1493
        :param credentials: the updated credentials.
1494
        """
1495
        # We don't want to call _set_connection here as we are only updating
1496
        # the credentials not creating a new connection.
2485.8.55 by Vincent Ladeuil
Cleanup connection accessors.
1497
        self._shared_connection.credentials = credentials
2485.8.39 by Vincent Ladeuil
Add tests around connection reuse.
1498
2485.8.37 by Vincent Ladeuil
Fix merge multiple connections. Test suite *not* passing (sftp
1499
    def _reuse_for(self, other_base):
1500
        """Returns a transport sharing the same connection if possible.
1501
1502
        Note: we share the connection if the expected credentials are the
1503
        same: (host, port, user). Some protocols may disagree and redefine the
1504
        criteria in daughter classes.
1505
1506
        Note: we don't compare the passwords here because other_base may have
1507
        been obtained from an existing transport.base which do not mention the
1508
        password.
1509
1510
        :param other_base: the URL we want to share the connection with.
1511
1512
        :return: A new transport or None if the connection cannot be shared.
1513
        """
2990.2.2 by Vincent Ladeuil
Detect invalid transport reuse attempts by catching invalid URLs.
1514
        try:
1515
            (scheme, user, password,
1516
             host, port, path) = self._split_url(other_base)
1517
        except errors.InvalidURL:
1518
            # No hope in trying to reuse an existing transport for an invalid
1519
            # URL
1520
            return None
1521
2485.8.37 by Vincent Ladeuil
Fix merge multiple connections. Test suite *not* passing (sftp
1522
        transport = None
2485.8.39 by Vincent Ladeuil
Add tests around connection reuse.
1523
        # Don't compare passwords, they may be absent from other_base or from
1524
        # self and they don't carry more information than user anyway.
2485.8.59 by Vincent Ladeuil
Update from review comments.
1525
        if (scheme == self._scheme
1526
            and user == self._user
1527
            and host == self._host
1528
            and port == self._port):
2485.8.37 by Vincent Ladeuil
Fix merge multiple connections. Test suite *not* passing (sftp
1529
            if not path.endswith('/'):
1530
                # This normally occurs at __init__ time, but it's easier to do
2485.8.39 by Vincent Ladeuil
Add tests around connection reuse.
1531
                # it now to avoid creating two transports for the same base.
2485.8.37 by Vincent Ladeuil
Fix merge multiple connections. Test suite *not* passing (sftp
1532
                path += '/'
1533
            if self._path  == path:
1534
                # shortcut, it's really the same transport
1535
                return self
1536
            # We don't call clone here because the intent is different: we
1537
            # build a new transport on a different base (which may be totally
1538
            # unrelated) but we share the connection.
2485.8.59 by Vincent Ladeuil
Update from review comments.
1539
            transport = self.__class__(other_base, _from_transport=self)
2485.8.37 by Vincent Ladeuil
Fix merge multiple connections. Test suite *not* passing (sftp
1540
        return transport
1541
1542
2687.2.1 by Martin Pool
Rename upcoming release from 0.19 to 0.90
1543
@deprecated_function(zero_ninety)
2485.8.62 by Vincent Ladeuil
From review comments, fix typos and deprecate some functions.
1544
def urlescape(relpath):
1545
    urlutils.escape(relpath)
2687.2.1 by Martin Pool
Rename upcoming release from 0.19 to 0.90
1546
1547
1548
@deprecated_function(zero_ninety)
2485.8.62 by Vincent Ladeuil
From review comments, fix typos and deprecate some functions.
1549
def urlunescape(url):
1550
    urlutils.unescape(url)
2485.8.19 by Vincent Ladeuil
Add a new ConnectedTransport class refactored from [s]ftp and http.
1551
2485.8.37 by Vincent Ladeuil
Fix merge multiple connections. Test suite *not* passing (sftp
1552
# We try to recognize an url lazily (ignoring user, password, etc)
1553
_urlRE = re.compile(r'^(?P<proto>[^:/\\]+)://(?P<rest>.*)$')
1685.1.9 by John Arbash Meinel
Updated LocalTransport so that it's base is now a URL rather than a local path. This helps consistency with all other functions. To do so, I added local_abspath() which returns the local path, and local_path_to/from_url
1554
2476.3.8 by Vincent Ladeuil
Mark transports that need to be instrumented or refactored to check
1555
def get_transport(base, possible_transports=None):
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
1556
    """Open a transport to access a URL or directory.
1557
2476.3.5 by Vincent Ladeuil
Naive implementation of transport reuse by Transport.get_transport().
1558
    :param base: either a URL or a directory name.
2485.8.37 by Vincent Ladeuil
Fix merge multiple connections. Test suite *not* passing (sftp
1559
1560
    :param transports: optional reusable transports list. If not None, created
2485.8.59 by Vincent Ladeuil
Update from review comments.
1561
        transports will be added to the list.
2485.8.37 by Vincent Ladeuil
Fix merge multiple connections. Test suite *not* passing (sftp
1562
1563
    :return: A new transport optionally sharing its connection with one of
2485.8.59 by Vincent Ladeuil
Update from review comments.
1564
        possible_transports.
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
1565
    """
907.1.13 by John Arbash Meinel
Fixed bzr root.
1566
    if base is None:
1685.1.11 by John Arbash Meinel
Not all of the registered transports use :// as part of their path, specifically memory:/
1567
        base = '.'
1843.1.1 by John Arbash Meinel
Update get_transport to raise a nicer error which includes dependency info
1568
    last_err = None
3251.3.1 by Aaron Bentley
Add support for directory services
1569
    from bzrlib.directory_service import directories
1570
    base = directories.dereference(base)
1843.1.1 by John Arbash Meinel
Update get_transport to raise a nicer error which includes dependency info
1571
1685.1.33 by John Arbash Meinel
Be more of a Nazi about URLs not being unicode
1572
    def convert_path_to_url(base, error_str):
1573
        m = _urlRE.match(base)
1574
        if m:
1575
            # This looks like a URL, but we weren't able to 
1576
            # instantiate it as such raise an appropriate error
2485.8.38 by Vincent Ladeuil
Finish sftp refactoring. Test suite passing.
1577
            # FIXME: we have a 'error_str' unused and we use last_err below
1843.1.1 by John Arbash Meinel
Update get_transport to raise a nicer error which includes dependency info
1578
            raise errors.UnsupportedProtocol(base, last_err)
1685.1.33 by John Arbash Meinel
Be more of a Nazi about URLs not being unicode
1579
        # This doesn't look like a protocol, consider it a local path
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
1580
        new_base = urlutils.local_path_to_url(base)
1908.3.1 by Carl Friedrich Bolz
Clean up some mutter() calls.
1581
        # mutter('converting os path %r => url %s', base, new_base)
1685.1.33 by John Arbash Meinel
Be more of a Nazi about URLs not being unicode
1582
        return new_base
1583
1584
    # Catch any URLs which are passing Unicode rather than ASCII
1585
    try:
1586
        base = base.encode('ascii')
1587
    except UnicodeError:
1588
        # Only local paths can be Unicode
1589
        base = convert_path_to_url(base,
1590
            'URLs must be properly escaped (protocol: %s)')
2476.3.5 by Vincent Ladeuil
Naive implementation of transport reuse by Transport.get_transport().
1591
1592
    transport = None
1551.18.10 by Aaron Bentley
get_transport appends to possible_transports if it's an empty list
1593
    if possible_transports is not None:
2476.3.8 by Vincent Ladeuil
Mark transports that need to be instrumented or refactored to check
1594
        for t in possible_transports:
2485.8.37 by Vincent Ladeuil
Fix merge multiple connections. Test suite *not* passing (sftp
1595
            t_same_connection = t._reuse_for(base)
1596
            if t_same_connection is not None:
1597
                # Add only new transports
1598
                if t_same_connection not in possible_transports:
1599
                    possible_transports.append(t_same_connection)
1600
                return t_same_connection
1601
1602
    for proto, factory_list in transport_list_registry.iteritems():
1603
        if proto is not None and base.startswith(proto):
1604
            transport, last_err = _try_transport_factories(base, factory_list)
1605
            if transport:
1551.18.10 by Aaron Bentley
get_transport appends to possible_transports if it's an empty list
1606
                if possible_transports is not None:
2485.8.37 by Vincent Ladeuil
Fix merge multiple connections. Test suite *not* passing (sftp
1607
                    assert transport not in possible_transports
1608
                    possible_transports.append(transport)
1609
                return transport
1610
2485.8.43 by Vincent Ladeuil
Cleaning.
1611
    # We tried all the different protocols, now try one last time
1612
    # as a local protocol
2485.8.37 by Vincent Ladeuil
Fix merge multiple connections. Test suite *not* passing (sftp
1613
    base = convert_path_to_url(base, 'Unsupported protocol: %s')
1614
2485.8.43 by Vincent Ladeuil
Cleaning.
1615
    # The default handler is the filesystem handler, stored as protocol None
2485.8.37 by Vincent Ladeuil
Fix merge multiple connections. Test suite *not* passing (sftp
1616
    factory_list = transport_list_registry.get(None)
1617
    transport, last_err = _try_transport_factories(base, factory_list)
1618
2476.3.5 by Vincent Ladeuil
Naive implementation of transport reuse by Transport.get_transport().
1619
    return transport
1620
1621
2485.8.37 by Vincent Ladeuil
Fix merge multiple connections. Test suite *not* passing (sftp
1622
def _try_transport_factories(base, factory_list):
1623
    last_err = None
1624
    for factory in factory_list:
1625
        try:
1626
            return factory.get_obj()(base), None
1627
        except errors.DependencyNotPresent, e:
1628
            mutter("failed to instantiate transport %r for %r: %r" %
1629
                    (factory, base, e))
1630
            last_err = e
1631
            continue
1632
    return None, last_err
1633
1634
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
1635
def do_catching_redirections(action, transport, redirected):
2164.2.21 by Vincent Ladeuil
Take bundles into account.
1636
    """Execute an action with given transport catching redirections.
1637
1638
    This is a facility provided for callers needing to follow redirections
2164.2.25 by Vincent Ladeuil
Fix typos noticed by Aaron.
1639
    silently. The silence is relative: it is the caller responsability to
2164.2.21 by Vincent Ladeuil
Take bundles into account.
1640
    inform the user about each redirection or only inform the user of a user
1641
    via the exception parameter.
1642
1643
    :param action: A callable, what the caller want to do while catching
1644
                  redirections.
1645
    :param transport: The initial transport used.
1646
    :param redirected: A callable receiving the redirected transport and the 
1647
                  RedirectRequested exception.
1648
1649
    :return: Whatever 'action' returns
1650
    """
1651
    MAX_REDIRECTIONS = 8
1652
1653
    # If a loop occurs, there is little we can do. So we don't try to detect
1654
    # them, just getting out if too much redirections occurs. The solution
1655
    # is outside: where the loop is defined.
1656
    for redirections in range(MAX_REDIRECTIONS):
1657
        try:
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
1658
            return action(transport)
2164.2.21 by Vincent Ladeuil
Take bundles into account.
1659
        except errors.RedirectRequested, e:
1660
            redirection_notice = '%s is%s redirected to %s' % (
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
1661
                e.source, e.permanently, e.target)
1662
            transport = redirected(transport, e, redirection_notice)
2164.2.21 by Vincent Ladeuil
Take bundles into account.
1663
    else:
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
1664
        # Loop exited without resolving redirect ? Either the
1665
        # user has kept a very very very old reference or a loop
2164.2.25 by Vincent Ladeuil
Fix typos noticed by Aaron.
1666
        # occurred in the redirections.  Nothing we can cure here:
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
1667
        # tell the user. Note that as the user has been informed
1668
        # about each redirection (it is the caller responsibility
1669
        # to do that in redirected via the provided
1670
        # redirection_notice). The caller may provide more
2164.2.25 by Vincent Ladeuil
Fix typos noticed by Aaron.
1671
        # information if needed (like what file or directory we
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
1672
        # were trying to act upon when the redirection loop
2164.2.25 by Vincent Ladeuil
Fix typos noticed by Aaron.
1673
        # occurred).
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
1674
        raise errors.TooManyRedirections
2164.2.21 by Vincent Ladeuil
Take bundles into account.
1675
1676
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1677
class Server(object):
1530.1.21 by Robert Collins
Review feedback fixes.
1678
    """A Transport Server.
1679
    
1680
    The Server interface provides a server for a given transport. We use
1681
    these servers as loopback testing tools. For any given transport the
1682
    Servers it provides must either allow writing, or serve the contents
1683
    of os.getcwdu() at the time setUp is called.
1684
    
1685
    Note that these are real servers - they must implement all the things
1686
    that we want bzr transports to take advantage of.
1687
    """
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1688
1689
    def setUp(self):
1690
        """Setup the server to service requests."""
1691
1692
    def tearDown(self):
1693
        """Remove the server and cleanup any resources it owns."""
1694
1695
    def get_url(self):
1530.1.21 by Robert Collins
Review feedback fixes.
1696
        """Return a url for this server.
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1697
        
1698
        If the transport does not represent a disk directory (i.e. it is 
1530.1.21 by Robert Collins
Review feedback fixes.
1699
        a database like svn, or a memory only transport, it should return
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1700
        a connection to a newly established resource for this Server.
1530.1.21 by Robert Collins
Review feedback fixes.
1701
        Otherwise it should return a url that will provide access to the path
1702
        that was os.getcwdu() when setUp() was called.
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1703
        
1704
        Subsequent calls will return the same resource.
1705
        """
1706
        raise NotImplementedError
1707
1530.1.9 by Robert Collins
Test bogus urls with http in the new infrastructure.
1708
    def get_bogus_url(self):
2018.5.104 by Andrew Bennetts
Completely rework chrooted transports.
1709
        """Return a url for this protocol, that will fail to connect.
1710
        
1711
        This may raise NotImplementedError to indicate that this server cannot
1712
        provide bogus urls.
1713
        """
1530.1.9 by Robert Collins
Test bogus urls with http in the new infrastructure.
1714
        raise NotImplementedError
1715
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1716
1185.16.81 by mbp at sourcefrog
[merge] robert
1717
# None is the default transport, for things with no url scheme
2241.2.9 by ghigo
add the 'file://' prefix to the urlspec topic
1718
register_transport_proto('file://',
1719
            help="Access using the standard filesystem (default)")
1185.16.79 by Martin Pool
Load transports when they're first used.
1720
register_lazy_transport('file://', 'bzrlib.transport.local', 'LocalTransport')
2241.2.3 by ghigo
removed the the registration of the 'None' transport, instead we use the set_default_transport function
1721
transport_list_registry.set_default_transport("file://")
2241.2.4 by ghigo
removed commented line
1722
2241.2.5 by ghigo
add the topics transport
1723
register_transport_proto('sftp://',
2919.2.1 by John Arbash Meinel
Register netloc protocols as soon as the protocol is registered.
1724
            help="Access using SFTP (most SSH servers provide SFTP).",
1725
            register_netloc=True)
1185.16.79 by Martin Pool
Load transports when they're first used.
1726
register_lazy_transport('sftp://', 'bzrlib.transport.sftp', 'SFTPTransport')
2164.2.7 by v.ladeuil+lp at free
First implementation of transport hints.
1727
# Decorated http transport
2241.2.5 by ghigo
add the topics transport
1728
register_transport_proto('http+urllib://',
2241.2.11 by ghigo
On the basis of Robert Collins and John Arbash Meinel
1729
#                help="Read-only access of branches exported on the web."
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
1730
                         register_netloc=True)
1540.3.23 by Martin Pool
Allow urls like http+pycurl://host/ to use a particular impl
1731
register_lazy_transport('http+urllib://', 'bzrlib.transport.http._urllib',
1540.3.26 by Martin Pool
[merge] bzr.dev; pycurl not updated for readv yet
1732
                        'HttpTransport_urllib')
2241.2.5 by ghigo
add the topics transport
1733
register_transport_proto('https+urllib://',
2241.2.11 by ghigo
On the basis of Robert Collins and John Arbash Meinel
1734
#                help="Read-only access of branches exported on the web using SSL."
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
1735
                         register_netloc=True)
1540.3.23 by Martin Pool
Allow urls like http+pycurl://host/ to use a particular impl
1736
register_lazy_transport('https+urllib://', 'bzrlib.transport.http._urllib',
1540.3.26 by Martin Pool
[merge] bzr.dev; pycurl not updated for readv yet
1737
                        'HttpTransport_urllib')
2241.2.5 by ghigo
add the topics transport
1738
register_transport_proto('http+pycurl://',
2241.2.11 by ghigo
On the basis of Robert Collins and John Arbash Meinel
1739
#                help="Read-only access of branches exported on the web."
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
1740
                         register_netloc=True)
1540.3.26 by Martin Pool
[merge] bzr.dev; pycurl not updated for readv yet
1741
register_lazy_transport('http+pycurl://', 'bzrlib.transport.http._pycurl',
1742
                        'PyCurlTransport')
2241.2.5 by ghigo
add the topics transport
1743
register_transport_proto('https+pycurl://',
2241.2.11 by ghigo
On the basis of Robert Collins and John Arbash Meinel
1744
#                help="Read-only access of branches exported on the web using SSL."
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
1745
                         register_netloc=True)
1540.3.26 by Martin Pool
[merge] bzr.dev; pycurl not updated for readv yet
1746
register_lazy_transport('https+pycurl://', 'bzrlib.transport.http._pycurl',
1747
                        'PyCurlTransport')
2164.2.7 by v.ladeuil+lp at free
First implementation of transport hints.
1748
# Default http transports (last declared wins (if it can be imported))
2241.2.5 by ghigo
add the topics transport
1749
register_transport_proto('http://',
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
1750
                 help="Read-only access of branches exported on the web.")
2241.2.5 by ghigo
add the topics transport
1751
register_transport_proto('https://',
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
1752
            help="Read-only access of branches exported on the web using SSL.")
1540.3.26 by Martin Pool
[merge] bzr.dev; pycurl not updated for readv yet
1753
register_lazy_transport('http://', 'bzrlib.transport.http._urllib',
1754
                        'HttpTransport_urllib')
1755
register_lazy_transport('https://', 'bzrlib.transport.http._urllib',
1756
                        'HttpTransport_urllib')
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
1757
register_lazy_transport('http://', 'bzrlib.transport.http._pycurl',
1758
                        'PyCurlTransport')
1759
register_lazy_transport('https://', 'bzrlib.transport.http._pycurl',
1760
                        'PyCurlTransport')
2241.2.4 by ghigo
removed commented line
1761
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
1762
register_transport_proto('ftp://', help="Access using passive FTP.")
1185.36.4 by Daniel Silverstone
Add FTP transport
1763
register_lazy_transport('ftp://', 'bzrlib.transport.ftp', 'FtpTransport')
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
1764
register_transport_proto('aftp://', help="Access using active FTP.")
1185.36.4 by Daniel Silverstone
Add FTP transport
1765
register_lazy_transport('aftp://', 'bzrlib.transport.ftp', 'FtpTransport')
2241.2.4 by ghigo
removed commented line
1766
2241.2.1 by ghigo
Add the TransportRegistry class
1767
register_transport_proto('memory://')
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
1768
register_lazy_transport('memory://', 'bzrlib.transport.memory',
1769
                        'MemoryTransport')
2745.5.3 by Robert Collins
* Move transport logging into a new transport class
1770
1771
# chroots cannot be implicitly accessed, they must be explicitly created:
2241.2.1 by ghigo
Add the TransportRegistry class
1772
register_transport_proto('chroot+')
2241.3.6 by ghigo
Upgraded to the latest bzr.dev
1773
2241.2.5 by ghigo
add the topics transport
1774
register_transport_proto('readonly+',
2241.2.11 by ghigo
On the basis of Robert Collins and John Arbash Meinel
1775
#              help="This modifier converts any transport to be readonly."
1776
            )
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
1777
register_lazy_transport('readonly+', 'bzrlib.transport.readonly',
1778
                        'ReadonlyTransportDecorator')
2555.3.8 by Martin Pool
Add new BrokenRenameTransportDecorator
1779
2617.4.5 by Robert Collins
Reinstate the fakenfs+ decorator registration.
1780
register_transport_proto('fakenfs+')
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
1781
register_lazy_transport('fakenfs+', 'bzrlib.transport.fakenfs',
1782
                        'FakeNFSTransportDecorator')
2617.4.5 by Robert Collins
Reinstate the fakenfs+ decorator registration.
1783
2745.5.3 by Robert Collins
* Move transport logging into a new transport class
1784
register_transport_proto('trace+')
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
1785
register_lazy_transport('trace+', 'bzrlib.transport.trace',
1786
                        'TransportTraceDecorator')
2745.5.3 by Robert Collins
* Move transport logging into a new transport class
1787
2617.4.1 by Robert Collins
Add a new transport decorator unlistable+ for testing.
1788
register_transport_proto('unlistable+')
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
1789
register_lazy_transport('unlistable+', 'bzrlib.transport.unlistable',
1790
                        'UnlistableTransportDecorator')
2555.3.8 by Martin Pool
Add new BrokenRenameTransportDecorator
1791
1792
register_transport_proto('brokenrename+')
1793
register_lazy_transport('brokenrename+', 'bzrlib.transport.brokenrename',
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
1794
                        'BrokenRenameTransportDecorator')
2555.3.8 by Martin Pool
Add new BrokenRenameTransportDecorator
1795
2241.2.1 by ghigo
Add the TransportRegistry class
1796
register_transport_proto('vfat+')
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1797
register_lazy_transport('vfat+',
1608.2.4 by Martin Pool
[broken] Add FakeFVATTransport
1798
                        'bzrlib.transport.fakevfat',
1799
                        'FakeVFATTransportDecorator')
2919.2.1 by John Arbash Meinel
Register netloc protocols as soon as the protocol is registered.
1800
1801
# These two schemes were registered, but don't seem to have an actual transport
1802
# protocol registered
1803
for scheme in ['ssh', 'bzr+loopback']:
2919.2.2 by John Arbash Meinel
fix a simple typo
1804
    register_urlparse_netloc_protocol(scheme)
2919.2.1 by John Arbash Meinel
Register netloc protocols as soon as the protocol is registered.
1805
del scheme
1806
2241.2.5 by ghigo
add the topics transport
1807
register_transport_proto('bzr://',
2811.1.1 by Andrew Bennetts
Cherrypick fix proposed for 0.90.
1808
            help="Fast access using the Bazaar smart server.",
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
1809
                         register_netloc=True)
2241.2.5 by ghigo
add the topics transport
1810
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
1811
register_lazy_transport('bzr://', 'bzrlib.transport.remote',
2413.2.1 by Andrew Bennetts
Rename Smart.*Transport classes to RemoteTransport, RemoteTCPTransport, etc.
1812
                        'RemoteTCPTransport')
2241.2.5 by ghigo
add the topics transport
1813
register_transport_proto('bzr+http://',
2241.2.11 by ghigo
On the basis of Robert Collins and John Arbash Meinel
1814
#                help="Fast access using the Bazaar smart server over HTTP."
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
1815
                         register_netloc=True)
1816
register_lazy_transport('bzr+http://', 'bzrlib.transport.remote',
2413.2.1 by Andrew Bennetts
Rename Smart.*Transport classes to RemoteTransport, RemoteTCPTransport, etc.
1817
                        'RemoteHTTPTransport')
2651.1.1 by John Ferlito
bzr+https support
1818
register_transport_proto('bzr+https://',
1819
#                help="Fast access using the Bazaar smart server over HTTPS."
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
1820
                         register_netloc=True)
2651.1.1 by John Ferlito
bzr+https support
1821
register_lazy_transport('bzr+https://',
1822
                        'bzrlib.transport.remote',
1823
                        'RemoteHTTPTransport')
2241.2.5 by ghigo
add the topics transport
1824
register_transport_proto('bzr+ssh://',
2919.2.1 by John Arbash Meinel
Register netloc protocols as soon as the protocol is registered.
1825
            help="Fast access using the Bazaar smart server over SSH.",
1826
            register_netloc=True)
3004.2.1 by Vincent Ladeuil
Fix 150860 by leaving port as user specified it.
1827
register_lazy_transport('bzr+ssh://', 'bzrlib.transport.remote',
2413.2.1 by Andrew Bennetts
Rename Smart.*Transport classes to RemoteTransport, RemoteTCPTransport, etc.
1828
                        'RemoteSSHTransport')