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