~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/__init__.py

(Martin Pool) Make it optional for transports to implement lock_read and lock_write by testing that they either work or raise TransportNotPossible.

Show diffs side-by-side

added added

removed removed

Lines of Context:
307
307
 
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
311
310
 
312
 
        XXX: Robert Collins 20051016 - is this really needed in the public
313
 
             interface ?
 
311
        :param relpath: a string of a relative path
314
312
        """
 
313
 
 
314
        # XXX: Robert Collins 20051016 - is this really needed in the public
 
315
        # interface ?
315
316
        raise NotImplementedError(self.abspath)
316
317
 
 
318
    def _combine_paths(self, base_path, relpath):
 
319
        """Transform a Transport-relative path to a remote absolute path.
 
320
 
 
321
        This does not handle substitution of ~ but does handle '..' and '.'
 
322
        components.
 
323
 
 
324
        Examples::
 
325
 
 
326
            >>> t = Transport('/')
 
327
            >>> t._combine_paths('/home/sarah', 'project/foo')
 
328
            '/home/sarah/project/foo'
 
329
            >>> t._combine_paths('/home/sarah', '../../etc')
 
330
            '/etc'
 
331
 
 
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.
 
336
        """
 
337
        # FIXME: share the common code across more transports; variants of
 
338
        # this likely occur in http and sftp too.
 
339
        #
 
340
        # TODO: Also need to consider handling of ~, which might vary between
 
341
        # transports?
 
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('/'):
 
348
            if p == '..':
 
349
                if len(base_parts) == 0:
 
350
                    # In most filesystems, a request for the parent
 
351
                    # of root, just returns root.
 
352
                    continue
 
353
                base_parts.pop()
 
354
            elif p == '.':
 
355
                continue # No-op
 
356
            elif p != '':
 
357
                base_parts.append(p)
 
358
        path = '/'.join(base_parts)
 
359
        return path
 
360
 
317
361
    def relpath(self, abspath):
318
362
        """Return the local path portion from a given absolute path.
319
363
 
862
906
        WARNING: many transports do not support this, so trying avoid using
863
907
        it if at all possible.
864
908
        """
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)."
 
913
                                          % (self))
869
914
 
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
 
917
 
 
918
        WARNING: many transports do not support this, so trying avoid using it.
 
919
        These methods may be removed in the future.
 
920
 
 
921
        Transports may raise TransportNotPossible if OS-level locks cannot be
 
922
        taken over this transport.  
873
923
 
874
924
        :return: A lock object, which should contain an unlock() function.
875
925
        """
876
 
        raise NotImplementedError(self.lock_read)
 
926
        raise errors.TransportNotPossible("transport locks not supported on %s" % self)
877
927
 
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
 
930
 
 
931
        WARNING: many transports do not support this, so trying avoid using it.
 
932
        These methods may be removed in the future.
 
933
 
 
934
        Transports may raise TransportNotPossible if OS-level locks cannot be
 
935
        taken over this transport.
881
936
 
882
937
        :return: A lock object, which should contain an unlock() function.
883
938
        """
884
 
        raise NotImplementedError(self.lock_write)
 
939
        raise errors.TransportNotPossible("transport locks not supported on %s" % self)
885
940
 
886
941
    def is_readonly(self):
887
942
        """Return true if this connection cannot be written to."""