~bzr-pqm/bzr/bzr.dev

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