/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: Martin Pool
  • Date: 2007-10-08 07:29:57 UTC
  • mfrom: (2894 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2895.
  • Revision ID: mbp@sourcefrog.net-20071008072957-uhm1gl1mqcsdc377
merge trunk

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):
639
 
        """Get parts of the file at the given relative path.
640
 
 
641
 
        :offsets: A list of (offset, size) tuples.
 
645
    def readv(self, relpath, offsets, adjust_for_latency=False,
 
646
        upper_limit=None):
 
647
        """Get parts of the file at the given relative path.
 
648
 
 
649
        :param relpath: The path to read data from.
 
650
        :param offsets: A list of (offset, size) tuples.
 
651
        :param adjust_for_latency: Adjust the requested offsets to accomdate
 
652
            transport latency. This may re-order the offsets, expand them to
 
653
            grab adjacent data when there is likely a high cost to requesting
 
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.
 
662
        :return: A list or generator of (offset, data) tuples
 
663
        """
 
664
        if adjust_for_latency:
 
665
            offsets = sorted(offsets)
 
666
            # short circuit empty requests
 
667
            if len(offsets) == 0:
 
668
                def empty_yielder():
 
669
                    # Quick thunk to stop this function becoming a generator
 
670
                    # itself, rather we return a generator that has nothing to
 
671
                    # yield.
 
672
                    if False:
 
673
                        yield None
 
674
                return empty_yielder()
 
675
            # expand by page size at either end
 
676
            maximum_expansion = self.recommended_page_size()
 
677
            new_offsets = []
 
678
            for offset, length in offsets:
 
679
                expansion = maximum_expansion - length
 
680
                if expansion < 0:
 
681
                    # we're asking for more than the minimum read anyway.
 
682
                    expansion = 0
 
683
                reduction = expansion / 2
 
684
                new_offset = offset - reduction
 
685
                new_length = length + expansion
 
686
                if new_offset < 0:
 
687
                    # don't ask for anything < 0
 
688
                    new_offset = 0
 
689
                if (upper_limit is not None and
 
690
                    new_offset + new_length > upper_limit):
 
691
                    new_length = upper_limit - new_offset
 
692
                new_offsets.append((new_offset, new_length))
 
693
            # combine the expanded offsets
 
694
            offsets = []
 
695
            current_offset, current_length = new_offsets[0]
 
696
            current_finish = current_length + current_offset
 
697
            for offset, length in new_offsets[1:]:
 
698
                if offset > current_finish:
 
699
                    offsets.append((current_offset, current_length))
 
700
                    current_offset = offset
 
701
                    current_length = length
 
702
                    continue
 
703
                finish = offset + length
 
704
                if finish > current_finish:
 
705
                    current_finish = finish
 
706
            offsets.append((current_offset, current_length))
 
707
        return self._readv(relpath, offsets)
 
708
 
 
709
    def _readv(self, relpath, offsets):
 
710
        """Get parts of the file at the given relative path.
 
711
 
 
712
        :param relpath: The path to read.
 
713
        :param offsets: A list of (offset, size) tuples.
642
714
        :return: A list or generator of (offset, data) tuples
643
715
        """
644
716
        if not offsets:
1256
1328
        host = urllib.unquote(host)
1257
1329
        path = urllib.unquote(path)
1258
1330
 
 
1331
        if port is None:
 
1332
            # The port isn't explicitly specified, so return the default (if
 
1333
            # there is one).
 
1334
            port = transport_list_registry.get_default_port(scheme)
1259
1335
        return (scheme, user, password, host, port, path)
1260
1336
 
1261
1337
    @staticmethod
1286
1362
            # have one so that it doesn't get accidentally
1287
1363
            # exposed.
1288
1364
            netloc = '%s@%s' % (urllib.quote(user), netloc)
1289
 
        if port is not None:
 
1365
        if (port is not None and 
 
1366
            port != transport_list_registry.get_default_port(scheme)):
 
1367
            # Include the port in the netloc (unless it's the same as the
 
1368
            # default, in which case we omit it as it is redundant).
1290
1369
            netloc = '%s:%d' % (netloc, port)
1291
1370
        path = urllib.quote(path)
1292
1371
        return urlparse.urlunparse((scheme, netloc, path, None, None, None))
1595
1674
        raise NotImplementedError
1596
1675
 
1597
1676
 
1598
 
class TransportLogger(object):
1599
 
    """Adapt a transport to get clear logging data on api calls.
1600
 
    
1601
 
    Feel free to extend to log whatever calls are of interest.
1602
 
    """
1603
 
 
1604
 
    def __init__(self, adapted):
1605
 
        self._adapted = adapted
1606
 
        self._calls = []
1607
 
 
1608
 
    def get(self, name):
1609
 
        self._calls.append((name,))
1610
 
        return self._adapted.get(name)
1611
 
 
1612
 
    def __getattr__(self, name):
1613
 
        """Thunk all undefined access through to self._adapted."""
1614
 
        # raise AttributeError, name 
1615
 
        return getattr(self._adapted, name)
1616
 
 
1617
 
    def readv(self, name, offsets):
1618
 
        self._calls.append((name, offsets))
1619
 
        return self._adapted.readv(name, offsets)
1620
 
 
1621
 
 
1622
1677
# None is the default transport, for things with no url scheme
1623
1678
register_transport_proto('file://',
1624
1679
            help="Access using the standard filesystem (default)")
1626
1681
transport_list_registry.set_default_transport("file://")
1627
1682
 
1628
1683
register_transport_proto('sftp://',
1629
 
            help="Access using SFTP (most SSH servers provide SFTP).")
 
1684
            help="Access using SFTP (most SSH servers provide SFTP).",
 
1685
            default_port=22)
1630
1686
register_lazy_transport('sftp://', 'bzrlib.transport.sftp', 'SFTPTransport')
1631
1687
# Decorated http transport
1632
1688
register_transport_proto('http+urllib://',
1633
1689
#                help="Read-only access of branches exported on the web."
1634
 
            )
 
1690
            default_port=80)
1635
1691
register_lazy_transport('http+urllib://', 'bzrlib.transport.http._urllib',
1636
1692
                        'HttpTransport_urllib')
1637
1693
register_transport_proto('https+urllib://',
1638
1694
#                help="Read-only access of branches exported on the web using SSL."
1639
 
            )
 
1695
            default_port=443)
1640
1696
register_lazy_transport('https+urllib://', 'bzrlib.transport.http._urllib',
1641
1697
                        'HttpTransport_urllib')
1642
1698
register_transport_proto('http+pycurl://',
1643
1699
#                help="Read-only access of branches exported on the web."
1644
 
            )
 
1700
            default_port=80)
1645
1701
register_lazy_transport('http+pycurl://', 'bzrlib.transport.http._pycurl',
1646
1702
                        'PyCurlTransport')
1647
1703
register_transport_proto('https+pycurl://',
1648
1704
#                help="Read-only access of branches exported on the web using SSL."
1649
 
            )
 
1705
            default_port=443)
1650
1706
register_lazy_transport('https+pycurl://', 'bzrlib.transport.http._pycurl',
1651
1707
                        'PyCurlTransport')
1652
1708
# Default http transports (last declared wins (if it can be imported))
1653
1709
register_transport_proto('http://',
1654
 
            help="Read-only access of branches exported on the web.")
 
1710
            help="Read-only access of branches exported on the web.",
 
1711
            default_port=80)
1655
1712
register_transport_proto('https://',
1656
 
            help="Read-only access of branches exported on the web using SSL.")
 
1713
            help="Read-only access of branches exported on the web using SSL.",
 
1714
            default_port=443)
1657
1715
register_lazy_transport('http://', 'bzrlib.transport.http._urllib',
1658
1716
                        'HttpTransport_urllib')
1659
1717
register_lazy_transport('https://', 'bzrlib.transport.http._urllib',
1662
1720
register_lazy_transport('https://', 'bzrlib.transport.http._pycurl', 'PyCurlTransport')
1663
1721
 
1664
1722
register_transport_proto('ftp://',
1665
 
            help="Access using passive FTP.")
 
1723
            help="Access using passive FTP.",
 
1724
            default_port=21)
1666
1725
register_lazy_transport('ftp://', 'bzrlib.transport.ftp', 'FtpTransport')
1667
1726
register_transport_proto('aftp://',
1668
 
            help="Access using active FTP.")
 
1727
            help="Access using active FTP.",
 
1728
            default_port=21)
1669
1729
register_lazy_transport('aftp://', 'bzrlib.transport.ftp', 'FtpTransport')
1670
1730
 
1671
1731
register_transport_proto('memory://')
1672
1732
register_lazy_transport('memory://', 'bzrlib.transport.memory', 'MemoryTransport')
 
1733
 
 
1734
# chroots cannot be implicitly accessed, they must be explicitly created:
1673
1735
register_transport_proto('chroot+')
1674
1736
 
1675
1737
register_transport_proto('readonly+',
1680
1742
register_transport_proto('fakenfs+')
1681
1743
register_lazy_transport('fakenfs+', 'bzrlib.transport.fakenfs', 'FakeNFSTransportDecorator')
1682
1744
 
 
1745
register_transport_proto('trace+')
 
1746
register_lazy_transport('trace+', 'bzrlib.transport.trace', 'TransportTraceDecorator')
 
1747
 
1683
1748
register_transport_proto('unlistable+')
1684
1749
register_lazy_transport('unlistable+', 'bzrlib.transport.unlistable', 'UnlistableTransportDecorator')
1685
1750
 
1692
1757
                        'bzrlib.transport.fakevfat',
1693
1758
                        'FakeVFATTransportDecorator')
1694
1759
register_transport_proto('bzr://',
1695
 
            help="Fast access using the Bazaar smart server.")
 
1760
            help="Fast access using the Bazaar smart server.",
 
1761
            default_port=4155)
1696
1762
 
1697
1763
register_lazy_transport('bzr://',
1698
1764
                        'bzrlib.transport.remote',
1699
1765
                        'RemoteTCPTransport')
1700
1766
register_transport_proto('bzr+http://',
1701
1767
#                help="Fast access using the Bazaar smart server over HTTP."
 
1768
            default_port=80)
 
1769
register_lazy_transport('bzr+http://',
 
1770
                        'bzrlib.transport.remote',
 
1771
                        'RemoteHTTPTransport')
 
1772
register_transport_proto('bzr+https://',
 
1773
#                help="Fast access using the Bazaar smart server over HTTPS."
1702
1774
             )
1703
 
register_lazy_transport('bzr+http://',
 
1775
register_lazy_transport('bzr+https://',
1704
1776
                        'bzrlib.transport.remote',
1705
1777
                        'RemoteHTTPTransport')
1706
1778
register_transport_proto('bzr+ssh://',
1707
 
            help="Fast access using the Bazaar smart server over SSH.")
 
1779
            help="Fast access using the Bazaar smart server over SSH.",
 
1780
            default_port=22)
1708
1781
register_lazy_transport('bzr+ssh://',
1709
1782
                        'bzrlib.transport.remote',
1710
1783
                        'RemoteSSHTransport')