/brz/remove-bazaar

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