/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/transport/__init__.py

  • Committer: John Arbash Meinel
  • Date: 2006-10-06 05:53:44 UTC
  • mfrom: (2063 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2071.
  • Revision ID: john@arbash-meinel.com-20061006055344-e73b97b7c6ca6e72
[merge] bzr.dev 2063

Show diffs side-by-side

added added

removed removed

Lines of Context:
168
168
            port = int(port)
169
169
        except ValueError:
170
170
            # TODO: Should this be ConnectionError?
171
 
            raise errors.TransportError('%s: invalid port number' % port)
 
171
            raise errors.TransportError(
 
172
                'invalid port number %s in url:\n%s' % (port, url))
172
173
    host = urllib.unquote(host)
173
174
 
174
175
    path = urllib.unquote(path)
201
202
    implementations can do pipelining.
202
203
    In general implementations should support having a generator or a list
203
204
    as an argument (ie always iterate, never index)
 
205
 
 
206
    :ivar base: Base URL for the transport; should always end in a slash.
204
207
    """
205
208
 
206
209
    # implementations can override this if it is more efficient
307
310
 
308
311
    def abspath(self, relpath):
309
312
        """Return the full url to the given relative path.
310
 
        This can be supplied with a string or a list
311
313
 
312
 
        XXX: Robert Collins 20051016 - is this really needed in the public
313
 
             interface ?
 
314
        :param relpath: a string of a relative path
314
315
        """
 
316
 
 
317
        # XXX: Robert Collins 20051016 - is this really needed in the public
 
318
        # interface ?
315
319
        raise NotImplementedError(self.abspath)
316
320
 
 
321
    def _combine_paths(self, base_path, relpath):
 
322
        """Transform a Transport-relative path to a remote absolute path.
 
323
 
 
324
        This does not handle substitution of ~ but does handle '..' and '.'
 
325
        components.
 
326
 
 
327
        Examples::
 
328
 
 
329
            t._combine_paths('/home/sarah', 'project/foo')
 
330
                => '/home/sarah/project/foo'
 
331
            t._combine_paths('/home/sarah', '../../etc')
 
332
                => '/etc'
 
333
 
 
334
        :param base_path: urlencoded path for the transport root; typically a 
 
335
             URL but need not contain scheme/host/etc.
 
336
        :param relpath: relative url string for relative part of remote path.
 
337
        :return: urlencoded string for final path.
 
338
        """
 
339
        # FIXME: share the common code across more transports; variants of
 
340
        # this likely occur in http and sftp too.
 
341
        #
 
342
        # TODO: Also need to consider handling of ~, which might vary between
 
343
        # transports?
 
344
        if not isinstance(relpath, str):
 
345
            raise errors.InvalidURL("not a valid url: %r" % relpath)
 
346
        if relpath.startswith('/'):
 
347
            base_parts = []
 
348
        else:
 
349
            base_parts = base_path.split('/')
 
350
        if len(base_parts) > 0 and base_parts[-1] == '':
 
351
            base_parts = base_parts[:-1]
 
352
        for p in relpath.split('/'):
 
353
            if p == '..':
 
354
                if len(base_parts) == 0:
 
355
                    # In most filesystems, a request for the parent
 
356
                    # of root, just returns root.
 
357
                    continue
 
358
                base_parts.pop()
 
359
            elif p == '.':
 
360
                continue # No-op
 
361
            elif p != '':
 
362
                base_parts.append(p)
 
363
        path = '/'.join(base_parts)
 
364
        return path
 
365
 
317
366
    def relpath(self, abspath):
318
367
        """Return the local path portion from a given absolute path.
319
368
 
345
394
        Note that some transports MAY allow querying on directories, but this
346
395
        is not part of the protocol.  In other words, the results of 
347
396
        t.has("a_directory_name") are undefined.
 
397
 
 
398
        :rtype: bool
348
399
        """
349
400
        raise NotImplementedError(self.has)
350
401
 
381
432
        """Get the file at the given relative path.
382
433
 
383
434
        :param relpath: The relative path to the file
 
435
        :rtype: File-like object.
384
436
        """
385
437
        raise NotImplementedError(self.get)
386
438
 
391
443
        """
392
444
        return self.get(relpath).read()
393
445
 
 
446
    def get_smart_client(self):
 
447
        """Return a smart client for this transport if possible.
 
448
 
 
449
        :raises NoSmartServer: if no smart server client is available.
 
450
        """
 
451
        raise errors.NoSmartServer(self.base)
 
452
 
394
453
    def readv(self, relpath, offsets):
395
454
        """Get parts of the file at the given relative path.
396
455
 
401
460
            return
402
461
 
403
462
        fp = self.get(relpath)
404
 
        return self._seek_and_read(fp, offsets)
 
463
        return self._seek_and_read(fp, offsets, relpath)
405
464
 
406
 
    def _seek_and_read(self, fp, offsets):
 
465
    def _seek_and_read(self, fp, offsets, relpath='<unknown>'):
407
466
        """An implementation of readv that uses fp.seek and fp.read.
408
467
 
409
468
        This uses _coalesce_offsets to issue larger reads and fewer seeks.
431
490
            #       benchmarked.
432
491
            fp.seek(c_offset.start)
433
492
            data = fp.read(c_offset.length)
 
493
            if len(data) < c_offset.length:
 
494
                raise errors.ShortReadvError(relpath, c_offset.start,
 
495
                            c_offset.length, actual=len(data))
434
496
            for suboffset, subsize in c_offset.ranges:
435
497
                key = (c_offset.start+suboffset, subsize)
436
498
                data_map[key] = data[suboffset:suboffset+subsize]
637
699
        return self.append_file(relpath, f, mode=mode)
638
700
 
639
701
    def append_file(self, relpath, f, mode=None):
640
 
        """Append the text in the file-like object to the supplied location.
641
 
 
642
 
        returns the length of relpath before the content was written to it.
643
 
        
644
 
        If the file does not exist, it is created with the supplied mode.
 
702
        """Append bytes from a file-like object to a file at relpath.
 
703
 
 
704
        The file is created if it does not already exist.
 
705
 
 
706
        :param f: a file-like object of the bytes to append.
 
707
        :param mode: Unix mode for newly created files.  This is not used for
 
708
            existing files.
 
709
 
 
710
        :returns: the length of relpath before the content was written to it.
645
711
        """
646
712
        symbol_versioning.warn('Transport %s should implement append_file,'
647
713
                               ' rather than implementing append() as of'
651
717
        return self.append(relpath, f, mode=mode)
652
718
 
653
719
    def append_bytes(self, relpath, bytes, mode=None):
654
 
        """Append the text in the string object to the supplied location.
655
 
 
656
 
        returns the length of relpath before the content was written to it.
657
 
        
658
 
        If the file does not exist, it is created with the supplied mode.
 
720
        """Append bytes to a file at relpath.
 
721
 
 
722
        The file is created if it does not already exist.
 
723
 
 
724
        :type f: str
 
725
        :param f: a string of the bytes to append.
 
726
        :param mode: Unix mode for newly created files.  This is not used for
 
727
            existing files.
 
728
 
 
729
        :returns: the length of relpath before the content was written to it.
659
730
        """
660
731
        assert isinstance(bytes, str), \
661
732
            'bytes must be a plain string, not %s' % type(bytes)
851
922
        WARNING: many transports do not support this, so trying avoid using
852
923
        it if at all possible.
853
924
        """
854
 
        raise errors.TransportNotPossible("This transport has not "
 
925
        raise errors.TransportNotPossible("Transport %r has not "
855
926
                                          "implemented list_dir "
856
927
                                          "(but must claim to be listable "
857
 
                                          "to trigger this error).")
 
928
                                          "to trigger this error)."
 
929
                                          % (self))
858
930
 
859
931
    def lock_read(self, relpath):
860
932
        """Lock the given file for shared (read) access.
861
 
        WARNING: many transports do not support this, so trying avoid using it
 
933
 
 
934
        WARNING: many transports do not support this, so trying avoid using it.
 
935
        These methods may be removed in the future.
 
936
 
 
937
        Transports may raise TransportNotPossible if OS-level locks cannot be
 
938
        taken over this transport.  
862
939
 
863
940
        :return: A lock object, which should contain an unlock() function.
864
941
        """
865
 
        raise NotImplementedError(self.lock_read)
 
942
        raise errors.TransportNotPossible("transport locks not supported on %s" % self)
866
943
 
867
944
    def lock_write(self, relpath):
868
945
        """Lock the given file for exclusive (write) access.
869
 
        WARNING: many transports do not support this, so trying avoid using it
 
946
 
 
947
        WARNING: many transports do not support this, so trying avoid using it.
 
948
        These methods may be removed in the future.
 
949
 
 
950
        Transports may raise TransportNotPossible if OS-level locks cannot be
 
951
        taken over this transport.
870
952
 
871
953
        :return: A lock object, which should contain an unlock() function.
872
954
        """
873
 
        raise NotImplementedError(self.lock_write)
 
955
        raise errors.TransportNotPossible("transport locks not supported on %s" % self)
874
956
 
875
957
    def is_readonly(self):
876
958
        """Return true if this connection cannot be written to."""
1086
1168
register_lazy_transport('memory://', 'bzrlib.transport.memory', 'MemoryTransport')
1087
1169
register_lazy_transport('readonly+', 'bzrlib.transport.readonly', 'ReadonlyTransportDecorator')
1088
1170
register_lazy_transport('fakenfs+', 'bzrlib.transport.fakenfs', 'FakeNFSTransportDecorator')
1089
 
register_lazy_transport('vfat+', 
 
1171
register_lazy_transport('vfat+',
1090
1172
                        'bzrlib.transport.fakevfat',
1091
1173
                        'FakeVFATTransportDecorator')
 
1174
register_lazy_transport('bzr://',
 
1175
                        'bzrlib.transport.smart',
 
1176
                        'SmartTCPTransport')
 
1177
register_lazy_transport('bzr+ssh://',
 
1178
                        'bzrlib.transport.smart',
 
1179
                        'SmartSSHTransport')