128
128
self.get(key).insert(0,
129
129
registry._LazyObjectGetter(module_name, member_name))
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)
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
138
def get_default_port(self, scheme):
139
"""Return the registered default port for this protocol scheme."""
141
return self.get_info(scheme + '://')
146
139
transport_list_registry = TransportListRegistry()
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))
238
return '%s(%r, %r, %r)' % (self.__class__.__name__,
239
self.start, self.length, self.ranges)
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
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
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
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
801
801
Turns [(15, 10), (25, 10)] => [(15, 20, [(0, 10), (10, 10)])]
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.
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
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'
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.
811
819
:return: yield _CoalescedOffset objects, which have members for where
812
820
to start, how much to read, and how to split those
1396
1402
# have one so that it doesn't get accidentally
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))
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
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.",
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',
1763
register_lazy_transport('https://', 'bzrlib.transport.http._pycurl',
1765
register_transport_proto('ftp://',
1766
help="Access using passive FTP.",
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.",
1768
register_transport_proto('aftp://', help="Access using active FTP.")
1772
1769
register_lazy_transport('aftp://', 'bzrlib.transport.ftp', 'FtpTransport')
1774
1771
register_transport_proto('memory://')
1775
register_lazy_transport('memory://', 'bzrlib.transport.memory', 'MemoryTransport')
1772
register_lazy_transport('memory://', 'bzrlib.transport.memory',
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."
1783
register_lazy_transport('readonly+', 'bzrlib.transport.readonly', 'ReadonlyTransportDecorator')
1781
register_lazy_transport('readonly+', 'bzrlib.transport.readonly',
1782
'ReadonlyTransportDecorator')
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')
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')
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')
1794
1796
register_transport_proto('brokenrename+')
1795
1797
register_lazy_transport('brokenrename+', 'bzrlib.transport.brokenrename',
1796
'BrokenRenameTransportDecorator')
1798
'BrokenRenameTransportDecorator')
1798
1800
register_transport_proto('vfat+')
1799
1801
register_lazy_transport('vfat+',
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)
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')