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