/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: Andrew Bennetts
  • Date: 2010-01-12 03:53:21 UTC
  • mfrom: (4948 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4964.
  • Revision ID: andrew.bennetts@canonical.com-20100112035321-hofpz5p10224ryj3
Merge lp:bzr, resolving conflicts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007, 2008, 2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""Transport is an abstraction layer to handle file access.
18
18
 
50
50
        deprecated_method,
51
51
        deprecated_function,
52
52
        DEPRECATED_PARAMETER,
53
 
        one_four,
54
53
        )
55
54
from bzrlib.trace import (
56
55
    mutter,
91
90
                modules.add(factory._module_name)
92
91
            else:
93
92
                modules.add(factory._obj.__module__)
94
 
    # Add chroot directly, because there is no handler registered for it.
 
93
    # Add chroot and pathfilter directly, because there is no handler
 
94
    # registered for it.
95
95
    modules.add('bzrlib.transport.chroot')
 
96
    modules.add('bzrlib.transport.pathfilter')
96
97
    result = list(modules)
97
98
    result.sort()
98
99
    return result
107
108
    register_transport_provider( ) ( and the "lazy" variant )
108
109
 
109
110
    This is needed because:
110
 
    a) a single provider can support multple protcol ( like the ftp
 
111
    a) a single provider can support multiple protocols ( like the ftp
111
112
    provider which supports both the ftp:// and the aftp:// protocols )
112
113
    b) a single protocol can have multiple providers ( like the http://
113
114
    protocol which is supported by both the urllib and pycurl provider )
243
244
 
244
245
class FileFileStream(FileStream):
245
246
    """A file stream object returned by open_write_stream.
246
 
    
 
247
 
247
248
    This version uses a file like object to perform writes.
248
249
    """
249
250
 
260
261
 
261
262
class AppendBasedFileStream(FileStream):
262
263
    """A file stream object returned by open_write_stream.
263
 
    
 
264
 
264
265
    This version uses append on a transport to perform writes.
265
266
    """
266
267
 
273
274
    from/to a storage location.
274
275
 
275
276
    Most functions have a _multi variant, which allows you to queue up
276
 
    multiple requests. They generally have a dumb base implementation 
 
277
    multiple requests. They generally have a dumb base implementation
277
278
    which just iterates over the arguments, but smart Transport
278
279
    implementations can do pipelining.
279
280
    In general implementations should support having a generator or a list
324
325
 
325
326
    def clone(self, offset=None):
326
327
        """Return a new Transport object, cloned from the current location,
327
 
        using a subdirectory or parent directory. This allows connections 
 
328
        using a subdirectory or parent directory. This allows connections
328
329
        to be pooled, rather than a new one needed for each subdir.
329
330
        """
330
331
        raise NotImplementedError(self.clone)
331
332
 
 
333
    def create_prefix(self):
 
334
        """Create all the directories leading down to self.base."""
 
335
        cur_transport = self
 
336
        needed = [cur_transport]
 
337
        # Recurse upwards until we can create a directory successfully
 
338
        while True:
 
339
            new_transport = cur_transport.clone('..')
 
340
            if new_transport.base == cur_transport.base:
 
341
                raise errors.BzrCommandError(
 
342
                    "Failed to create path prefix for %s."
 
343
                    % cur_transport.base)
 
344
            try:
 
345
                new_transport.mkdir('.')
 
346
            except errors.NoSuchFile:
 
347
                needed.append(new_transport)
 
348
                cur_transport = new_transport
 
349
            except errors.FileExists:
 
350
                break
 
351
            else:
 
352
                break
 
353
        # Now we only need to create child directories
 
354
        while needed:
 
355
            cur_transport = needed.pop()
 
356
            cur_transport.ensure_base()
 
357
 
332
358
    def ensure_base(self):
333
359
        """Ensure that the directory this transport references exists.
334
360
 
368
394
        raise NotImplementedError(self.external_url)
369
395
 
370
396
    def _pump(self, from_file, to_file):
371
 
        """Most children will need to copy from one file-like 
 
397
        """Most children will need to copy from one file-like
372
398
        object or string to another one.
373
399
        This just gives them something easy to call.
374
400
        """
452
478
            t._combine_paths('/home/sarah', '/etc')
453
479
                => '/etc'
454
480
 
455
 
        :param base_path: urlencoded path for the transport root; typically a 
 
481
        :param base_path: urlencoded path for the transport root; typically a
456
482
             URL but need not contain scheme/host/etc.
457
483
        :param relpath: relative url string for relative part of remote path.
458
484
        :return: urlencoded string for final path.
485
511
        """Return the recommended page size for this transport.
486
512
 
487
513
        This is potentially different for every path in a given namespace.
488
 
        For example, local transports might use an operating system call to 
 
514
        For example, local transports might use an operating system call to
489
515
        get the block size for a given path, which can vary due to mount
490
516
        points.
491
517
 
497
523
        """Return the local path portion from a given absolute path.
498
524
 
499
525
        This default implementation is not suitable for filesystems with
500
 
        aliasing, such as that given by symlinks, where a path may not 
501
 
        start with our base, but still be a relpath once aliasing is 
 
526
        aliasing, such as that given by symlinks, where a path may not
 
527
        start with our base, but still be a relpath once aliasing is
502
528
        resolved.
503
529
        """
504
530
        # TODO: This might want to use bzrlib.osutils.relpath
516
542
        """
517
543
        raise errors.NotLocalUrl(self.abspath(relpath))
518
544
 
519
 
 
520
545
    def has(self, relpath):
521
546
        """Does the file relpath exist?
522
 
        
 
547
 
523
548
        Note that some transports MAY allow querying on directories, but this
524
 
        is not part of the protocol.  In other words, the results of 
 
549
        is not part of the protocol.  In other words, the results of
525
550
        t.has("a_directory_name") are undefined.
526
551
 
527
552
        :rtype: bool
548
573
        """Iter the relative paths of files in the transports sub-tree.
549
574
 
550
575
        *NOTE*: This only lists *files*, not subdirectories!
551
 
        
 
576
 
552
577
        As with other listing functions, only some transports implement this,.
553
578
        you may check via listable() to determine if it will.
554
579
        """
587
612
        finally:
588
613
            f.close()
589
614
 
590
 
    @deprecated_method(one_four)
591
 
    def get_smart_client(self):
592
 
        """Return a smart client for this transport if possible.
593
 
 
594
 
        A smart client doesn't imply the presence of a smart server: it implies
595
 
        that the smart protocol can be tunnelled via this transport.
596
 
 
597
 
        :raises NoSmartServer: if no smart server client is available.
598
 
        """
599
 
        raise errors.NoSmartServer(self.base)
600
 
 
601
615
    def get_smart_medium(self):
602
616
        """Return a smart client medium for this transport if possible.
603
617
 
608
622
        """
609
623
        raise errors.NoSmartMedium(self)
610
624
 
611
 
    @deprecated_method(one_four)
612
 
    def get_shared_medium(self):
613
 
        """Return a smart client shared medium for this transport if possible.
614
 
 
615
 
        A smart medium doesn't imply the presence of a smart server: it implies
616
 
        that the smart protocol can be tunnelled via this transport.
617
 
 
618
 
        :raises NoSmartMedium: if no smart server medium is available.
619
 
        """
620
 
        raise errors.NoSmartMedium(self)
621
 
 
622
625
    def readv(self, relpath, offsets, adjust_for_latency=False,
623
626
        upper_limit=None):
624
627
        """Get parts of the file at the given relative path.
690
693
        # Cache the results, but only until they have been fulfilled
691
694
        data_map = {}
692
695
        for c_offset in coalesced:
693
 
            # TODO: jam 20060724 it might be faster to not issue seek if 
 
696
            # TODO: jam 20060724 it might be faster to not issue seek if
694
697
            #       we are already at the right location. This should be
695
698
            #       benchmarked.
696
699
            fp.seek(c_offset.start)
845
848
        """Get a list of file-like objects, one for each entry in relpaths.
846
849
 
847
850
        :param relpaths: A list of relative paths.
848
 
        :param pb:  An optional ProgressBar for indicating percent done.
 
851
        :param pb:  An optional ProgressTask for indicating percent done.
849
852
        :return: A list or generator of file-like objects
850
853
        """
851
854
        # TODO: Consider having this actually buffer the requests,
877
880
                             dir_mode=None):
878
881
        """Copy the string into the target location.
879
882
 
880
 
        This function is not strictly safe to use. See 
 
883
        This function is not strictly safe to use. See
881
884
        Transport.put_bytes_non_atomic for more information.
882
885
 
883
886
        :param relpath: The remote location to put the contents.
965
968
        be synchronised with any internal buffering that may be present.
966
969
 
967
970
        :param relpath: The relative path to the file.
968
 
        :param mode: The mode for the newly created file, 
 
971
        :param mode: The mode for the newly created file,
969
972
                     None means just use the default
970
973
        :return: A FileStream. FileStream objects have two methods, write() and
971
974
            close(). There is no guarantee that data is committed to the file
1014
1017
        the supplied location.
1015
1018
 
1016
1019
        :param files: A set of (path, f) entries
1017
 
        :param pb:  An optional ProgressBar for indicating percent done.
 
1020
        :param pb:  An optional ProgressTask for indicating percent done.
1018
1021
        """
1019
1022
        return self._iterate_over(files, self.append_file, pb, 'append', expand=True)
1020
1023
 
1021
1024
    def copy(self, rel_from, rel_to):
1022
1025
        """Copy the item at rel_from to the location at rel_to.
1023
 
        
1024
 
        Override this for efficiency if a specific transport can do it 
 
1026
 
 
1027
        Override this for efficiency if a specific transport can do it
1025
1028
        faster than this default implementation.
1026
1029
        """
1027
1030
        self.put_file(rel_to, self.get(rel_from))
1028
1031
 
1029
1032
    def copy_multi(self, relpaths, pb=None):
1030
1033
        """Copy a bunch of entries.
1031
 
        
 
1034
 
1032
1035
        :param relpaths: A list of tuples of the form [(from, to), (from, to),...]
1033
1036
        """
1034
1037
        # This is the non-pipelined implementation, so that
1052
1055
    def copy_tree(self, from_relpath, to_relpath):
1053
1056
        """Copy a subtree from one relpath to another.
1054
1057
 
1055
 
        If a faster implementation is available, specific transports should 
 
1058
        If a faster implementation is available, specific transports should
1056
1059
        implement it.
1057
1060
        """
1058
1061
        source = self.clone(from_relpath)
1106
1109
 
1107
1110
        The destination is deleted if possible, even if it's a non-empty
1108
1111
        directory tree.
1109
 
        
 
1112
 
1110
1113
        If a transport can directly implement this it is suggested that
1111
1114
        it do so for efficiency.
1112
1115
        """
1119
1122
 
1120
1123
    def move_multi(self, relpaths, pb=None):
1121
1124
        """Move a bunch of entries.
1122
 
        
 
1125
 
1123
1126
        :param relpaths: A list of tuples of the form [(from1, to1), (from2, to2),...]
1124
1127
        """
1125
1128
        return self._iterate_over(relpaths, self.move, pb, 'move', expand=True)
1178
1181
        NOTE: This returns an object with fields such as 'st_size'. It MAY
1179
1182
        or MAY NOT return the literal result of an os.stat() call, so all
1180
1183
        access should be via named fields.
1181
 
        ALSO NOTE: Stats of directories may not be supported on some 
 
1184
        ALSO NOTE: Stats of directories may not be supported on some
1182
1185
        transports.
1183
1186
        """
1184
1187
        raise NotImplementedError(self.stat)
1221
1224
        These methods may be removed in the future.
1222
1225
 
1223
1226
        Transports may raise TransportNotPossible if OS-level locks cannot be
1224
 
        taken over this transport.  
 
1227
        taken over this transport.
1225
1228
 
1226
1229
        :return: A lock object, which should contain an unlock() function.
1227
1230
        """
1248
1251
        """Return true if this transport can store and retrieve unix modebits.
1249
1252
 
1250
1253
        (For example, 0700 to make a directory owner-private.)
1251
 
        
1252
 
        Note: most callers will not want to switch on this, but should rather 
 
1254
 
 
1255
        Note: most callers will not want to switch on this, but should rather
1253
1256
        just try and set permissions and let them be either stored or not.
1254
1257
        This is intended mainly for the use of the test suite.
1255
 
        
1256
 
        Warning: this is not guaranteed to be accurate as sometimes we can't 
 
1258
 
 
1259
        Warning: this is not guaranteed to be accurate as sometimes we can't
1257
1260
        be sure: for example with vfat mounted on unix, or a windows sftp
1258
1261
        server."""
1259
1262
        # TODO: Perhaps return a e.g. TransportCharacteristics that can answer
1357
1360
 
1358
1361
    @staticmethod
1359
1362
    def _split_url(url):
1360
 
        """
1361
 
        Extract the server address, the credentials and the path from the url.
1362
 
 
1363
 
        user, password, host and path should be quoted if they contain reserved
1364
 
        chars.
1365
 
 
1366
 
        :param url: an quoted url
1367
 
 
1368
 
        :return: (scheme, user, password, host, port, path) tuple, all fields
1369
 
            are unquoted.
1370
 
        """
1371
 
        if isinstance(url, unicode):
1372
 
            raise errors.InvalidURL('should be ascii:\n%r' % url)
1373
 
        url = url.encode('utf-8')
1374
 
        (scheme, netloc, path, params,
1375
 
         query, fragment) = urlparse.urlparse(url, allow_fragments=False)
1376
 
        user = password = host = port = None
1377
 
        if '@' in netloc:
1378
 
            user, host = netloc.rsplit('@', 1)
1379
 
            if ':' in user:
1380
 
                user, password = user.split(':', 1)
1381
 
                password = urllib.unquote(password)
1382
 
            user = urllib.unquote(user)
1383
 
        else:
1384
 
            host = netloc
1385
 
 
1386
 
        if ':' in host:
1387
 
            host, port = host.rsplit(':', 1)
1388
 
            try:
1389
 
                port = int(port)
1390
 
            except ValueError:
1391
 
                raise errors.InvalidURL('invalid port number %s in url:\n%s' %
1392
 
                                        (port, url))
1393
 
        if host == '':
1394
 
            raise errors.InvalidURL('Host empty in: %s' % url)
1395
 
 
1396
 
        host = urllib.unquote(host)
1397
 
        path = urllib.unquote(path)
1398
 
 
1399
 
        return (scheme, user, password, host, port, path)
 
1363
        return urlutils.parse_url(url)
1400
1364
 
1401
1365
    @staticmethod
1402
1366
    def _unsplit_url(scheme, user, password, host, port, path):
1428
1392
            netloc = '%s@%s' % (urllib.quote(user), netloc)
1429
1393
        if port is not None:
1430
1394
            netloc = '%s:%d' % (netloc, port)
1431
 
        path = urllib.quote(path)
 
1395
        path = urlutils.escape(path)
1432
1396
        return urlparse.urlunparse((scheme, netloc, path, None, None, None))
1433
1397
 
1434
1398
    def relpath(self, abspath):
1453
1417
 
1454
1418
    def abspath(self, relpath):
1455
1419
        """Return the full url to the given relative path.
1456
 
        
 
1420
 
1457
1421
        :param relpath: the relative path urlencoded
1458
1422
 
1459
1423
        :returns: the Unicode version of the absolute path for relpath.
1519
1483
 
1520
1484
        Some protocols can renegociate the credentials within a connection,
1521
1485
        this method allows daughter classes to share updated credentials.
1522
 
        
 
1486
 
1523
1487
        :param credentials: the updated credentials.
1524
1488
        """
1525
1489
        # We don't want to call _set_connection here as we are only updating
1593
1557
    def convert_path_to_url(base, error_str):
1594
1558
        m = _urlRE.match(base)
1595
1559
        if m:
1596
 
            # This looks like a URL, but we weren't able to 
 
1560
            # This looks like a URL, but we weren't able to
1597
1561
            # instantiate it as such raise an appropriate error
1598
1562
            # FIXME: we have a 'error_str' unused and we use last_err below
1599
1563
            raise errors.UnsupportedProtocol(base, last_err)
1665
1629
    :param action: A callable, what the caller want to do while catching
1666
1630
                  redirections.
1667
1631
    :param transport: The initial transport used.
1668
 
    :param redirected: A callable receiving the redirected transport and the 
 
1632
    :param redirected: A callable receiving the redirected transport and the
1669
1633
                  RedirectRequested exception.
1670
1634
 
1671
1635
    :return: Whatever 'action' returns
1698
1662
 
1699
1663
class Server(object):
1700
1664
    """A Transport Server.
1701
 
    
 
1665
 
1702
1666
    The Server interface provides a server for a given transport. We use
1703
1667
    these servers as loopback testing tools. For any given transport the
1704
1668
    Servers it provides must either allow writing, or serve the contents
1705
 
    of os.getcwdu() at the time setUp is called.
1706
 
    
 
1669
    of os.getcwdu() at the time start_server is called.
 
1670
 
1707
1671
    Note that these are real servers - they must implement all the things
1708
1672
    that we want bzr transports to take advantage of.
1709
1673
    """
1710
1674
 
1711
 
    def setUp(self):
 
1675
    def start_server(self):
1712
1676
        """Setup the server to service requests."""
1713
1677
 
1714
 
    def tearDown(self):
 
1678
    def stop_server(self):
1715
1679
        """Remove the server and cleanup any resources it owns."""
1716
1680
 
1717
1681
    def get_url(self):
1718
1682
        """Return a url for this server.
1719
 
        
1720
 
        If the transport does not represent a disk directory (i.e. it is 
 
1683
 
 
1684
        If the transport does not represent a disk directory (i.e. it is
1721
1685
        a database like svn, or a memory only transport, it should return
1722
1686
        a connection to a newly established resource for this Server.
1723
1687
        Otherwise it should return a url that will provide access to the path
1724
 
        that was os.getcwdu() when setUp() was called.
1725
 
        
 
1688
        that was os.getcwdu() when start_server() was called.
 
1689
 
1726
1690
        Subsequent calls will return the same resource.
1727
1691
        """
1728
1692
        raise NotImplementedError
1729
1693
 
1730
1694
    def get_bogus_url(self):
1731
1695
        """Return a url for this protocol, that will fail to connect.
1732
 
        
 
1696
 
1733
1697
        This may raise NotImplementedError to indicate that this server cannot
1734
1698
        provide bogus urls.
1735
1699
        """
1787
1751
register_transport_proto('aftp://', help="Access using active FTP.")
1788
1752
register_lazy_transport('aftp://', 'bzrlib.transport.ftp', 'FtpTransport')
1789
1753
 
1790
 
# Default to trying GSSAPI authentication (if the kerberos module is available)
1791
 
register_transport_proto('ftp+gssapi://', register_netloc=True)
1792
 
register_lazy_transport('ftp+gssapi://', 'bzrlib.transport.ftp._gssapi', 
1793
 
                        'GSSAPIFtpTransport')
1794
 
register_transport_proto('aftp+gssapi://', register_netloc=True)
1795
 
register_lazy_transport('aftp+gssapi://', 'bzrlib.transport.ftp._gssapi', 
1796
 
                        'GSSAPIFtpTransport')
1797
 
register_transport_proto('ftp+nogssapi://', register_netloc=True)
1798
 
register_transport_proto('aftp+nogssapi://', register_netloc=True)
1799
 
 
1800
 
register_lazy_transport('ftp://', 'bzrlib.transport.ftp._gssapi', 
1801
 
                        'GSSAPIFtpTransport')
1802
 
register_lazy_transport('aftp://', 'bzrlib.transport.ftp._gssapi', 
1803
 
                        'GSSAPIFtpTransport')
1804
 
register_lazy_transport('ftp+nogssapi://', 'bzrlib.transport.ftp', 
1805
 
                        'FtpTransport')
1806
 
register_lazy_transport('aftp+nogssapi://', 'bzrlib.transport.ftp', 
1807
 
                        'FtpTransport')
 
1754
try:
 
1755
    import kerberos
 
1756
    kerberos_available = True
 
1757
except ImportError:
 
1758
    kerberos_available = False
 
1759
 
 
1760
if kerberos_available:
 
1761
    # Default to trying GSSAPI authentication (if the kerberos module is
 
1762
    # available)
 
1763
    register_transport_proto('ftp+gssapi://', register_netloc=True)
 
1764
    register_lazy_transport('ftp+gssapi://', 'bzrlib.transport.ftp._gssapi',
 
1765
                            'GSSAPIFtpTransport')
 
1766
    register_transport_proto('aftp+gssapi://', register_netloc=True)
 
1767
    register_lazy_transport('aftp+gssapi://', 'bzrlib.transport.ftp._gssapi',
 
1768
                            'GSSAPIFtpTransport')
 
1769
    register_transport_proto('ftp+nogssapi://', register_netloc=True)
 
1770
    register_transport_proto('aftp+nogssapi://', register_netloc=True)
 
1771
 
 
1772
    register_lazy_transport('ftp://', 'bzrlib.transport.ftp._gssapi',
 
1773
                            'GSSAPIFtpTransport')
 
1774
    register_lazy_transport('aftp://', 'bzrlib.transport.ftp._gssapi',
 
1775
                            'GSSAPIFtpTransport')
 
1776
    register_lazy_transport('ftp+nogssapi://', 'bzrlib.transport.ftp',
 
1777
                            'FtpTransport')
 
1778
    register_lazy_transport('aftp+nogssapi://', 'bzrlib.transport.ftp',
 
1779
                            'FtpTransport')
1808
1780
 
1809
1781
register_transport_proto('memory://')
1810
1782
register_lazy_transport('memory://', 'bzrlib.transport.memory',
1879
1851
            register_netloc=True)
1880
1852
register_lazy_transport('bzr+ssh://', 'bzrlib.transport.remote',
1881
1853
                        'RemoteSSHTransport')
 
1854
 
 
1855
register_transport_proto('ssh:')
 
1856
register_lazy_transport('ssh:', 'bzrlib.transport.remote',
 
1857
                        'HintingSSHTransport')
 
1858
 
 
1859
 
 
1860
transport_server_registry = registry.Registry()
 
1861
transport_server_registry.register_lazy('bzr', 'bzrlib.smart.server', 
 
1862
    'serve_bzr', help="The Bazaar smart server protocol over TCP. (default port: 4155)")
 
1863
transport_server_registry.default_key = 'bzr'