/brz/remove-bazaar

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