40
40
## mutter('registering transport: %s => %s' % (prefix, klass.__name__))
41
41
_protocol_handlers[prefix] = klass
43
44
class Transport(object):
44
45
"""This class encapsulates methods for retrieving or putting a file
45
46
from/to a storage location.
122
123
def abspath(self, relpath):
123
124
"""Return the full url to the given relative path.
124
125
This can be supplied with a string or a list
127
XXX: Robert Collins 20051016 - is this really needed in the public
126
130
raise NotImplementedError
128
132
def relpath(self, abspath):
129
133
"""Return the local path portion from a given absolute path.
135
This default implementation is not suitable for filesystems with
136
aliasing, such as that given by symlinks, where a path may not
137
start with our base, but still be a relpath once aliasing is
131
raise NotImplementedError
140
if not abspath.startswith(self.base):
141
raise NonRelativePath('path %r is not under base URL %r'
142
% (abspath, self.base))
144
return abspath[pl:].lstrip('/')
133
147
def has(self, relpath):
134
"""Does the target location exist?"""
148
"""Does the file relpath exist?
150
Note that some transports MAY allow querying on directories, but this
151
is not part of the protocol.
135
153
raise NotImplementedError
137
155
def has_multi(self, relpaths, pb=None):
143
161
yield self.has(relpath)
164
def iter_files_recursive(self):
165
"""Iter the relative paths of files in the transports sub-tree.
167
As with other listing functions, only some transports implement this,.
168
you may check via is_listable to determine if it will.
170
raise NotImplementedError
146
172
def get(self, relpath):
147
173
"""Get the file at the given relative path.
167
193
yield self.get(relpath)
170
def get_partial(self, relpath, start, length=None):
171
"""Get just part of a file.
173
:param relpath: Path to the file, relative to base
174
:param start: The starting position to read from
175
:param length: The length to read. A length of None indicates
176
read to the end of the file.
177
:return: A file-like object containing at least the specified bytes.
178
Some implementations may return objects which can be read
179
past this length, but this is not guaranteed.
181
raise NotImplementedError
183
def get_partial_multi(self, offsets, pb=None):
184
"""Put a set of files or strings into the location.
186
Requesting multiple portions of the same file can be dangerous.
188
:param offsets: A list of tuples of relpath, start, length
189
[(path1, start1, length1),
190
(path2, start2, length2),
191
(path3, start3), ...]
192
length is optional, defaulting to None
193
:param pb: An optional ProgressBar for indicating percent done.
194
:return: A generator of file-like objects.
196
total = self._get_total(offsets)
198
for offset in offsets:
199
self._update_pb(pb, 'get_partial', count, total)
200
yield self.get_partial(*offset)
203
196
def put(self, relpath, f):
204
197
"""Copy the file-like or string object into the location.
301
294
"""Return the stat information for a file.
302
295
WARNING: This may not be implementable for all protocols, so use
297
NOTE: This returns an object with fields such as 'st_size'. It MAY
298
or MAY NOT return the literal result of an os.stat() call, so all
299
access should be via named fields.
300
ALSO NOTE: Stats of directories may not be supported on some
305
303
raise NotImplementedError
359
357
# Local transport should always be initialized
360
358
import bzrlib.transport.local
361
def register_builtin_transports():
362
"""Register all builtin transport modules.
364
This happens as a sideeffect of importing the modules.
366
import bzrlib.transport.local, \
367
bzrlib.transport.http, \
368
bzrlib.transport.sftp