~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/__init__.py

  • Committer: Robert Collins
  • Date: 2007-10-04 22:00:07 UTC
  • mfrom: (2887 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2933.
  • Revision ID: robertc@robertcollins.net-20071004220007-6tb7pyeknkhpnfyq
Merge bzr.dev (untested)

Show diffs side-by-side

added added

removed removed

Lines of Context:
99
99
                modules.add(factory._module_name)
100
100
            else:
101
101
                modules.add(factory._obj.__module__)
102
 
    # Add chroot directly, because there is not handler registered for it.
 
102
    # Add chroot directly, because there is no handler registered for it.
103
103
    modules.add('bzrlib.transport.chroot')
104
104
    result = list(modules)
105
105
    result.sort()
125
125
        self.get(key).insert(0, registry._ObjectGetter(obj))
126
126
 
127
127
    def register_lazy_transport_provider(self, key, module_name, member_name):
128
 
        self.get(key).insert(0, 
 
128
        self.get(key).insert(0,
129
129
                registry._LazyObjectGetter(module_name, member_name))
130
130
 
131
 
    def register_transport(self, key, help=None, info=None):
132
 
        self.register(key, [], help, info)
 
131
    def register_transport(self, key, help=None, default_port=None):
 
132
        self.register(key, [], help, default_port)
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
 
 
139
 
transport_list_registry = TransportListRegistry( )
140
 
 
141
 
 
142
 
def register_transport_proto(prefix, help=None, info=None):
143
 
    transport_list_registry.register_transport(prefix, help, info)
 
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
 
 
146
transport_list_registry = TransportListRegistry()
 
147
 
 
148
 
 
149
def register_transport_proto(prefix, help=None, info=None, default_port=None):
 
150
    transport_list_registry.register_transport(prefix, help, default_port)
144
151
 
145
152
 
146
153
def register_lazy_transport(prefix, module, classname):
635
642
        """
636
643
        raise errors.NoSmartMedium(self)
637
644
 
638
 
    def readv(self, relpath, offsets, adjust_for_latency=False):
 
645
    def readv(self, relpath, offsets, adjust_for_latency=False,
 
646
        upper_limit=None):
639
647
        """Get parts of the file at the given relative path.
640
648
 
641
649
        :param relpath: The path to read data from.
644
652
            transport latency. This may re-order the offsets, expand them to
645
653
            grab adjacent data when there is likely a high cost to requesting
646
654
            data relative to delivering it.
 
655
        :param upper_limit: When adjust_for_latency is True setting upper_limit
 
656
            allows the caller to tell the transport about the length of the
 
657
            file, so that requests are not issued for ranges beyond the end of
 
658
            the file. This matters because some servers and/or transports error
 
659
            in such a case rather than just satisfying the available ranges.
 
660
            upper_limit should always be provided when adjust_for_latency is
 
661
            True, and should be the size of the file in bytes.
647
662
        :return: A list or generator of (offset, data) tuples
648
663
        """
649
664
        if adjust_for_latency:
658
673
                        yield None
659
674
                return empty_yielder()
660
675
            # expand by page size at either end
661
 
            expansion = self.recommended_page_size() / 2
 
676
            expansion = self.recommended_page_size()
 
677
            reduction = expansion / 2
662
678
            new_offsets = []
663
679
            for offset, length in offsets:
664
 
                new_offset = offset - expansion
 
680
                new_offset = offset - reduction
665
681
                new_length = length + expansion
666
682
                if new_offset < 0:
667
683
                    # don't ask for anything < 0
668
684
                    new_length -= new_offset
669
685
                    new_offset = 0
 
686
                if (upper_limit is not None and
 
687
                    new_offset + new_length > upper_limit):
 
688
                    new_length = upper_limit - new_offset
670
689
                new_offsets.append((new_offset, new_length))
671
690
            # combine the expanded offsets
672
691
            offsets = []
687
706
    def _readv(self, relpath, offsets):
688
707
        """Get parts of the file at the given relative path.
689
708
 
690
 
        :offsets: A list of (offset, size) tuples.
 
709
        :param relpath: The path to read.
 
710
        :param offsets: A list of (offset, size) tuples.
691
711
        :return: A list or generator of (offset, data) tuples
692
712
        """
693
713
        if not offsets:
1305
1325
        host = urllib.unquote(host)
1306
1326
        path = urllib.unquote(path)
1307
1327
 
 
1328
        if port is None:
 
1329
            # The port isn't explicitly specified, so return the default (if
 
1330
            # there is one).
 
1331
            port = transport_list_registry.get_default_port(scheme)
1308
1332
        return (scheme, user, password, host, port, path)
1309
1333
 
1310
1334
    @staticmethod
1335
1359
            # have one so that it doesn't get accidentally
1336
1360
            # exposed.
1337
1361
            netloc = '%s@%s' % (urllib.quote(user), netloc)
1338
 
        if port is not None:
 
1362
        if (port is not None and 
 
1363
            port != transport_list_registry.get_default_port(scheme)):
 
1364
            # Include the port in the netloc (unless it's the same as the
 
1365
            # default, in which case we omit it as it is redundant).
1339
1366
            netloc = '%s:%d' % (netloc, port)
1340
1367
        path = urllib.quote(path)
1341
1368
        return urlparse.urlunparse((scheme, netloc, path, None, None, None))
1644
1671
        raise NotImplementedError
1645
1672
 
1646
1673
 
1647
 
class TransportLogger(object):
1648
 
    """Adapt a transport to get clear logging data on api calls.
1649
 
    
1650
 
    Feel free to extend to log whatever calls are of interest.
1651
 
    """
1652
 
 
1653
 
    def __init__(self, adapted):
1654
 
        self._adapted = adapted
1655
 
        self._calls = []
1656
 
 
1657
 
    def get(self, name):
1658
 
        self._calls.append((name,))
1659
 
        return self._adapted.get(name)
1660
 
 
1661
 
    def __getattr__(self, name):
1662
 
        """Thunk all undefined access through to self._adapted."""
1663
 
        # raise AttributeError, name 
1664
 
        return getattr(self._adapted, name)
1665
 
 
1666
 
    def readv(self, name, offsets):
1667
 
        self._calls.append((name, offsets))
1668
 
        return self._adapted.readv(name, offsets)
1669
 
 
1670
 
 
1671
1674
# None is the default transport, for things with no url scheme
1672
1675
register_transport_proto('file://',
1673
1676
            help="Access using the standard filesystem (default)")
1675
1678
transport_list_registry.set_default_transport("file://")
1676
1679
 
1677
1680
register_transport_proto('sftp://',
1678
 
            help="Access using SFTP (most SSH servers provide SFTP).")
 
1681
            help="Access using SFTP (most SSH servers provide SFTP).",
 
1682
            default_port=22)
1679
1683
register_lazy_transport('sftp://', 'bzrlib.transport.sftp', 'SFTPTransport')
1680
1684
# Decorated http transport
1681
1685
register_transport_proto('http+urllib://',
1682
1686
#                help="Read-only access of branches exported on the web."
1683
 
            )
 
1687
            default_port=80)
1684
1688
register_lazy_transport('http+urllib://', 'bzrlib.transport.http._urllib',
1685
1689
                        'HttpTransport_urllib')
1686
1690
register_transport_proto('https+urllib://',
1687
1691
#                help="Read-only access of branches exported on the web using SSL."
1688
 
            )
 
1692
            default_port=443)
1689
1693
register_lazy_transport('https+urllib://', 'bzrlib.transport.http._urllib',
1690
1694
                        'HttpTransport_urllib')
1691
1695
register_transport_proto('http+pycurl://',
1692
1696
#                help="Read-only access of branches exported on the web."
1693
 
            )
 
1697
            default_port=80)
1694
1698
register_lazy_transport('http+pycurl://', 'bzrlib.transport.http._pycurl',
1695
1699
                        'PyCurlTransport')
1696
1700
register_transport_proto('https+pycurl://',
1697
1701
#                help="Read-only access of branches exported on the web using SSL."
1698
 
            )
 
1702
            default_port=443)
1699
1703
register_lazy_transport('https+pycurl://', 'bzrlib.transport.http._pycurl',
1700
1704
                        'PyCurlTransport')
1701
1705
# Default http transports (last declared wins (if it can be imported))
1702
1706
register_transport_proto('http://',
1703
 
            help="Read-only access of branches exported on the web.")
 
1707
            help="Read-only access of branches exported on the web.",
 
1708
            default_port=80)
1704
1709
register_transport_proto('https://',
1705
 
            help="Read-only access of branches exported on the web using SSL.")
 
1710
            help="Read-only access of branches exported on the web using SSL.",
 
1711
            default_port=443)
1706
1712
register_lazy_transport('http://', 'bzrlib.transport.http._urllib',
1707
1713
                        'HttpTransport_urllib')
1708
1714
register_lazy_transport('https://', 'bzrlib.transport.http._urllib',
1711
1717
register_lazy_transport('https://', 'bzrlib.transport.http._pycurl', 'PyCurlTransport')
1712
1718
 
1713
1719
register_transport_proto('ftp://',
1714
 
            help="Access using passive FTP.")
 
1720
            help="Access using passive FTP.",
 
1721
            default_port=21)
1715
1722
register_lazy_transport('ftp://', 'bzrlib.transport.ftp', 'FtpTransport')
1716
1723
register_transport_proto('aftp://',
1717
 
            help="Access using active FTP.")
 
1724
            help="Access using active FTP.",
 
1725
            default_port=21)
1718
1726
register_lazy_transport('aftp://', 'bzrlib.transport.ftp', 'FtpTransport')
1719
1727
 
1720
1728
register_transport_proto('memory://')
1721
1729
register_lazy_transport('memory://', 'bzrlib.transport.memory', 'MemoryTransport')
 
1730
 
 
1731
# chroots cannot be implicitly accessed, they must be explicitly created:
1722
1732
register_transport_proto('chroot+')
1723
1733
 
1724
1734
register_transport_proto('readonly+',
1729
1739
register_transport_proto('fakenfs+')
1730
1740
register_lazy_transport('fakenfs+', 'bzrlib.transport.fakenfs', 'FakeNFSTransportDecorator')
1731
1741
 
 
1742
register_transport_proto('trace+')
 
1743
register_lazy_transport('trace+', 'bzrlib.transport.trace', 'TransportTraceDecorator')
 
1744
 
1732
1745
register_transport_proto('unlistable+')
1733
1746
register_lazy_transport('unlistable+', 'bzrlib.transport.unlistable', 'UnlistableTransportDecorator')
1734
1747
 
1741
1754
                        'bzrlib.transport.fakevfat',
1742
1755
                        'FakeVFATTransportDecorator')
1743
1756
register_transport_proto('bzr://',
1744
 
            help="Fast access using the Bazaar smart server.")
 
1757
            help="Fast access using the Bazaar smart server.",
 
1758
            default_port=4155)
1745
1759
 
1746
1760
register_lazy_transport('bzr://',
1747
1761
                        'bzrlib.transport.remote',
1748
1762
                        'RemoteTCPTransport')
1749
1763
register_transport_proto('bzr+http://',
1750
1764
#                help="Fast access using the Bazaar smart server over HTTP."
1751
 
             )
 
1765
            default_port=80)
1752
1766
register_lazy_transport('bzr+http://',
1753
1767
                        'bzrlib.transport.remote',
1754
1768
                        'RemoteHTTPTransport')
1758
1772
register_lazy_transport('bzr+https://',
1759
1773
                        'bzrlib.transport.remote',
1760
1774
                        'RemoteHTTPTransport')
 
1775
register_transport_proto('bzr+https://',
 
1776
#                help="Fast access using the Bazaar smart server over HTTPS."
 
1777
             )
 
1778
register_lazy_transport('bzr+https://',
 
1779
                        'bzrlib.transport.remote',
 
1780
                        'RemoteHTTPTransport')
1761
1781
register_transport_proto('bzr+ssh://',
1762
 
            help="Fast access using the Bazaar smart server over SSH.")
 
1782
            help="Fast access using the Bazaar smart server over SSH.",
 
1783
            default_port=22)
1763
1784
register_lazy_transport('bzr+ssh://',
1764
1785
                        'bzrlib.transport.remote',
1765
1786
                        'RemoteSSHTransport')