308
308
def abspath(self, relpath):
309
309
"""Return the full url to the given relative path.
310
This can be supplied with a string or a list
312
XXX: Robert Collins 20051016 - is this really needed in the public
311
:param relpath: a string of a relative path
314
# XXX: Robert Collins 20051016 - is this really needed in the public
315
316
raise NotImplementedError(self.abspath)
318
def _combine_paths(self, base_path, relpath):
319
"""Transform a Transport-relative path to a remote absolute path.
321
This does not handle substitution of ~ but does handle '..' and '.'
326
>>> t = Transport('/')
327
>>> t._combine_paths('/home/sarah', 'project/foo')
328
'/home/sarah/project/foo'
329
>>> t._combine_paths('/home/sarah', '../../etc')
332
:param base_path: urlencoded path for the transport root; typically a
333
URL but need not contain scheme/host/etc.
334
:param relpath: relative url string for relative part of remote path.
335
:return: urlencoded string for final path.
337
# FIXME: share the common code across more transports; variants of
338
# this likely occur in http and sftp too.
340
# TODO: Also need to consider handling of ~, which might vary between
342
if not isinstance(relpath, str):
343
raise errors.InvalidURL("not a valid url: %r" % relpath)
344
base_parts = base_path.split('/')
345
if len(base_parts) > 0 and base_parts[-1] == '':
346
base_parts = base_parts[:-1]
347
for p in relpath.split('/'):
349
if len(base_parts) == 0:
350
# In most filesystems, a request for the parent
351
# of root, just returns root.
358
path = '/'.join(base_parts)
317
361
def relpath(self, abspath):
318
362
"""Return the local path portion from a given absolute path.
862
906
WARNING: many transports do not support this, so trying avoid using
863
907
it if at all possible.
865
raise errors.TransportNotPossible("This transport has not "
909
raise errors.TransportNotPossible("Transport %r has not "
866
910
"implemented list_dir "
867
911
"(but must claim to be listable "
868
"to trigger this error).")
912
"to trigger this error)."
870
915
def lock_read(self, relpath):
871
916
"""Lock the given file for shared (read) access.
872
WARNING: many transports do not support this, so trying avoid using it
918
WARNING: many transports do not support this, so trying avoid using it.
919
These methods may be removed in the future.
921
Transports may raise TransportNotPossible if OS-level locks cannot be
922
taken over this transport.
874
924
:return: A lock object, which should contain an unlock() function.
876
raise NotImplementedError(self.lock_read)
926
raise errors.TransportNotPossible("transport locks not supported on %s" % self)
878
928
def lock_write(self, relpath):
879
929
"""Lock the given file for exclusive (write) access.
880
WARNING: many transports do not support this, so trying avoid using it
931
WARNING: many transports do not support this, so trying avoid using it.
932
These methods may be removed in the future.
934
Transports may raise TransportNotPossible if OS-level locks cannot be
935
taken over this transport.
882
937
:return: A lock object, which should contain an unlock() function.
884
raise NotImplementedError(self.lock_write)
939
raise errors.TransportNotPossible("transport locks not supported on %s" % self)
886
941
def is_readonly(self):
887
942
"""Return true if this connection cannot be written to."""