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