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