~bzr-pqm/bzr/bzr.dev

2245.8.2 by Martin Pool
doc
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.11.19 by John Arbash Meinel
Testing put and append, also testing agaist file-like objects as well as strings.
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1185.11.19 by John Arbash Meinel
Testing put and append, also testing agaist file-like objects as well as strings.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.11.19 by John Arbash Meinel
Testing put and append, also testing agaist file-like objects as well as strings.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1540.3.1 by Martin Pool
First-cut implementation of pycurl. Substantially faster than using urllib.
16
1185.11.19 by John Arbash Meinel
Testing put and append, also testing agaist file-like objects as well as strings.
17
"""Transport is an abstraction layer to handle file access.
18
19
The abstraction is to allow access from the local filesystem, as well
20
as remote (such as http or sftp).
1540.3.12 by Martin Pool
Multiple transports can be registered for any protocol, and they are
21
22
Transports are constructed from a string, being a URL or (as a degenerate
23
case) a local filesystem path.  This is typically the top directory of
24
a bzrdir, repository, or similar object we are interested in working with.
25
The Transport returned has methods to read, write and manipulate files within
26
it.
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
27
"""
28
1996.3.6 by John Arbash Meinel
Find a few places that weren't importing their dependencies.
29
from cStringIO import StringIO
30
import re
31
import sys
32
33
from bzrlib.lazy_import import lazy_import
34
lazy_import(globals(), """
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
35
import errno
1594.2.17 by Robert Collins
Better readv coalescing, now with test, and progress during knit index reading.
36
from collections import deque
1530.1.1 by Robert Collins
Minimal infrastructure to test TransportTestProviderAdapter.
37
from copy import deepcopy
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
38
from stat import S_ISDIR
1996.3.6 by John Arbash Meinel
Find a few places that weren't importing their dependencies.
39
import unittest
1685.1.70 by Wouter van Heyst
working on get_parent, set_parent and relative urls, broken
40
import urllib
1636.1.1 by Robert Collins
Fix calling relpath() and abspath() on transports at their root.
41
import urlparse
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
42
import warnings
1530.1.1 by Robert Collins
Minimal infrastructure to test TransportTestProviderAdapter.
43
1725.2.3 by Robert Collins
Remove import of pumpfile from inner loop of commit.
44
import bzrlib
1955.3.6 by John Arbash Meinel
Lots of deprecation warnings, but no errors
45
from bzrlib import (
46
    errors,
47
    osutils,
48
    symbol_versioning,
49
    urlutils,
50
    )
1996.3.6 by John Arbash Meinel
Find a few places that weren't importing their dependencies.
51
""")
52
1955.3.6 by John Arbash Meinel
Lots of deprecation warnings, but no errors
53
from bzrlib.symbol_versioning import (
54
        deprecated_passed,
55
        deprecated_method,
56
        deprecated_function,
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
57
        DEPRECATED_PARAMETER,
1955.3.6 by John Arbash Meinel
Lots of deprecation warnings, but no errors
58
        zero_eight,
59
        zero_eleven,
60
        )
2164.2.21 by Vincent Ladeuil
Take bundles into account.
61
from bzrlib.trace import (
62
    note,
63
    mutter,
64
    warning,
65
    )
2241.2.1 by ghigo
Add the TransportRegistry class
66
from bzrlib import registry
2018.5.104 by Andrew Bennetts
Completely rework chrooted transports.
67
68
1530.1.11 by Robert Collins
Push the transport permutations list into each transport module allowing for automatic testing of new modules that are registered as transports.
69
def _get_protocol_handlers():
1540.3.12 by Martin Pool
Multiple transports can be registered for any protocol, and they are
70
    """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
71
    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.
72
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
73
1530.1.11 by Robert Collins
Push the transport permutations list into each transport module allowing for automatic testing of new modules that are registered as transports.
74
def _set_protocol_handlers(new_handlers):
75
    """Replace the current protocol handlers dictionary.
76
77
    WARNING this will remove all build in protocols. Use with care.
78
    """
2241.2.3 by ghigo
removed the the registration of the 'None' transport, instead we use the set_default_transport function
79
    global transport_list_registry
80
    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.
81
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
82
1540.3.12 by Martin Pool
Multiple transports can be registered for any protocol, and they are
83
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
84
    global transport_list_registry
85
    transport_list_registry = TransportListRegistry()
1540.3.12 by Martin Pool
Multiple transports can be registered for any protocol, and they are
86
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
87
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.
88
def _get_transport_modules():
89
    """Return a list of the modules providing transports."""
90
    modules = set()
2241.2.3 by ghigo
removed the the registration of the 'None' transport, instead we use the set_default_transport function
91
    for prefix, factory_list in transport_list_registry.iteritems():
1540.3.12 by Martin Pool
Multiple transports can be registered for any protocol, and they are
92
        for factory in factory_list:
2241.2.2 by ghigo
Create the TransportList class
93
            if hasattr(factory, "_module_name"):
94
                modules.add(factory._module_name)
1540.3.12 by Martin Pool
Multiple transports can be registered for any protocol, and they are
95
            else:
2241.2.2 by ghigo
Create the TransportList class
96
                modules.add(factory._obj.__module__)
2018.5.104 by Andrew Bennetts
Completely rework chrooted transports.
97
    # Add chroot directly, because there is not handler registered for it.
98
    modules.add('bzrlib.transport.chroot')
1530.1.19 by Robert Collins
Make transport test adapter tests reliable.
99
    result = list(modules)
100
    result.sort()
101
    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.
102
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
103
2241.2.3 by ghigo
removed the the registration of the 'None' transport, instead we use the set_default_transport function
104
class TransportListRegistry(registry.Registry):
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
105
    """A registry which simplifies tracking available Transports.
106
107
    A registration of a new protocol requires two step:
108
    1) register the prefix with the function register_transport( )
109
    2) register the protocol provider with the function
110
    register_transport_provider( ) ( and the "lazy" variant )
111
112
    This in needed because:
113
    a) a single provider can support multple protcol ( like the ftp
114
    privider which supports both the ftp:// and the aftp:// protocols )
115
    b) a single protocol can have multiple providers ( like the http://
116
    protocol which is supported by both the urllib and pycurl privider )
117
    """
118
2241.2.3 by ghigo
removed the the registration of the 'None' transport, instead we use the set_default_transport function
119
    def register_transport_provider(self, key, obj):
120
        self.get(key).insert(0, registry._ObjectGetter(obj))
121
122
    def register_lazy_transport_provider(self, key, module_name, member_name):
123
        self.get(key).insert(0, 
2241.2.1 by ghigo
Add the TransportRegistry class
124
                registry._LazyObjectGetter(module_name, member_name))
125
126
    def register_transport(self, key, help=None, info=None):
2241.2.3 by ghigo
removed the the registration of the 'None' transport, instead we use the set_default_transport function
127
        self.register(key, [], help, info)
2241.2.1 by ghigo
Add the TransportRegistry class
128
129
    def set_default_transport(self, key=None):
130
        """Return either 'key' or the default key if key is None"""
131
        self._default_key = key
132
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
133
2241.2.3 by ghigo
removed the the registration of the 'None' transport, instead we use the set_default_transport function
134
transport_list_registry = TransportListRegistry( )
2241.2.1 by ghigo
Add the TransportRegistry class
135
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
136
2241.2.1 by ghigo
Add the TransportRegistry class
137
def register_transport_proto(prefix, help=None, info=None):
2241.2.3 by ghigo
removed the the registration of the 'None' transport, instead we use the set_default_transport function
138
    transport_list_registry.register_transport(prefix, help, info)
2241.2.1 by ghigo
Add the TransportRegistry class
139
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
140
2241.2.1 by ghigo
Add the TransportRegistry class
141
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
142
    if not prefix in transport_list_registry:
2241.2.2 by ghigo
Create the TransportList class
143
        register_transport_proto(prefix)
2241.2.3 by ghigo
removed the the registration of the 'None' transport, instead we use the set_default_transport function
144
    transport_list_registry.register_lazy_transport_provider(prefix, module, classname)
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
145
146
2241.2.1 by ghigo
Add the TransportRegistry class
147
def register_transport(prefix, klass, override=DEPRECATED_PARAMETER):
2241.2.3 by ghigo
removed the the registration of the 'None' transport, instead we use the set_default_transport function
148
    if not prefix in transport_list_registry:
2241.2.2 by ghigo
Create the TransportList class
149
        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
150
    transport_list_registry.register_transport_provider(prefix, klass)
2241.2.1 by ghigo
Add the TransportRegistry class
151
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
152
1636.1.2 by Robert Collins
More review fixen to the relpath at '/' fixes.
153
def register_urlparse_netloc_protocol(protocol):
1636.1.1 by Robert Collins
Fix calling relpath() and abspath() on transports at their root.
154
    """Ensure that protocol is setup to be used with urlparse netloc parsing."""
155
    if protocol not in urlparse.uses_netloc:
156
        urlparse.uses_netloc.append(protocol)
157
2241.3.4 by ghigo
Updates on the basis of John Arbash Meinel comments
158
2241.3.5 by ghigo
update to the latest bzr.dev
159
def unregister_transport(scheme, factory):
160
    """Unregister a transport."""
161
    l = transport_list_registry.get(scheme)
162
    for i in l:
163
        o = i.get_obj( )
164
        if o == factory:
165
            transport_list_registry.get(scheme).remove(i)
166
            break
167
    if len(l) == 0:
168
        transport_list_registry.remove(scheme)
169
170
171
1707.3.4 by John Arbash Meinel
Moved most of sftp.split_url into a Transport function.
172
def split_url(url):
1685.1.69 by Wouter van Heyst
merge bzr.dev 1740
173
    # TODO: jam 20060606 urls should only be ascii, or they should raise InvalidURL
1707.3.4 by John Arbash Meinel
Moved most of sftp.split_url into a Transport function.
174
    if isinstance(url, unicode):
175
        url = url.encode('utf-8')
176
    (scheme, netloc, path, params,
177
     query, fragment) = urlparse.urlparse(url, allow_fragments=False)
178
    username = password = host = port = None
179
    if '@' in netloc:
180
        username, host = netloc.split('@', 1)
181
        if ':' in username:
182
            username, password = username.split(':', 1)
183
            password = urllib.unquote(password)
184
        username = urllib.unquote(username)
185
    else:
186
        host = netloc
187
188
    if ':' in host:
189
        host, port = host.rsplit(':', 1)
190
        try:
191
            port = int(port)
192
        except ValueError:
193
            # TODO: Should this be ConnectionError?
1910.15.8 by Andrew Bennetts
Put url in 'invalid port number' message on a new line.
194
            raise errors.TransportError(
195
                'invalid port number %s in url:\n%s' % (port, url))
1707.3.4 by John Arbash Meinel
Moved most of sftp.split_url into a Transport function.
196
    host = urllib.unquote(host)
197
198
    path = urllib.unquote(path)
199
200
    return (scheme, username, password, host, port, path)
201
202
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
203
class _CoalescedOffset(object):
204
    """A data container for keeping track of coalesced offsets."""
205
206
    __slots__ = ['start', 'length', 'ranges']
207
208
    def __init__(self, start, length, ranges):
209
        self.start = start
210
        self.length = length
211
        self.ranges = ranges
212
213
    def __cmp__(self, other):
214
        return cmp((self.start, self.length, self.ranges),
215
                   (other.start, other.length, other.ranges))
216
217
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
218
class Transport(object):
219
    """This class encapsulates methods for retrieving or putting a file
220
    from/to a storage location.
221
222
    Most functions have a _multi variant, which allows you to queue up
223
    multiple requests. They generally have a dumb base implementation 
224
    which just iterates over the arguments, but smart Transport
225
    implementations can do pipelining.
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
226
    In general implementations should support having a generator or a list
227
    as an argument (ie always iterate, never index)
1910.7.17 by Andrew Bennetts
Various cosmetic changes.
228
229
    :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.
230
    """
231
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
232
    # implementations can override this if it is more efficient
233
    # for them to combine larger read chunks together
1864.5.4 by John Arbash Meinel
play around with tuning the partial reads.
234
    _max_readv_combine = 50
1864.5.3 by John Arbash Meinel
Allow collapsing ranges even if they are just 'close'
235
    # It is better to read this much more data in order, rather
236
    # than doing another seek. Even for the local filesystem,
237
    # there is a benefit in just reading.
238
    # TODO: jam 20060714 Do some real benchmarking to figure out
239
    #       where the biggest benefit between combining reads and
1864.5.8 by John Arbash Meinel
Cleanup and NEWS
240
    #       and seeking is. Consider a runtime auto-tune.
1864.5.4 by John Arbash Meinel
play around with tuning the partial reads.
241
    _bytes_to_read_before_seek = 0
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
242
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
243
    def __init__(self, base):
907.1.50 by John Arbash Meinel
Removed encode/decode from Transport.put/get, added more exceptions that can be thrown.
244
        super(Transport, self).__init__()
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
245
        self.base = base
246
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
247
    def _translate_error(self, e, path, raise_generic=True):
248
        """Translate an IOError or OSError into an appropriate bzr error.
249
250
        This handles things like ENOENT, ENOTDIR, EEXIST, and EACCESS
251
        """
1963.2.6 by Robey Pointer
pychecker is on crack; go back to using 'is None'.
252
        if getattr(e, 'errno', None) is not None:
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
253
            if e.errno in (errno.ENOENT, errno.ENOTDIR):
254
                raise errors.NoSuchFile(path, extra=e)
1185.31.58 by John Arbash Meinel
Updating for new transport tests so that they pass on win32
255
            # I would rather use errno.EFOO, but there doesn't seem to be
256
            # any matching for 267
257
            # This is the error when doing a listdir on a file:
258
            # WindowsError: [Errno 267] The directory name is invalid
259
            if sys.platform == 'win32' and e.errno in (errno.ESRCH, 267):
260
                raise errors.NoSuchFile(path, extra=e)
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
261
            if e.errno == errno.EEXIST:
262
                raise errors.FileExists(path, extra=e)
263
            if e.errno == errno.EACCES:
264
                raise errors.PermissionDenied(path, extra=e)
1553.5.10 by Martin Pool
New DirectoryNotEmpty exception, and raise this from local and memory
265
            if e.errno == errno.ENOTEMPTY:
266
                raise errors.DirectoryNotEmpty(path, extra=e)
1558.10.1 by Aaron Bentley
Handle lockdirs over NFS properly
267
            if e.errno == errno.EBUSY:
268
                raise errors.ResourceBusy(path, extra=e)
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
269
        if raise_generic:
270
            raise errors.TransportError(orig_error=e)
271
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
272
    def clone(self, offset=None):
273
        """Return a new Transport object, cloned from the current location,
1185.11.6 by John Arbash Meinel
Made HttpTransport handle a request for a parent directory differently.
274
        using a subdirectory or parent directory. This allows connections 
275
        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.
276
        """
1540.3.1 by Martin Pool
First-cut implementation of pycurl. Substantially faster than using urllib.
277
        raise NotImplementedError(self.clone)
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
278
2475.3.2 by John Arbash Meinel
Add Transport.ensure_base()
279
    def ensure_base(self):
280
        """Ensure that the directory this transport references exists.
281
282
        This will create a directory if it doesn't exist.
283
        :return: True if the directory was created, False otherwise.
284
        """
285
        # The default implementation just uses "Easier to ask for forgiveness
286
        # than permission". We attempt to create the directory, and just
287
        # suppress a FileExists exception.
288
        try:
289
            self.mkdir('.')
290
        except errors.FileExists:
291
            return False
292
        else:
293
            return True
294
907.1.32 by John Arbash Meinel
Renaming is_remote to should_cache as it is more appropriate.
295
    def should_cache(self):
296
        """Return True if the data pulled across should be cached locally.
907.1.22 by John Arbash Meinel
Fixed some encoding issues, added is_remote function for Transport objects.
297
        """
907.1.32 by John Arbash Meinel
Renaming is_remote to should_cache as it is more appropriate.
298
        return False
907.1.22 by John Arbash Meinel
Fixed some encoding issues, added is_remote function for Transport objects.
299
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
300
    def _pump(self, from_file, to_file):
301
        """Most children will need to copy from one file-like 
302
        object or string to another one.
303
        This just gives them something easy to call.
304
        """
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
305
        assert not isinstance(from_file, basestring), \
306
            '_pump should only be called on files not %s' % (type(from_file,))
1996.3.6 by John Arbash Meinel
Find a few places that weren't importing their dependencies.
307
        osutils.pumpfile(from_file, to_file)
1948.3.8 by Vincent LADEUIL
_pump accepts strings finally :)
308
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
309
    def _get_total(self, multi):
310
        """Try to figure out how many entries are in multi,
311
        but if not possible, return None.
312
        """
313
        try:
314
            return len(multi)
315
        except TypeError: # We can't tell how many, because relpaths is a generator
316
            return None
317
318
    def _update_pb(self, pb, msg, count, total):
319
        """Update the progress bar based on the current count
320
        and total available, total may be None if it was
321
        not possible to determine.
322
        """
907.1.14 by John Arbash Meinel
Handling some transport functions which take only a single argument.
323
        if pb is None:
324
            return
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
325
        if total is None:
326
            pb.update(msg, count, count+1)
327
        else:
328
            pb.update(msg, count, total)
329
907.1.14 by John Arbash Meinel
Handling some transport functions which take only a single argument.
330
    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.
331
        """Iterate over all entries in multi, passing them to func,
332
        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.
333
334
        :param expand:  If True, the entries will be passed to the function
335
                        by expanding the tuple. If False, it will be passed
336
                        as a single parameter.
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
337
        """
338
        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.
339
        result = []
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
340
        count = 0
341
        for entry in multi:
342
            self._update_pb(pb, msg, count, total)
907.1.14 by John Arbash Meinel
Handling some transport functions which take only a single argument.
343
            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.
344
                result.append(func(*entry))
907.1.14 by John Arbash Meinel
Handling some transport functions which take only a single argument.
345
            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.
346
                result.append(func(entry))
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
347
            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.
348
        return tuple(result)
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
349
907.1.34 by John Arbash Meinel
Fixing append(), cleaning up function locations.
350
    def abspath(self, relpath):
351
        """Return the full url to the given relative path.
1910.16.6 by Andrew Bennetts
Update Transport.abspath docstring.
352
353
        :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.
354
        """
1442.1.44 by Robert Collins
Many transport related tweaks:
355
1910.16.2 by Andrew Bennetts
Reduce transport code duplication by creating a '_combine_paths' method to Transport.
356
        # XXX: Robert Collins 20051016 - is this really needed in the public
357
        # interface ?
1540.3.1 by Martin Pool
First-cut implementation of pycurl. Substantially faster than using urllib.
358
        raise NotImplementedError(self.abspath)
907.1.34 by John Arbash Meinel
Fixing append(), cleaning up function locations.
359
1910.16.2 by Andrew Bennetts
Reduce transport code duplication by creating a '_combine_paths' method to Transport.
360
    def _combine_paths(self, base_path, relpath):
361
        """Transform a Transport-relative path to a remote absolute path.
362
363
        This does not handle substitution of ~ but does handle '..' and '.'
364
        components.
365
366
        Examples::
367
1996.3.20 by John Arbash Meinel
[merge] bzr.dev 2063
368
            t._combine_paths('/home/sarah', 'project/foo')
369
                => '/home/sarah/project/foo'
370
            t._combine_paths('/home/sarah', '../../etc')
371
                => '/etc'
2070.3.2 by Andrew Bennetts
Merge from bzr.dev
372
            t._combine_paths('/home/sarah', '/etc')
373
                => '/etc'
1910.16.2 by Andrew Bennetts
Reduce transport code duplication by creating a '_combine_paths' method to Transport.
374
375
        :param base_path: urlencoded path for the transport root; typically a 
376
             URL but need not contain scheme/host/etc.
377
        :param relpath: relative url string for relative part of remote path.
378
        :return: urlencoded string for final path.
379
        """
380
        # FIXME: share the common code across more transports; variants of
381
        # this likely occur in http and sftp too.
382
        #
383
        # TODO: Also need to consider handling of ~, which might vary between
384
        # transports?
385
        if not isinstance(relpath, str):
386
            raise errors.InvalidURL("not a valid url: %r" % relpath)
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
387
        if relpath.startswith('/'):
388
            base_parts = []
389
        else:
390
            base_parts = base_path.split('/')
1910.16.2 by Andrew Bennetts
Reduce transport code duplication by creating a '_combine_paths' method to Transport.
391
        if len(base_parts) > 0 and base_parts[-1] == '':
392
            base_parts = base_parts[:-1]
393
        for p in relpath.split('/'):
394
            if p == '..':
395
                if len(base_parts) == 0:
396
                    # In most filesystems, a request for the parent
397
                    # of root, just returns root.
398
                    continue
399
                base_parts.pop()
400
            elif p == '.':
401
                continue # No-op
402
            elif p != '':
403
                base_parts.append(p)
404
        path = '/'.join(base_parts)
2070.3.1 by Andrew Bennetts
Fix memory_transport.abspath('/foo')
405
        if not path.startswith('/'):
406
            path = '/' + path
1910.16.2 by Andrew Bennetts
Reduce transport code duplication by creating a '_combine_paths' method to Transport.
407
        return path
408
907.1.34 by John Arbash Meinel
Fixing append(), cleaning up function locations.
409
    def relpath(self, abspath):
410
        """Return the local path portion from a given absolute path.
1442.1.44 by Robert Collins
Many transport related tweaks:
411
412
        This default implementation is not suitable for filesystems with
413
        aliasing, such as that given by symlinks, where a path may not 
414
        start with our base, but still be a relpath once aliasing is 
415
        resolved.
907.1.34 by John Arbash Meinel
Fixing append(), cleaning up function locations.
416
        """
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
417
        # TODO: This might want to use bzrlib.osutils.relpath
418
        #       but we have to watch out because of the prefix issues
1530.1.3 by Robert Collins
transport implementations now tested consistently.
419
        if not (abspath == self.base[:-1] or abspath.startswith(self.base)):
1185.31.44 by John Arbash Meinel
Cleaned up Exceptions for all transports.
420
            raise errors.PathNotChild(abspath, self.base)
1442.1.44 by Robert Collins
Many transport related tweaks:
421
        pl = len(self.base)
1530.1.3 by Robert Collins
transport implementations now tested consistently.
422
        return abspath[pl:].strip('/')
907.1.34 by John Arbash Meinel
Fixing append(), cleaning up function locations.
423
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
424
    def local_abspath(self, relpath):
425
        """Return the absolute path on the local filesystem.
426
427
        This function will only be defined for Transports which have a
428
        physical local filesystem representation.
429
        """
2018.18.4 by Martin Pool
Change Transport.local_abspath to raise NotLocalUrl, and test.
430
        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
431
432
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
433
    def has(self, relpath):
1442.1.44 by Robert Collins
Many transport related tweaks:
434
        """Does the file relpath exist?
435
        
436
        Note that some transports MAY allow querying on directories, but this
1553.5.66 by Martin Pool
doc
437
        is not part of the protocol.  In other words, the results of 
1786.1.8 by John Arbash Meinel
[merge] Johan Rydberg test updates
438
        t.has("a_directory_name") are undefined.
1910.7.17 by Andrew Bennetts
Various cosmetic changes.
439
440
        :rtype: bool
1442.1.44 by Robert Collins
Many transport related tweaks:
441
        """
1540.3.1 by Martin Pool
First-cut implementation of pycurl. Substantially faster than using urllib.
442
        raise NotImplementedError(self.has)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
443
907.1.36 by John Arbash Meinel
Moving the multi-get functionality higher up into the Branch class.
444
    def has_multi(self, relpaths, pb=None):
907.1.34 by John Arbash Meinel
Fixing append(), cleaning up function locations.
445
        """Return True/False for each entry in relpaths"""
446
        total = self._get_total(relpaths)
447
        count = 0
448
        for relpath in relpaths:
907.1.36 by John Arbash Meinel
Moving the multi-get functionality higher up into the Branch class.
449
            self._update_pb(pb, 'has', count, total)
907.1.34 by John Arbash Meinel
Fixing append(), cleaning up function locations.
450
            yield self.has(relpath)
451
            count += 1
452
1185.16.155 by John Arbash Meinel
Added a has_any function to the Transport API
453
    def has_any(self, relpaths):
454
        """Return True if any of the paths exist."""
455
        for relpath in relpaths:
456
            if self.has(relpath):
457
                return True
458
        return False
459
1442.1.44 by Robert Collins
Many transport related tweaks:
460
    def iter_files_recursive(self):
461
        """Iter the relative paths of files in the transports sub-tree.
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
462
463
        *NOTE*: This only lists *files*, not subdirectories!
1442.1.44 by Robert Collins
Many transport related tweaks:
464
        
465
        As with other listing functions, only some transports implement this,.
466
        you may check via is_listable to determine if it will.
467
        """
1530.1.4 by Robert Collins
integrate Memory tests into transport interface tests.
468
        raise errors.TransportNotPossible("This transport has not "
1530.1.21 by Robert Collins
Review feedback fixes.
469
                                          "implemented iter_files_recursive "
1530.1.4 by Robert Collins
integrate Memory tests into transport interface tests.
470
                                          "(but must claim to be listable "
471
                                          "to trigger this error).")
1442.1.44 by Robert Collins
Many transport related tweaks:
472
2164.2.15 by Vincent Ladeuil
Http redirections are not followed by default. Do not use hints
473
    def get(self, relpath):
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
474
        """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
475
476
        :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
477
        :rtype: File-like object.
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
478
        """
1540.3.1 by Martin Pool
First-cut implementation of pycurl. Substantially faster than using urllib.
479
        raise NotImplementedError(self.get)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
480
1955.3.3 by John Arbash Meinel
Implement and test 'get_bytes'
481
    def get_bytes(self, relpath):
482
        """Get a raw string of the bytes for a file at the given location.
483
484
        :param relpath: The relative path to the file
485
        """
486
        return self.get(relpath).read()
487
1910.19.2 by Andrew Bennetts
Add a new method ``Transport.get_smart_client()``. This is provided to allow
488
    def get_smart_client(self):
489
        """Return a smart client for this transport if possible.
490
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
491
        A smart client doesn't imply the presence of a smart server: it implies
492
        that the smart protocol can be tunnelled via this transport.
493
1910.19.2 by Andrew Bennetts
Add a new method ``Transport.get_smart_client()``. This is provided to allow
494
        :raises NoSmartServer: if no smart server client is available.
495
        """
496
        raise errors.NoSmartServer(self.base)
497
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
498
    def get_smart_medium(self):
499
        """Return a smart client medium for this transport if possible.
500
501
        A smart medium doesn't imply the presence of a smart server: it implies
502
        that the smart protocol can be tunnelled via this transport.
503
504
        :raises NoSmartMedium: if no smart server medium is available.
505
        """
506
        raise errors.NoSmartMedium(self)
507
1594.2.5 by Robert Collins
Readv patch from Johan Rydberg giving knits partial download support.
508
    def readv(self, relpath, offsets):
509
        """Get parts of the file at the given relative path.
510
511
        :offsets: A list of (offset, size) tuples.
512
        :return: A list or generator of (offset, data) tuples
513
        """
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
514
        if not offsets:
1594.2.16 by Robert Collins
Coalesce readv requests on file based transports.
515
            return
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
516
1864.5.7 by John Arbash Meinel
remove disable prefetch support
517
        fp = self.get(relpath)
2001.3.2 by John Arbash Meinel
Force all transports to raise ShortReadvError if they can
518
        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.
519
2001.3.2 by John Arbash Meinel
Force all transports to raise ShortReadvError if they can
520
    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.
521
        """An implementation of readv that uses fp.seek and fp.read.
522
523
        This uses _coalesce_offsets to issue larger reads and fewer seeks.
524
525
        :param fp: A file-like object that supports seek() and read(size)
526
        :param offsets: A list of offsets to be read from the given file.
527
        :return: yield (pos, data) tuples for each request
528
        """
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
529
        # We are going to iterate multiple times, we need a list
530
        offsets = list(offsets)
531
        sorted_offsets = sorted(offsets)
532
533
        # 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.
534
        offset_stack = iter(offsets)
535
        cur_offset_and_size = offset_stack.next()
1864.5.2 by John Arbash Meinel
always read in sorted order, and return in requested order, but only cache what is currently out of order
536
        coalesced = self._coalesce_offsets(sorted_offsets,
1864.5.3 by John Arbash Meinel
Allow collapsing ranges even if they are just 'close'
537
                               limit=self._max_readv_combine,
538
                               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
539
540
        # Cache the results, but only until they have been fulfilled
541
        data_map = {}
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
542
        for c_offset in coalesced:
1864.5.11 by John Arbash Meinel
Factor out the workhorse of Transport.readv() into a helper function, and re-use that function in sftp but with a non-prefetch file.
543
            # TODO: jam 20060724 it might be faster to not issue seek if 
544
            #       we are already at the right location. This should be
545
            #       benchmarked.
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
546
            fp.seek(c_offset.start)
547
            data = fp.read(c_offset.length)
2001.3.2 by John Arbash Meinel
Force all transports to raise ShortReadvError if they can
548
            if len(data) < c_offset.length:
549
                raise errors.ShortReadvError(relpath, c_offset.start,
2001.3.3 by John Arbash Meinel
review feedback: add the actual count written to ShortReadvError
550
                            c_offset.length, actual=len(data))
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
551
            for suboffset, subsize in c_offset.ranges:
552
                key = (c_offset.start+suboffset, subsize)
553
                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.
554
1864.5.8 by John Arbash Meinel
Cleanup and NEWS
555
            # Now that we've read some data, see if we can yield anything back
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
556
            while cur_offset_and_size in data_map:
557
                this_data = data_map.pop(cur_offset_and_size)
558
                yield cur_offset_and_size[0], this_data
559
                cur_offset_and_size = offset_stack.next()
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
560
561
    @staticmethod
1864.5.3 by John Arbash Meinel
Allow collapsing ranges even if they are just 'close'
562
    def _coalesce_offsets(offsets, limit, fudge_factor):
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
563
        """Yield coalesced offsets.
564
565
        With a long list of neighboring requests, combine them
566
        into a single large request, while retaining the original
567
        offsets.
568
        Turns  [(15, 10), (25, 10)] => [(15, 20, [(0, 10), (10, 10)])]
569
570
        :param offsets: A list of (start, length) pairs
571
        :param limit: Only combine a maximum of this many pairs
572
                      Some transports penalize multiple reads more than
573
                      others, and sometimes it is better to return early.
574
                      0 means no limit
1864.5.3 by John Arbash Meinel
Allow collapsing ranges even if they are just 'close'
575
        :param fudge_factor: All transports have some level of 'it is
576
                better to read some more data and throw it away rather 
577
                than seek', so collapse if we are 'close enough'
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
578
        :return: yield _CoalescedOffset objects, which have members for wher
579
                to start, how much to read, and how to split those 
580
                chunks back up
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
581
        """
582
        last_end = None
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
583
        cur = _CoalescedOffset(None, None, [])
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
584
585
        for start, size in offsets:
586
            end = start + size
587
            if (last_end is not None 
1864.5.3 by John Arbash Meinel
Allow collapsing ranges even if they are just 'close'
588
                and start <= last_end + fudge_factor
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
589
                and start >= cur.start
590
                and (limit <= 0 or len(cur.ranges) < limit)):
591
                cur.length = end - cur.start
592
                cur.ranges.append((start-cur.start, size))
1594.2.16 by Robert Collins
Coalesce readv requests on file based transports.
593
            else:
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
594
                if cur.start is not None:
595
                    yield cur
596
                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.
597
            last_end = end
598
1864.5.9 by John Arbash Meinel
Switch to returning an object to make the api more understandable.
599
        if cur.start is not None:
600
            yield cur
1864.5.1 by John Arbash Meinel
Change the readv combining algorithm for one that is easier to test.
601
602
        return
1594.2.5 by Robert Collins
Readv patch from Johan Rydberg giving knits partial download support.
603
907.1.50 by John Arbash Meinel
Removed encode/decode from Transport.put/get, added more exceptions that can be thrown.
604
    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.
605
        """Get a list of file-like objects, one for each entry in relpaths.
606
607
        :param relpaths: A list of relative paths.
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
608
        :param pb:  An optional ProgressBar for indicating percent done.
609
        :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.
610
        """
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
611
        # TODO: Consider having this actually buffer the requests,
612
        # in the default mode, it probably won't give worse performance,
613
        # and all children wouldn't have to implement buffering
907.1.16 by John Arbash Meinel
Fixing a few cut&paste typos.
614
        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.
615
        count = 0
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
616
        for relpath in relpaths:
907.1.16 by John Arbash Meinel
Fixing a few cut&paste typos.
617
            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.
618
            yield self.get(relpath)
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
619
            count += 1
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
620
1955.3.6 by John Arbash Meinel
Lots of deprecation warnings, but no errors
621
    @deprecated_method(zero_eleven)
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
622
    def put(self, relpath, f, mode=None):
1946.1.1 by John Arbash Meinel
Stub out the test and basic implementation for 'non_atomic_put'
623
        """Copy the file-like object into the location.
907.1.20 by John Arbash Meinel
Removed Transport.open(), making get + put encode/decode to utf-8
624
625
        :param relpath: Location to put the contents, relative to base.
1946.1.1 by John Arbash Meinel
Stub out the test and basic implementation for 'non_atomic_put'
626
        :param f:       File-like object.
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
627
        :param mode: The mode for the newly created file, 
628
                     None means just use the default
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
629
        """
1955.3.6 by John Arbash Meinel
Lots of deprecation warnings, but no errors
630
        if isinstance(f, str):
631
            return self.put_bytes(relpath, f, mode=mode)
632
        else:
633
            return self.put_file(relpath, f, mode=mode)
634
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
635
    def put_bytes(self, relpath, bytes, mode=None):
636
        """Atomically put the supplied bytes into the given location.
637
638
        :param relpath: The location to put the contents, relative to the
639
            transport base.
640
        :param bytes: A bytestring of data.
641
        :param mode: Create the file with the given mode.
642
        :return: None
643
        """
2414.1.3 by Andrew Bennetts
Fix test failures under 'python2.4 -O' ('python2.5 -O' was already passing).
644
        if not isinstance(bytes, str):
645
            raise AssertionError(
646
                'bytes must be a plain string, not %s' % type(bytes))
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
647
        return self.put_file(relpath, StringIO(bytes), mode=mode)
648
649
    def put_bytes_non_atomic(self, relpath, bytes, mode=None,
1946.2.12 by John Arbash Meinel
Add ability to pass a directory mode to non_atomic_put
650
                             create_parent_dir=False,
651
                             dir_mode=None):
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
652
        """Copy the string into the target location.
653
654
        This function is not strictly safe to use. See 
655
        Transport.put_bytes_non_atomic for more information.
656
657
        :param relpath: The remote location to put the contents.
658
        :param bytes:   A string object containing the raw bytes to write into
659
                        the target file.
660
        :param mode:    Possible access permissions for new file.
661
                        None means do not set remote permissions.
662
        :param create_parent_dir: If we cannot create the target file because
663
                        the parent directory does not exist, go ahead and
664
                        create it, and then try again.
1946.2.12 by John Arbash Meinel
Add ability to pass a directory mode to non_atomic_put
665
        :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
666
        """
2414.1.3 by Andrew Bennetts
Fix test failures under 'python2.4 -O' ('python2.5 -O' was already passing).
667
        if not isinstance(bytes, str):
668
            raise AssertionError(
669
                'bytes must be a plain string, not %s' % type(bytes))
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
670
        self.put_file_non_atomic(relpath, StringIO(bytes), mode=mode,
1946.2.12 by John Arbash Meinel
Add ability to pass a directory mode to non_atomic_put
671
                                 create_parent_dir=create_parent_dir,
672
                                 dir_mode=dir_mode)
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
673
1955.3.6 by John Arbash Meinel
Lots of deprecation warnings, but no errors
674
    def put_file(self, relpath, f, mode=None):
675
        """Copy the file-like object into the location.
676
677
        :param relpath: Location to put the contents, relative to base.
678
        :param f:       File-like object.
679
        :param mode: The mode for the newly created file,
680
                     None means just use the default.
681
        """
682
        # We would like to mark this as NotImplemented, but most likely
683
        # transports have defined it in terms of the old api.
684
        symbol_versioning.warn('Transport %s should implement put_file,'
685
                               ' rather than implementing put() as of'
686
                               ' version 0.11.'
687
                               % (self.__class__.__name__,),
688
                               DeprecationWarning)
689
        return self.put(relpath, f, mode=mode)
690
        #raise NotImplementedError(self.put_file)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
691
1955.3.27 by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions
692
    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
693
                            create_parent_dir=False,
694
                            dir_mode=None):
1946.1.1 by John Arbash Meinel
Stub out the test and basic implementation for 'non_atomic_put'
695
        """Copy the file-like object into the target location.
696
697
        This function is not strictly safe to use. It is only meant to
698
        be used when you already know that the target does not exist.
699
        It is not safe, because it will open and truncate the remote
700
        file. So there may be a time when the file has invalid contents.
701
702
        :param relpath: The remote location to put the contents.
703
        :param f:       File-like object.
704
        :param mode:    Possible access permissions for new file.
705
                        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
706
        :param create_parent_dir: If we cannot create the target file because
707
                        the parent directory does not exist, go ahead and
708
                        create it, and then try again.
1946.2.12 by John Arbash Meinel
Add ability to pass a directory mode to non_atomic_put
709
        :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'
710
        """
711
        # 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
712
        try:
1955.3.19 by John Arbash Meinel
rename non_atomic_put => non_atomic_put_file
713
            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
714
        except errors.NoSuchFile:
715
            if not create_parent_dir:
716
                raise
717
            parent_dir = osutils.dirname(relpath)
718
            if parent_dir:
1946.2.12 by John Arbash Meinel
Add ability to pass a directory mode to non_atomic_put
719
                self.mkdir(parent_dir, mode=dir_mode)
1955.3.19 by John Arbash Meinel
rename non_atomic_put => non_atomic_put_file
720
                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'
721
1955.3.7 by John Arbash Meinel
Fix the deprecation warnings in the transport tests themselves
722
    @deprecated_method(zero_eleven)
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
723
    def put_multi(self, files, mode=None, pb=None):
1530.1.3 by Robert Collins
transport implementations now tested consistently.
724
        """Put a set of files into the location.
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
725
726
        :param files: A list of tuples of relpath, file object [(path1, file1), (path2, file2),...]
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
727
        :param pb:  An optional ProgressBar for indicating percent done.
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
728
        :param mode: The mode for the newly created files
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
729
        :return: The number of files copied.
730
        """
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
731
        def _put(path, f):
1955.3.7 by John Arbash Meinel
Fix the deprecation warnings in the transport tests themselves
732
            if isinstance(f, str):
733
                self.put_bytes(path, f, mode=mode)
734
            else:
735
                self.put_file(path, f, mode=mode)
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
736
        return len(self._iterate_over(files, _put, pb, 'put', expand=True))
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
737
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
738
    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.
739
        """Create a directory at the given path."""
1540.3.1 by Martin Pool
First-cut implementation of pycurl. Substantially faster than using urllib.
740
        raise NotImplementedError(self.mkdir)
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
741
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
742
    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
743
        """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.
744
        def mkdir(path):
745
            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.
746
        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
747
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
748
    @deprecated_method(zero_eleven)
1752.2.31 by Martin Pool
[broken] some support for write operations over hpss
749
    def append(self, relpath, f, mode=None):
1955.3.2 by John Arbash Meinel
Implement and test 'Transport.append_bytes', cleanup the tests of plain append
750
        """Append the text in the file-like object to the supplied location.
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.
751
1955.3.2 by John Arbash Meinel
Implement and test 'Transport.append_bytes', cleanup the tests of plain append
752
        returns the length of relpath before the content was written to it.
1755.3.1 by Robert Collins
Tune the time to build our kernel_like tree : make LocalTransport.put faster, AtomicFile faster, LocalTransport.append faster.
753
        
754
        If the file does not exist, it is created with the supplied mode.
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
755
        """
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
756
        return self.append_file(relpath, f, mode=mode)
757
758
    def append_file(self, relpath, f, mode=None):
1910.7.18 by Andrew Bennetts
Merge from bzr.dev
759
        """Append bytes from a file-like object to a file at relpath.
760
761
        The file is created if it does not already exist.
762
763
        :param f: a file-like object of the bytes to append.
764
        :param mode: Unix mode for newly created files.  This is not used for
765
            existing files.
766
767
        :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
768
        """
769
        symbol_versioning.warn('Transport %s should implement append_file,'
770
                               ' rather than implementing append() as of'
771
                               ' version 0.11.'
772
                               % (self.__class__.__name__,),
773
                               DeprecationWarning)
774
        return self.append(relpath, f, mode=mode)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
775
1955.3.2 by John Arbash Meinel
Implement and test 'Transport.append_bytes', cleanup the tests of plain append
776
    def append_bytes(self, relpath, bytes, mode=None):
1910.7.18 by Andrew Bennetts
Merge from bzr.dev
777
        """Append bytes to a file at relpath.
778
779
        The file is created if it does not already exist.
780
781
        :type f: str
782
        :param f: a string of the bytes to append.
783
        :param mode: Unix mode for newly created files.  This is not used for
784
            existing files.
785
786
        :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
787
        """
788
        assert isinstance(bytes, str), \
789
            'bytes must be a plain string, not %s' % type(bytes)
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
790
        return self.append_file(relpath, StringIO(bytes), mode=mode)
1955.3.2 by John Arbash Meinel
Implement and test 'Transport.append_bytes', cleanup the tests of plain append
791
1185.11.19 by John Arbash Meinel
Testing put and append, also testing agaist file-like objects as well as strings.
792
    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.
793
        """Append the text in each file-like or string object to
794
        the supplied location.
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
795
796
        :param files: A set of (path, f) entries
797
        :param pb:  An optional ProgressBar for indicating percent done.
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
798
        """
1955.3.15 by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes
799
        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.
800
801
    def copy(self, rel_from, rel_to):
1530.1.3 by Robert Collins
transport implementations now tested consistently.
802
        """Copy the item at rel_from to the location at rel_to.
803
        
804
        Override this for efficiency if a specific transport can do it 
805
        faster than this default implementation.
806
        """
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
807
        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.
808
907.1.28 by John Arbash Meinel
Added pb to function that were missing, implemented a basic double-dispatch copy_to function.
809
    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.
810
        """Copy a bunch of entries.
811
        
812
        :param relpaths: A list of tuples of the form [(from, to), (from, to),...]
813
        """
814
        # This is the non-pipelined implementation, so that
815
        # implementors don't have to implement everything.
907.1.14 by John Arbash Meinel
Handling some transport functions which take only a single argument.
816
        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.
817
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
818
    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.
819
        """Copy a set of entries from self into another Transport.
820
821
        :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.
822
        :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
823
        TODO: This interface needs to be updated so that the target location
824
              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.
825
        """
826
        # The dummy implementation just does a simple get + put
827
        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
828
            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.
829
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.
830
        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.
831
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
832
    def copy_tree(self, from_relpath, to_relpath):
833
        """Copy a subtree from one relpath to another.
834
835
        If a faster implementation is available, specific transports should 
836
        implement it.
837
        """
838
        source = self.clone(from_relpath)
839
        self.mkdir(to_relpath)
840
        target = self.clone(to_relpath)
841
        files = []
842
        directories = ['.']
843
        while directories:
844
            dir = directories.pop()
845
            if dir != '.':
846
                target.mkdir(dir)
847
            for path in source.list_dir(dir):
848
                path = dir + '/' + path
849
                stat = source.stat(path)
850
                if S_ISDIR(stat.st_mode):
851
                    directories.append(path)
852
                else:
853
                    files.append(path)
854
        source.copy_to(files, target)
855
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
856
    def rename(self, rel_from, rel_to):
857
        """Rename a file or directory.
858
859
        This *must* fail if the destination is a nonempty directory - it must
860
        not automatically remove it.  It should raise DirectoryNotEmpty, or
861
        some other PathError if the case can't be specifically detected.
862
863
        If the destination is an empty directory or a file this function may
864
        either fail or succeed, depending on the underlying transport.  It
865
        should not attempt to remove the destination if overwriting is not the
866
        native transport behaviour.  If at all possible the transport should
867
        ensure that the rename either completes or not, without leaving the
868
        destination deleted and the new file not moved in place.
869
870
        This is intended mainly for use in implementing LockDir.
871
        """
872
        # transports may need to override this
1553.5.17 by Martin Pool
Transport.rename should be unimplemented in base class
873
        raise NotImplementedError(self.rename)
1553.5.13 by Martin Pool
New Transport.rename that mustn't overwrite
874
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
875
    def move(self, rel_from, rel_to):
1530.1.3 by Robert Collins
transport implementations now tested consistently.
876
        """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
877
878
        The destination is deleted if possible, even if it's a non-empty
879
        directory tree.
1530.1.3 by Robert Collins
transport implementations now tested consistently.
880
        
881
        If a transport can directly implement this it is suggested that
882
        it do so for efficiency.
883
        """
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
884
        if S_ISDIR(self.stat(rel_from).st_mode):
885
            self.copy_tree(rel_from, rel_to)
886
            self.delete_tree(rel_from)
887
        else:
888
            self.copy(rel_from, rel_to)
889
            self.delete(rel_from)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
890
907.1.28 by John Arbash Meinel
Added pb to function that were missing, implemented a basic double-dispatch copy_to function.
891
    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.
892
        """Move a bunch of entries.
893
        
894
        :param relpaths: A list of tuples of the form [(from1, to1), (from2, to2),...]
895
        """
907.1.14 by John Arbash Meinel
Handling some transport functions which take only a single argument.
896
        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.
897
898
    def move_multi_to(self, relpaths, rel_to):
899
        """Move a bunch of entries to a single location.
900
        This differs from move_multi in that you give a list of from, and
901
        a single destination, rather than multiple destinations.
902
903
        :param relpaths: A list of relative paths [from1, from2, from3, ...]
904
        :param rel_to: A directory where each entry should be placed.
905
        """
906
        # This is not implemented, because you need to do special tricks to
907
        # 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.
908
        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.
909
910
    def delete(self, relpath):
911
        """Delete the item at relpath"""
1540.3.1 by Martin Pool
First-cut implementation of pycurl. Substantially faster than using urllib.
912
        raise NotImplementedError(self.delete)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
913
907.1.28 by John Arbash Meinel
Added pb to function that were missing, implemented a basic double-dispatch copy_to function.
914
    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.
915
        """Queue up a bunch of deletes to be done.
916
        """
907.1.14 by John Arbash Meinel
Handling some transport functions which take only a single argument.
917
        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.
918
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
919
    def delete_tree(self, relpath):
920
        """Delete an entire tree. This may require a listable transport."""
921
        subtree = self.clone(relpath)
922
        files = []
923
        directories = ['.']
924
        pending_rmdirs = []
925
        while directories:
926
            dir = directories.pop()
927
            if dir != '.':
928
                pending_rmdirs.append(dir)
929
            for path in subtree.list_dir(dir):
930
                path = dir + '/' + path
931
                stat = subtree.stat(path)
932
                if S_ISDIR(stat.st_mode):
933
                    directories.append(path)
934
                else:
935
                    files.append(path)
936
        subtree.delete_multi(files)
937
        pending_rmdirs.reverse()
938
        for dir in pending_rmdirs:
939
            subtree.rmdir(dir)
940
        self.rmdir(relpath)
941
1534.5.7 by Robert Collins
Start factoring out the upgrade policy logic.
942
    def __repr__(self):
943
        return "<%s.%s url=%s>" % (self.__module__, self.__class__.__name__, self.base)
944
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
945
    def stat(self, relpath):
946
        """Return the stat information for a file.
947
        WARNING: This may not be implementable for all protocols, so use
948
        sparingly.
1442.1.44 by Robert Collins
Many transport related tweaks:
949
        NOTE: This returns an object with fields such as 'st_size'. It MAY
950
        or MAY NOT return the literal result of an os.stat() call, so all
951
        access should be via named fields.
952
        ALSO NOTE: Stats of directories may not be supported on some 
953
        transports.
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
954
        """
1540.3.1 by Martin Pool
First-cut implementation of pycurl. Substantially faster than using urllib.
955
        raise NotImplementedError(self.stat)
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
956
1534.4.15 by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports.
957
    def rmdir(self, relpath):
958
        """Remove a directory at the given path."""
959
        raise NotImplementedError
960
907.1.2 by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport.
961
    def stat_multi(self, relpaths, pb=None):
962
        """Stat multiple files and return the information.
963
        """
964
        #TODO:  Is it worth making this a generator instead of a
965
        #       returning a list?
966
        stats = []
967
        def gather(path):
968
            stats.append(self.stat(path))
969
907.1.14 by John Arbash Meinel
Handling some transport functions which take only a single argument.
970
        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.
971
        return stats
972
1400.1.1 by Robert Collins
implement a basic test for the ui branch command from http servers
973
    def listable(self):
974
        """Return True if this store supports listing."""
1540.3.1 by Martin Pool
First-cut implementation of pycurl. Substantially faster than using urllib.
975
        raise NotImplementedError(self.listable)
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
976
977
    def list_dir(self, relpath):
978
        """Return a list of all files at the given location.
979
        WARNING: many transports do not support this, so trying avoid using
980
        it if at all possible.
981
        """
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
982
        raise errors.TransportNotPossible("Transport %r has not "
1530.1.21 by Robert Collins
Review feedback fixes.
983
                                          "implemented list_dir "
1530.1.3 by Robert Collins
transport implementations now tested consistently.
984
                                          "(but must claim to be listable "
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
985
                                          "to trigger this error)."
986
                                          % (self))
907.1.1 by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer.
987
907.1.24 by John Arbash Meinel
Remote functionality work.
988
    def lock_read(self, relpath):
989
        """Lock the given file for shared (read) access.
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
990
991
        WARNING: many transports do not support this, so trying avoid using it.
992
        These methods may be removed in the future.
993
994
        Transports may raise TransportNotPossible if OS-level locks cannot be
995
        taken over this transport.  
907.1.24 by John Arbash Meinel
Remote functionality work.
996
997
        :return: A lock object, which should contain an unlock() function.
998
        """
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
999
        raise errors.TransportNotPossible("transport locks not supported on %s" % self)
907.1.24 by John Arbash Meinel
Remote functionality work.
1000
1001
    def lock_write(self, relpath):
1002
        """Lock the given file for exclusive (write) access.
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
1003
1004
        WARNING: many transports do not support this, so trying avoid using it.
1005
        These methods may be removed in the future.
1006
1007
        Transports may raise TransportNotPossible if OS-level locks cannot be
1008
        taken over this transport.
907.1.24 by John Arbash Meinel
Remote functionality work.
1009
1010
        :return: A lock object, which should contain an unlock() function.
1011
        """
1910.16.1 by Andrew Bennetts
lock_read and lock_write may raise TransportNotPossible.
1012
        raise errors.TransportNotPossible("transport locks not supported on %s" % self)
907.1.24 by John Arbash Meinel
Remote functionality work.
1013
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1014
    def is_readonly(self):
1015
        """Return true if this connection cannot be written to."""
1016
        return False
1017
1608.2.7 by Martin Pool
Rename supports_unix_modebits to _can_roundtrip_unix_modebits for clarity
1018
    def _can_roundtrip_unix_modebits(self):
1608.2.5 by Martin Pool
Add Transport.supports_unix_modebits, so tests can
1019
        """Return true if this transport can store and retrieve unix modebits.
1020
1021
        (For example, 0700 to make a directory owner-private.)
1022
        
1023
        Note: most callers will not want to switch on this, but should rather 
1024
        just try and set permissions and let them be either stored or not.
1025
        This is intended mainly for the use of the test suite.
1026
        
1027
        Warning: this is not guaranteed to be accurate as sometimes we can't 
1028
        be sure: for example with vfat mounted on unix, or a windows sftp
1029
        server."""
1030
        # TODO: Perhaps return a e.g. TransportCharacteristics that can answer
1031
        # several questions about the transport.
1032
        return False
1033
907.1.24 by John Arbash Meinel
Remote functionality work.
1034
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
1035
# jam 20060426 For compatibility we copy the functions here
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
1036
# TODO: The should be marked as deprecated
1037
urlescape = urlutils.escape
1038
urlunescape = urlutils.unescape
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
1039
_urlRE = re.compile(r'^(?P<proto>[^:/\\]+)://(?P<path>.*)$')
1040
1041
1393.2.4 by John Arbash Meinel
All tests pass.
1042
def get_transport(base):
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
1043
    """Open a transport to access a URL or directory.
1044
1045
    base is either a URL or a directory name.  
1046
    """
2241.3.6 by ghigo
Upgraded to the latest bzr.dev
1047
907.1.13 by John Arbash Meinel
Fixed bzr root.
1048
    if base is None:
1685.1.11 by John Arbash Meinel
Not all of the registered transports use :// as part of their path, specifically memory:/
1049
        base = '.'
1843.1.1 by John Arbash Meinel
Update get_transport to raise a nicer error which includes dependency info
1050
    last_err = None
1051
1685.1.33 by John Arbash Meinel
Be more of a Nazi about URLs not being unicode
1052
    def convert_path_to_url(base, error_str):
1053
        m = _urlRE.match(base)
1054
        if m:
1055
            # This looks like a URL, but we weren't able to 
1056
            # instantiate it as such raise an appropriate error
1843.1.1 by John Arbash Meinel
Update get_transport to raise a nicer error which includes dependency info
1057
            raise errors.UnsupportedProtocol(base, last_err)
1685.1.33 by John Arbash Meinel
Be more of a Nazi about URLs not being unicode
1058
        # This doesn't look like a protocol, consider it a local path
1685.1.45 by John Arbash Meinel
Moved url functions into bzrlib.urlutils
1059
        new_base = urlutils.local_path_to_url(base)
1908.3.1 by Carl Friedrich Bolz
Clean up some mutter() calls.
1060
        # mutter('converting os path %r => url %s', base, new_base)
1685.1.33 by John Arbash Meinel
Be more of a Nazi about URLs not being unicode
1061
        return new_base
1062
1063
    # Catch any URLs which are passing Unicode rather than ASCII
1064
    try:
1065
        base = base.encode('ascii')
1066
    except UnicodeError:
1067
        # Only local paths can be Unicode
1068
        base = convert_path_to_url(base,
1069
            'URLs must be properly escaped (protocol: %s)')
1685.1.11 by John Arbash Meinel
Not all of the registered transports use :// as part of their path, specifically memory:/
1070
    
2241.2.3 by ghigo
removed the the registration of the 'None' transport, instead we use the set_default_transport function
1071
    for proto, factory_list in transport_list_registry.iteritems():
1685.1.11 by John Arbash Meinel
Not all of the registered transports use :// as part of their path, specifically memory:/
1072
        if proto is not None and base.startswith(proto):
1843.1.1 by John Arbash Meinel
Update get_transport to raise a nicer error which includes dependency info
1073
            t, last_err = _try_transport_factories(base, factory_list)
1685.1.11 by John Arbash Meinel
Not all of the registered transports use :// as part of their path, specifically memory:/
1074
            if t:
1075
                return t
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
1076
1685.1.33 by John Arbash Meinel
Be more of a Nazi about URLs not being unicode
1077
    # We tried all the different protocols, now try one last time
1078
    # as a local protocol
1079
    base = convert_path_to_url(base, 'Unsupported protocol: %s')
1685.1.11 by John Arbash Meinel
Not all of the registered transports use :// as part of their path, specifically memory:/
1080
1540.3.12 by Martin Pool
Multiple transports can be registered for any protocol, and they are
1081
    # The default handler is the filesystem handler, stored as protocol None
2241.2.1 by ghigo
Add the TransportRegistry class
1082
    return _try_transport_factories(base,
2241.2.3 by ghigo
removed the the registration of the 'None' transport, instead we use the set_default_transport function
1083
                    transport_list_registry.get(None))[0]
2241.2.1 by ghigo
Add the TransportRegistry class
1084
                                                   
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
1085
def do_catching_redirections(action, transport, redirected):
2164.2.21 by Vincent Ladeuil
Take bundles into account.
1086
    """Execute an action with given transport catching redirections.
1087
1088
    This is a facility provided for callers needing to follow redirections
2164.2.25 by Vincent Ladeuil
Fix typos noticed by Aaron.
1089
    silently. The silence is relative: it is the caller responsability to
2164.2.21 by Vincent Ladeuil
Take bundles into account.
1090
    inform the user about each redirection or only inform the user of a user
1091
    via the exception parameter.
1092
1093
    :param action: A callable, what the caller want to do while catching
1094
                  redirections.
1095
    :param transport: The initial transport used.
1096
    :param redirected: A callable receiving the redirected transport and the 
1097
                  RedirectRequested exception.
1098
1099
    :return: Whatever 'action' returns
1100
    """
1101
    MAX_REDIRECTIONS = 8
1102
1103
    # If a loop occurs, there is little we can do. So we don't try to detect
1104
    # them, just getting out if too much redirections occurs. The solution
1105
    # is outside: where the loop is defined.
1106
    for redirections in range(MAX_REDIRECTIONS):
1107
        try:
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
1108
            return action(transport)
2164.2.21 by Vincent Ladeuil
Take bundles into account.
1109
        except errors.RedirectRequested, e:
1110
            redirection_notice = '%s is%s redirected to %s' % (
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
1111
                e.source, e.permanently, e.target)
1112
            transport = redirected(transport, e, redirection_notice)
2164.2.21 by Vincent Ladeuil
Take bundles into account.
1113
    else:
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
1114
        # Loop exited without resolving redirect ? Either the
1115
        # user has kept a very very very old reference or a loop
2164.2.25 by Vincent Ladeuil
Fix typos noticed by Aaron.
1116
        # occurred in the redirections.  Nothing we can cure here:
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
1117
        # tell the user. Note that as the user has been informed
1118
        # about each redirection (it is the caller responsibility
1119
        # to do that in redirected via the provided
1120
        # redirection_notice). The caller may provide more
2164.2.25 by Vincent Ladeuil
Fix typos noticed by Aaron.
1121
        # information if needed (like what file or directory we
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
1122
        # were trying to act upon when the redirection loop
2164.2.25 by Vincent Ladeuil
Fix typos noticed by Aaron.
1123
        # occurred).
2164.2.22 by Vincent Ladeuil
Take Aaron's review comments into account.
1124
        raise errors.TooManyRedirections
2164.2.21 by Vincent Ladeuil
Take bundles into account.
1125
1126
1540.3.12 by Martin Pool
Multiple transports can be registered for any protocol, and they are
1127
def _try_transport_factories(base, factory_list):
1843.1.1 by John Arbash Meinel
Update get_transport to raise a nicer error which includes dependency info
1128
    last_err = None
1540.3.12 by Martin Pool
Multiple transports can be registered for any protocol, and they are
1129
    for factory in factory_list:
1130
        try:
2241.2.1 by ghigo
Add the TransportRegistry class
1131
            return factory.get_obj()(base), None
1996.3.6 by John Arbash Meinel
Find a few places that weren't importing their dependencies.
1132
        except errors.DependencyNotPresent, e:
1540.3.12 by Martin Pool
Multiple transports can be registered for any protocol, and they are
1133
            mutter("failed to instantiate transport %r for %r: %r" %
1134
                    (factory, base, e))
1843.1.1 by John Arbash Meinel
Update get_transport to raise a nicer error which includes dependency info
1135
            last_err = e
1540.3.12 by Martin Pool
Multiple transports can be registered for any protocol, and they are
1136
            continue
1843.1.1 by John Arbash Meinel
Update get_transport to raise a nicer error which includes dependency info
1137
    return None, last_err
1185.16.81 by mbp at sourcefrog
[merge] robert
1138
1185.16.78 by Martin Pool
- load paramiko sftp transport by default
1139
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1140
class Server(object):
1530.1.21 by Robert Collins
Review feedback fixes.
1141
    """A Transport Server.
1142
    
1143
    The Server interface provides a server for a given transport. We use
1144
    these servers as loopback testing tools. For any given transport the
1145
    Servers it provides must either allow writing, or serve the contents
1146
    of os.getcwdu() at the time setUp is called.
1147
    
1148
    Note that these are real servers - they must implement all the things
1149
    that we want bzr transports to take advantage of.
1150
    """
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1151
1152
    def setUp(self):
1153
        """Setup the server to service requests."""
1154
1155
    def tearDown(self):
1156
        """Remove the server and cleanup any resources it owns."""
1157
1158
    def get_url(self):
1530.1.21 by Robert Collins
Review feedback fixes.
1159
        """Return a url for this server.
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1160
        
1161
        If the transport does not represent a disk directory (i.e. it is 
1530.1.21 by Robert Collins
Review feedback fixes.
1162
        a database like svn, or a memory only transport, it should return
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1163
        a connection to a newly established resource for this Server.
1530.1.21 by Robert Collins
Review feedback fixes.
1164
        Otherwise it should return a url that will provide access to the path
1165
        that was os.getcwdu() when setUp() was called.
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1166
        
1167
        Subsequent calls will return the same resource.
1168
        """
1169
        raise NotImplementedError
1170
1530.1.9 by Robert Collins
Test bogus urls with http in the new infrastructure.
1171
    def get_bogus_url(self):
2018.5.104 by Andrew Bennetts
Completely rework chrooted transports.
1172
        """Return a url for this protocol, that will fail to connect.
1173
        
1174
        This may raise NotImplementedError to indicate that this server cannot
1175
        provide bogus urls.
1176
        """
1530.1.9 by Robert Collins
Test bogus urls with http in the new infrastructure.
1177
        raise NotImplementedError
1178
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1179
1530.1.1 by Robert Collins
Minimal infrastructure to test TransportTestProviderAdapter.
1180
class TransportTestProviderAdapter(object):
1530.1.21 by Robert Collins
Review feedback fixes.
1181
    """A tool to generate a suite testing all transports for a single test.
1182
1183
    This is done by copying the test once for each transport and injecting
1184
    the transport_class and transport_server classes into each copy. Each copy
1185
    is also given a new id() to make it easy to identify.
1186
    """
1530.1.1 by Robert Collins
Minimal infrastructure to test TransportTestProviderAdapter.
1187
1188
    def adapt(self, test):
1996.3.6 by John Arbash Meinel
Find a few places that weren't importing their dependencies.
1189
        result = unittest.TestSuite()
1530.1.1 by Robert Collins
Minimal infrastructure to test TransportTestProviderAdapter.
1190
        for klass, server_factory in self._test_permutations():
1191
            new_test = deepcopy(test)
1192
            new_test.transport_class = klass
1193
            new_test.transport_server = server_factory
1530.1.3 by Robert Collins
transport implementations now tested consistently.
1194
            def make_new_test_id():
1195
                new_id = "%s(%s)" % (new_test.id(), server_factory.__name__)
1196
                return lambda: new_id
1197
            new_test.id = make_new_test_id()
1530.1.1 by Robert Collins
Minimal infrastructure to test TransportTestProviderAdapter.
1198
            result.addTest(new_test)
1199
        return result
1200
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.
1201
    def get_transport_test_permutations(self, module):
1202
        """Get the permutations module wants to have tested."""
1963.2.6 by Robey Pointer
pychecker is on crack; go back to using 'is None'.
1203
        if getattr(module, 'get_test_permutations', None) is None:
2477.1.7 by Martin Pool
test_transport must provide get_test_permutations
1204
            raise AssertionError("transport module %s doesn't provide get_test_permutations()"
1540.3.6 by Martin Pool
[merge] update from bzr.dev
1205
                    % module.__name__)
2477.1.7 by Martin Pool
test_transport must provide get_test_permutations
1206
            ##warning("transport module %s doesn't provide get_test_permutations()"
1207
            ##       % module.__name__)
1540.3.6 by Martin Pool
[merge] update from bzr.dev
1208
            return []
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.
1209
        return module.get_test_permutations()
1210
1530.1.1 by Robert Collins
Minimal infrastructure to test TransportTestProviderAdapter.
1211
    def _test_permutations(self):
1212
        """Return a list of the klass, server_factory pairs to test."""
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.
1213
        result = []
1214
        for module in _get_transport_modules():
1534.7.70 by abentley
Fix bug when no paramiko
1215
            try:
1216
                result.extend(self.get_transport_test_permutations(reduce(getattr, 
1217
                    (module).split('.')[1:],
1185.71.1 by John Arbash Meinel
Allow selftest to run, even if we can't load a transport.
1218
                     __import__(module))))
1185.62.24 by John Arbash Meinel
Changing the exception that sftp.py throws when it can't find paramiko, so that the test suite can handle it.
1219
            except errors.DependencyNotPresent, e:
1220
                # Continue even if a dependency prevents us 
1221
                # from running this test
1534.7.70 by abentley
Fix bug when no paramiko
1222
                pass
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.
1223
        return result
1594.2.24 by Robert Collins
Make use of the transaction finalisation warning support to implement in-knit caching.
1224
1225
1226
class TransportLogger(object):
1227
    """Adapt a transport to get clear logging data on api calls.
1228
    
1229
    Feel free to extend to log whatever calls are of interest.
1230
    """
1231
1232
    def __init__(self, adapted):
1233
        self._adapted = adapted
1234
        self._calls = []
1235
2164.2.15 by Vincent Ladeuil
Http redirections are not followed by default. Do not use hints
1236
    def get(self, name):
1594.2.24 by Robert Collins
Make use of the transaction finalisation warning support to implement in-knit caching.
1237
        self._calls.append((name,))
2164.2.15 by Vincent Ladeuil
Http redirections are not followed by default. Do not use hints
1238
        return self._adapted.get(name)
1594.2.24 by Robert Collins
Make use of the transaction finalisation warning support to implement in-knit caching.
1239
1240
    def __getattr__(self, name):
1241
        """Thunk all undefined access through to self._adapted."""
1242
        # raise AttributeError, name 
1243
        return getattr(self._adapted, name)
1244
1245
    def readv(self, name, offsets):
1246
        self._calls.append((name, offsets))
1247
        return self._adapted.readv(name, offsets)
1530.1.1 by Robert Collins
Minimal infrastructure to test TransportTestProviderAdapter.
1248
1249
1185.16.81 by mbp at sourcefrog
[merge] robert
1250
# None is the default transport, for things with no url scheme
2241.2.9 by ghigo
add the 'file://' prefix to the urlspec topic
1251
register_transport_proto('file://',
1252
            help="Access using the standard filesystem (default)")
1185.16.79 by Martin Pool
Load transports when they're first used.
1253
register_lazy_transport('file://', 'bzrlib.transport.local', 'LocalTransport')
2241.2.3 by ghigo
removed the the registration of the 'None' transport, instead we use the set_default_transport function
1254
transport_list_registry.set_default_transport("file://")
2241.2.4 by ghigo
removed commented line
1255
2241.2.5 by ghigo
add the topics transport
1256
register_transport_proto('sftp://',
1257
            help="Access using SFTP (most SSH servers provide SFTP).")
1185.16.79 by Martin Pool
Load transports when they're first used.
1258
register_lazy_transport('sftp://', 'bzrlib.transport.sftp', 'SFTPTransport')
2164.2.7 by v.ladeuil+lp at free
First implementation of transport hints.
1259
# Decorated http transport
2241.2.5 by ghigo
add the topics transport
1260
register_transport_proto('http+urllib://',
2241.2.11 by ghigo
On the basis of Robert Collins and John Arbash Meinel
1261
#                help="Read-only access of branches exported on the web."
1262
            )
1540.3.23 by Martin Pool
Allow urls like http+pycurl://host/ to use a particular impl
1263
register_lazy_transport('http+urllib://', 'bzrlib.transport.http._urllib',
1540.3.26 by Martin Pool
[merge] bzr.dev; pycurl not updated for readv yet
1264
                        'HttpTransport_urllib')
2241.2.5 by ghigo
add the topics transport
1265
register_transport_proto('https+urllib://',
2241.2.11 by ghigo
On the basis of Robert Collins and John Arbash Meinel
1266
#                help="Read-only access of branches exported on the web using SSL."
1267
            )
1540.3.23 by Martin Pool
Allow urls like http+pycurl://host/ to use a particular impl
1268
register_lazy_transport('https+urllib://', 'bzrlib.transport.http._urllib',
1540.3.26 by Martin Pool
[merge] bzr.dev; pycurl not updated for readv yet
1269
                        'HttpTransport_urllib')
2241.2.5 by ghigo
add the topics transport
1270
register_transport_proto('http+pycurl://',
2241.2.11 by ghigo
On the basis of Robert Collins and John Arbash Meinel
1271
#                help="Read-only access of branches exported on the web."
1272
            )
1540.3.26 by Martin Pool
[merge] bzr.dev; pycurl not updated for readv yet
1273
register_lazy_transport('http+pycurl://', 'bzrlib.transport.http._pycurl',
1274
                        'PyCurlTransport')
2241.2.5 by ghigo
add the topics transport
1275
register_transport_proto('https+pycurl://',
2241.2.11 by ghigo
On the basis of Robert Collins and John Arbash Meinel
1276
#                help="Read-only access of branches exported on the web using SSL."
1277
            )
1540.3.26 by Martin Pool
[merge] bzr.dev; pycurl not updated for readv yet
1278
register_lazy_transport('https+pycurl://', 'bzrlib.transport.http._pycurl',
1279
                        'PyCurlTransport')
2164.2.7 by v.ladeuil+lp at free
First implementation of transport hints.
1280
# Default http transports (last declared wins (if it can be imported))
2241.2.5 by ghigo
add the topics transport
1281
register_transport_proto('http://',
1282
            help="Read-only access of branches exported on the web.")
1283
register_transport_proto('https://',
1284
            help="Read-only access of branches exported on the web using SSL.")
1540.3.26 by Martin Pool
[merge] bzr.dev; pycurl not updated for readv yet
1285
register_lazy_transport('http://', 'bzrlib.transport.http._urllib',
1286
                        'HttpTransport_urllib')
1287
register_lazy_transport('https://', 'bzrlib.transport.http._urllib',
1288
                        'HttpTransport_urllib')
1540.3.7 by Martin Pool
Prepare to select a transport depending on what dependencies can be satisfied.
1289
register_lazy_transport('http://', 'bzrlib.transport.http._pycurl', 'PyCurlTransport')
1290
register_lazy_transport('https://', 'bzrlib.transport.http._pycurl', 'PyCurlTransport')
2241.2.4 by ghigo
removed commented line
1291
2241.2.5 by ghigo
add the topics transport
1292
register_transport_proto('ftp://',
1293
            help="Access using passive FTP.")
1185.36.4 by Daniel Silverstone
Add FTP transport
1294
register_lazy_transport('ftp://', 'bzrlib.transport.ftp', 'FtpTransport')
2241.2.5 by ghigo
add the topics transport
1295
register_transport_proto('aftp://',
1296
            help="Access using active FTP.")
1185.36.4 by Daniel Silverstone
Add FTP transport
1297
register_lazy_transport('aftp://', 'bzrlib.transport.ftp', 'FtpTransport')
2241.2.4 by ghigo
removed commented line
1298
2241.2.1 by ghigo
Add the TransportRegistry class
1299
register_transport_proto('memory://')
1685.1.41 by John Arbash Meinel
memory is now memory://, need to fix the test cases.
1300
register_lazy_transport('memory://', 'bzrlib.transport.memory', 'MemoryTransport')
2241.2.1 by ghigo
Add the TransportRegistry class
1301
register_transport_proto('chroot+')
2241.3.6 by ghigo
Upgraded to the latest bzr.dev
1302
2241.2.5 by ghigo
add the topics transport
1303
register_transport_proto('readonly+',
2241.2.11 by ghigo
On the basis of Robert Collins and John Arbash Meinel
1304
#              help="This modifier converts any transport to be readonly."
1305
            )
1534.4.9 by Robert Collins
Add a readonly decorator for transports.
1306
register_lazy_transport('readonly+', 'bzrlib.transport.readonly', 'ReadonlyTransportDecorator')
2241.2.1 by ghigo
Add the TransportRegistry class
1307
register_transport_proto('fakenfs+')
1558.10.2 by Robert Collins
Refactor the FakeNFS support into a TransportDecorator.
1308
register_lazy_transport('fakenfs+', 'bzrlib.transport.fakenfs', 'FakeNFSTransportDecorator')
2241.2.1 by ghigo
Add the TransportRegistry class
1309
register_transport_proto('vfat+')
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1310
register_lazy_transport('vfat+',
1608.2.4 by Martin Pool
[broken] Add FakeFVATTransport
1311
                        'bzrlib.transport.fakevfat',
1312
                        'FakeVFATTransportDecorator')
2241.2.5 by ghigo
add the topics transport
1313
register_transport_proto('bzr://',
1314
            help="Fast access using the Bazaar smart server.")
1315
1910.19.1 by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used
1316
register_lazy_transport('bzr://',
2018.5.20 by Andrew Bennetts
Move bzrlib/transport/smart/_smart.py to bzrlib/transport/remote.py and rename SmartTransport to RemoteTransport (Robert Collins, Andrew Bennetts)
1317
                        'bzrlib.transport.remote',
2413.2.1 by Andrew Bennetts
Rename Smart.*Transport classes to RemoteTransport, RemoteTCPTransport, etc.
1318
                        'RemoteTCPTransport')
2241.2.5 by ghigo
add the topics transport
1319
register_transport_proto('bzr+http://',
2241.2.11 by ghigo
On the basis of Robert Collins and John Arbash Meinel
1320
#                help="Fast access using the Bazaar smart server over HTTP."
1321
             )
2190.1.3 by John Arbash Meinel
Implement bzr+http://
1322
register_lazy_transport('bzr+http://',
2018.5.43 by Andrew Bennetts
Merge from bzr.dev.
1323
                        'bzrlib.transport.remote',
2413.2.1 by Andrew Bennetts
Rename Smart.*Transport classes to RemoteTransport, RemoteTCPTransport, etc.
1324
                        'RemoteHTTPTransport')
2241.2.5 by ghigo
add the topics transport
1325
register_transport_proto('bzr+ssh://',
1326
            help="Fast access using the Bazaar smart server over SSH.")
1752.2.73 by Andrew Bennetts
Define (and register as bzr+ssh://) SmartSSHTransport, factor out an SSHSubprocess from SFTPSubprocess, and make SmartTransport connect lazily rather than in the constructor.
1327
register_lazy_transport('bzr+ssh://',
2018.5.20 by Andrew Bennetts
Move bzrlib/transport/smart/_smart.py to bzrlib/transport/remote.py and rename SmartTransport to RemoteTransport (Robert Collins, Andrew Bennetts)
1328
                        'bzrlib.transport.remote',
2413.2.1 by Andrew Bennetts
Rename Smart.*Transport classes to RemoteTransport, RemoteTCPTransport, etc.
1329
                        'RemoteSSHTransport')