/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: Robert Collins
  • Date: 2008-02-13 03:30:01 UTC
  • mfrom: (3221 +trunk)
  • mto: This revision was merged to the branch mainline in revision 3224.
  • Revision ID: robertc@robertcollins.net-20080213033001-rw70ul0zb02ph856
Merge to fix conflicts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
128
128
        self.get(key).insert(0,
129
129
                registry._LazyObjectGetter(module_name, member_name))
130
130
 
131
 
    def register_transport(self, key, help=None, default_port=None):
132
 
        self.register(key, [], help, default_port)
 
131
    def register_transport(self, key, help=None):
 
132
        self.register(key, [], help)
133
133
 
134
134
    def set_default_transport(self, key=None):
135
135
        """Return either 'key' or the default key if key is None"""
136
136
        self._default_key = key
137
137
 
138
 
    def get_default_port(self, scheme):
139
 
        """Return the registered default port for this protocol scheme."""
140
 
        try:
141
 
            return self.get_info(scheme + '://')
142
 
        except LookupError:
143
 
            return None
144
 
 
145
138
 
146
139
transport_list_registry = TransportListRegistry()
147
140
 
148
141
 
149
 
def register_transport_proto(prefix, help=None, info=None, default_port=None,
 
142
def register_transport_proto(prefix, help=None, info=None,
150
143
                             register_netloc=False):
151
 
    transport_list_registry.register_transport(prefix, help, default_port)
 
144
    transport_list_registry.register_transport(prefix, help)
152
145
    if register_netloc:
153
146
        assert prefix.endswith('://')
154
147
        register_urlparse_netloc_protocol(prefix[:-3])
241
234
        return cmp((self.start, self.length, self.ranges),
242
235
                   (other.start, other.length, other.ranges))
243
236
 
 
237
    def __repr__(self):
 
238
        return '%s(%r, %r, %r)' % (self.__class__.__name__,
 
239
            self.start, self.length, self.ranges)
 
240
 
244
241
 
245
242
class LateReadError(object):
246
243
    """A helper for transports which pretends to be a readable file.
346
343
        This handles things like ENOENT, ENOTDIR, EEXIST, and EACCESS
347
344
        """
348
345
        if getattr(e, 'errno', None) is not None:
349
 
            if e.errno in (errno.ENOENT, errno.ENOTDIR):
 
346
            if e.errno in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL):
350
347
                raise errors.NoSuchFile(path, extra=e)
351
348
            # I would rather use errno.EFOO, but there doesn't seem to be
352
349
            # any matching for 267
652
649
 
653
650
        :param relpath: The path to read data from.
654
651
        :param offsets: A list of (offset, size) tuples.
655
 
        :param adjust_for_latency: Adjust the requested offsets to accomdate
 
652
        :param adjust_for_latency: Adjust the requested offsets to accomodate
656
653
            transport latency. This may re-order the offsets, expand them to
657
654
            grab adjacent data when there is likely a high cost to requesting
658
655
            data relative to delivering it.
668
665
        if adjust_for_latency:
669
666
            # Design note: We may wish to have different algorithms for the
670
667
            # expansion of the offsets per-transport. E.g. for local disk to
671
 
            # use page-aligned expansion. If that is the case consider the following structure:
672
 
            #  - a test that transport.readv uses self._offset_expander or some similar attribute, to do the expansion
673
 
            #  - a test for each transport that it has some known-good offset expander
 
668
            # use page-aligned expansion. If that is the case consider the
 
669
            # following structure:
 
670
            #  - a test that transport.readv uses self._offset_expander or some
 
671
            #    similar attribute, to do the expansion
 
672
            #  - a test for each transport that it has some known-good offset
 
673
            #    expander
674
674
            #  - unit tests for each offset expander
675
675
            #  - a set of tests for the offset expander interface, giving
676
676
            #    baseline behaviour (which the current transport
792
792
        return offsets
793
793
 
794
794
    @staticmethod
795
 
    def _coalesce_offsets(offsets, limit, fudge_factor):
 
795
    def _coalesce_offsets(offsets, limit=0, fudge_factor=0, max_size=0):
796
796
        """Yield coalesced offsets.
797
797
 
798
798
        With a long list of neighboring requests, combine them
801
801
        Turns  [(15, 10), (25, 10)] => [(15, 20, [(0, 10), (10, 10)])]
802
802
 
803
803
        :param offsets: A list of (start, length) pairs
804
 
        :param limit: Only combine a maximum of this many pairs
805
 
                      Some transports penalize multiple reads more than
806
 
                      others, and sometimes it is better to return early.
807
 
                      0 means no limit
 
804
 
 
805
        :param limit: Only combine a maximum of this many pairs Some transports
 
806
                penalize multiple reads more than others, and sometimes it is
 
807
                better to return early.
 
808
                0 means no limit
 
809
 
808
810
        :param fudge_factor: All transports have some level of 'it is
809
811
                better to read some more data and throw it away rather 
810
812
                than seek', so collapse if we are 'close enough'
 
813
 
 
814
        :param max_size: Create coalesced offsets no bigger than this size.
 
815
                When a single offset is bigger than 'max_size', it will keep
 
816
                its size and be alone in the coalesced offset.
 
817
                0 means no maximum size.
 
818
 
811
819
        :return: yield _CoalescedOffset objects, which have members for where
812
820
                to start, how much to read, and how to split those 
813
821
                chunks back up
817
825
 
818
826
        for start, size in offsets:
819
827
            end = start + size
820
 
            if (last_end is not None 
 
828
            if (last_end is not None
821
829
                and start <= last_end + fudge_factor
822
830
                and start >= cur.start
823
 
                and (limit <= 0 or len(cur.ranges) < limit)):
 
831
                and (limit <= 0 or len(cur.ranges) < limit)
 
832
                and (max_size <= 0 or end - cur.start <= max_size)):
824
833
                cur.length = end - cur.start
825
834
                cur.ranges.append((start-cur.start, size))
826
835
            else:
1253
1262
class _SharedConnection(object):
1254
1263
    """A connection shared between several transports."""
1255
1264
 
1256
 
    def __init__(self, connection=None, credentials=None):
 
1265
    def __init__(self, connection=None, credentials=None, base=None):
1257
1266
        """Constructor.
1258
1267
 
1259
1268
        :param connection: An opaque object specific to each transport.
1263
1272
        """
1264
1273
        self.connection = connection
1265
1274
        self.credentials = credentials
 
1275
        self.base = base
1266
1276
 
1267
1277
 
1268
1278
class ConnectedTransport(Transport):
1362
1372
        host = urllib.unquote(host)
1363
1373
        path = urllib.unquote(path)
1364
1374
 
1365
 
        if port is None:
1366
 
            # The port isn't explicitly specified, so return the default (if
1367
 
            # there is one).
1368
 
            port = transport_list_registry.get_default_port(scheme)
1369
1375
        return (scheme, user, password, host, port, path)
1370
1376
 
1371
1377
    @staticmethod
1396
1402
            # have one so that it doesn't get accidentally
1397
1403
            # exposed.
1398
1404
            netloc = '%s@%s' % (urllib.quote(user), netloc)
1399
 
        if (port is not None and 
1400
 
            port != transport_list_registry.get_default_port(scheme)):
1401
 
            # Include the port in the netloc (unless it's the same as the
1402
 
            # default, in which case we omit it as it is redundant).
 
1405
        if port is not None:
1403
1406
            netloc = '%s:%d' % (netloc, port)
1404
1407
        path = urllib.quote(path)
1405
1408
        return urlparse.urlunparse((scheme, netloc, path, None, None, None))
1456
1459
        """Get the object shared amongst cloned transports.
1457
1460
 
1458
1461
        This should be used only by classes that needs to extend the sharing
1459
 
        with other objects than tramsports.
 
1462
        with objects other than transports.
1460
1463
 
1461
1464
        Use _get_connection to get the connection itself.
1462
1465
        """
1721
1724
register_lazy_transport('file://', 'bzrlib.transport.local', 'LocalTransport')
1722
1725
transport_list_registry.set_default_transport("file://")
1723
1726
 
1724
 
# Note that sftp:// has no default_port, because the user's ~/.ssh/config
1725
 
# can set it to arbitrary values based on hostname.
1726
1727
register_transport_proto('sftp://',
1727
1728
            help="Access using SFTP (most SSH servers provide SFTP).",
1728
1729
            register_netloc=True)
1730
1731
# Decorated http transport
1731
1732
register_transport_proto('http+urllib://',
1732
1733
#                help="Read-only access of branches exported on the web."
1733
 
            default_port=80, register_netloc=True)
 
1734
                         register_netloc=True)
1734
1735
register_lazy_transport('http+urllib://', 'bzrlib.transport.http._urllib',
1735
1736
                        'HttpTransport_urllib')
1736
1737
register_transport_proto('https+urllib://',
1737
1738
#                help="Read-only access of branches exported on the web using SSL."
1738
 
            default_port=443, register_netloc=True)
 
1739
                         register_netloc=True)
1739
1740
register_lazy_transport('https+urllib://', 'bzrlib.transport.http._urllib',
1740
1741
                        'HttpTransport_urllib')
1741
1742
register_transport_proto('http+pycurl://',
1742
1743
#                help="Read-only access of branches exported on the web."
1743
 
            default_port=80, register_netloc=True)
 
1744
                         register_netloc=True)
1744
1745
register_lazy_transport('http+pycurl://', 'bzrlib.transport.http._pycurl',
1745
1746
                        'PyCurlTransport')
1746
1747
register_transport_proto('https+pycurl://',
1747
1748
#                help="Read-only access of branches exported on the web using SSL."
1748
 
            default_port=443, register_netloc=True)
 
1749
                         register_netloc=True)
1749
1750
register_lazy_transport('https+pycurl://', 'bzrlib.transport.http._pycurl',
1750
1751
                        'PyCurlTransport')
1751
1752
# Default http transports (last declared wins (if it can be imported))
1752
1753
register_transport_proto('http://',
1753
 
            help="Read-only access of branches exported on the web.",
1754
 
            default_port=80)
 
1754
                 help="Read-only access of branches exported on the web.")
1755
1755
register_transport_proto('https://',
1756
 
            help="Read-only access of branches exported on the web using SSL.",
1757
 
            default_port=443)
 
1756
            help="Read-only access of branches exported on the web using SSL.")
1758
1757
register_lazy_transport('http://', 'bzrlib.transport.http._urllib',
1759
1758
                        'HttpTransport_urllib')
1760
1759
register_lazy_transport('https://', 'bzrlib.transport.http._urllib',
1761
1760
                        'HttpTransport_urllib')
1762
 
register_lazy_transport('http://', 'bzrlib.transport.http._pycurl', 'PyCurlTransport')
1763
 
register_lazy_transport('https://', 'bzrlib.transport.http._pycurl', 'PyCurlTransport')
 
1761
register_lazy_transport('http://', 'bzrlib.transport.http._pycurl',
 
1762
                        'PyCurlTransport')
 
1763
register_lazy_transport('https://', 'bzrlib.transport.http._pycurl',
 
1764
                        'PyCurlTransport')
1764
1765
 
1765
 
register_transport_proto('ftp://',
1766
 
            help="Access using passive FTP.",
1767
 
            default_port=21)
 
1766
register_transport_proto('ftp://', help="Access using passive FTP.")
1768
1767
register_lazy_transport('ftp://', 'bzrlib.transport.ftp', 'FtpTransport')
1769
 
register_transport_proto('aftp://',
1770
 
            help="Access using active FTP.",
1771
 
            default_port=21)
 
1768
register_transport_proto('aftp://', help="Access using active FTP.")
1772
1769
register_lazy_transport('aftp://', 'bzrlib.transport.ftp', 'FtpTransport')
1773
1770
 
1774
1771
register_transport_proto('memory://')
1775
 
register_lazy_transport('memory://', 'bzrlib.transport.memory', 'MemoryTransport')
 
1772
register_lazy_transport('memory://', 'bzrlib.transport.memory',
 
1773
                        'MemoryTransport')
1776
1774
 
1777
1775
# chroots cannot be implicitly accessed, they must be explicitly created:
1778
1776
register_transport_proto('chroot+')
1780
1778
register_transport_proto('readonly+',
1781
1779
#              help="This modifier converts any transport to be readonly."
1782
1780
            )
1783
 
register_lazy_transport('readonly+', 'bzrlib.transport.readonly', 'ReadonlyTransportDecorator')
 
1781
register_lazy_transport('readonly+', 'bzrlib.transport.readonly',
 
1782
                        'ReadonlyTransportDecorator')
1784
1783
 
1785
1784
register_transport_proto('fakenfs+')
1786
 
register_lazy_transport('fakenfs+', 'bzrlib.transport.fakenfs', 'FakeNFSTransportDecorator')
 
1785
register_lazy_transport('fakenfs+', 'bzrlib.transport.fakenfs',
 
1786
                        'FakeNFSTransportDecorator')
1787
1787
 
1788
1788
register_transport_proto('trace+')
1789
 
register_lazy_transport('trace+', 'bzrlib.transport.trace', 'TransportTraceDecorator')
 
1789
register_lazy_transport('trace+', 'bzrlib.transport.trace',
 
1790
                        'TransportTraceDecorator')
1790
1791
 
1791
1792
register_transport_proto('unlistable+')
1792
 
register_lazy_transport('unlistable+', 'bzrlib.transport.unlistable', 'UnlistableTransportDecorator')
 
1793
register_lazy_transport('unlistable+', 'bzrlib.transport.unlistable',
 
1794
                        'UnlistableTransportDecorator')
1793
1795
 
1794
1796
register_transport_proto('brokenrename+')
1795
1797
register_lazy_transport('brokenrename+', 'bzrlib.transport.brokenrename',
1796
 
        'BrokenRenameTransportDecorator')
 
1798
                        'BrokenRenameTransportDecorator')
1797
1799
 
1798
1800
register_transport_proto('vfat+')
1799
1801
register_lazy_transport('vfat+',
1808
1810
 
1809
1811
register_transport_proto('bzr://',
1810
1812
            help="Fast access using the Bazaar smart server.",
1811
 
            default_port=4155, register_netloc=True)
 
1813
                         register_netloc=True)
1812
1814
 
1813
 
register_lazy_transport('bzr://',
1814
 
                        'bzrlib.transport.remote',
 
1815
register_lazy_transport('bzr://', 'bzrlib.transport.remote',
1815
1816
                        'RemoteTCPTransport')
1816
1817
register_transport_proto('bzr+http://',
1817
1818
#                help="Fast access using the Bazaar smart server over HTTP."
1818
 
            default_port=80, register_netloc=True)
1819
 
register_lazy_transport('bzr+http://',
1820
 
                        'bzrlib.transport.remote',
 
1819
                         register_netloc=True)
 
1820
register_lazy_transport('bzr+http://', 'bzrlib.transport.remote',
1821
1821
                        'RemoteHTTPTransport')
1822
1822
register_transport_proto('bzr+https://',
1823
1823
#                help="Fast access using the Bazaar smart server over HTTPS."
1824
 
             register_netloc=True)
 
1824
                         register_netloc=True)
1825
1825
register_lazy_transport('bzr+https://',
1826
1826
                        'bzrlib.transport.remote',
1827
1827
                        'RemoteHTTPTransport')
1828
 
# Note that bzr+ssh:// has no default_port, because the user's ~/.ssh/config
1829
 
# can set it to arbitrary values based on hostname.
1830
1828
register_transport_proto('bzr+ssh://',
1831
1829
            help="Fast access using the Bazaar smart server over SSH.",
1832
1830
            register_netloc=True)
1833
 
register_lazy_transport('bzr+ssh://',
1834
 
                        'bzrlib.transport.remote',
 
1831
register_lazy_transport('bzr+ssh://', 'bzrlib.transport.remote',
1835
1832
                        'RemoteSSHTransport')