~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/__init__.py

  • Committer: Matt Nordhoff
  • Date: 2009-04-04 02:50:01 UTC
  • mfrom: (4253 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4256.
  • Revision ID: mnordhoff@mattnordhoff.com-20090404025001-z1403k0tatmc8l91
Merge bzr.dev, fixing conflicts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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,
243
242
 
244
243
class FileFileStream(FileStream):
245
244
    """A file stream object returned by open_write_stream.
246
 
    
 
245
 
247
246
    This version uses a file like object to perform writes.
248
247
    """
249
248
 
260
259
 
261
260
class AppendBasedFileStream(FileStream):
262
261
    """A file stream object returned by open_write_stream.
263
 
    
 
262
 
264
263
    This version uses append on a transport to perform writes.
265
264
    """
266
265
 
273
272
    from/to a storage location.
274
273
 
275
274
    Most functions have a _multi variant, which allows you to queue up
276
 
    multiple requests. They generally have a dumb base implementation 
 
275
    multiple requests. They generally have a dumb base implementation
277
276
    which just iterates over the arguments, but smart Transport
278
277
    implementations can do pipelining.
279
278
    In general implementations should support having a generator or a list
324
323
 
325
324
    def clone(self, offset=None):
326
325
        """Return a new Transport object, cloned from the current location,
327
 
        using a subdirectory or parent directory. This allows connections 
 
326
        using a subdirectory or parent directory. This allows connections
328
327
        to be pooled, rather than a new one needed for each subdir.
329
328
        """
330
329
        raise NotImplementedError(self.clone)
368
367
        raise NotImplementedError(self.external_url)
369
368
 
370
369
    def _pump(self, from_file, to_file):
371
 
        """Most children will need to copy from one file-like 
 
370
        """Most children will need to copy from one file-like
372
371
        object or string to another one.
373
372
        This just gives them something easy to call.
374
373
        """
452
451
            t._combine_paths('/home/sarah', '/etc')
453
452
                => '/etc'
454
453
 
455
 
        :param base_path: urlencoded path for the transport root; typically a 
 
454
        :param base_path: urlencoded path for the transport root; typically a
456
455
             URL but need not contain scheme/host/etc.
457
456
        :param relpath: relative url string for relative part of remote path.
458
457
        :return: urlencoded string for final path.
485
484
        """Return the recommended page size for this transport.
486
485
 
487
486
        This is potentially different for every path in a given namespace.
488
 
        For example, local transports might use an operating system call to 
 
487
        For example, local transports might use an operating system call to
489
488
        get the block size for a given path, which can vary due to mount
490
489
        points.
491
490
 
497
496
        """Return the local path portion from a given absolute path.
498
497
 
499
498
        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 
 
499
        aliasing, such as that given by symlinks, where a path may not
 
500
        start with our base, but still be a relpath once aliasing is
502
501
        resolved.
503
502
        """
504
503
        # TODO: This might want to use bzrlib.osutils.relpath
519
518
 
520
519
    def has(self, relpath):
521
520
        """Does the file relpath exist?
522
 
        
 
521
 
523
522
        Note that some transports MAY allow querying on directories, but this
524
 
        is not part of the protocol.  In other words, the results of 
 
523
        is not part of the protocol.  In other words, the results of
525
524
        t.has("a_directory_name") are undefined.
526
525
 
527
526
        :rtype: bool
548
547
        """Iter the relative paths of files in the transports sub-tree.
549
548
 
550
549
        *NOTE*: This only lists *files*, not subdirectories!
551
 
        
 
550
 
552
551
        As with other listing functions, only some transports implement this,.
553
552
        you may check via listable() to determine if it will.
554
553
        """
587
586
        finally:
588
587
            f.close()
589
588
 
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
589
    def get_smart_medium(self):
602
590
        """Return a smart client medium for this transport if possible.
603
591
 
608
596
        """
609
597
        raise errors.NoSmartMedium(self)
610
598
 
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
599
    def readv(self, relpath, offsets, adjust_for_latency=False,
623
600
        upper_limit=None):
624
601
        """Get parts of the file at the given relative path.
690
667
        # Cache the results, but only until they have been fulfilled
691
668
        data_map = {}
692
669
        for c_offset in coalesced:
693
 
            # TODO: jam 20060724 it might be faster to not issue seek if 
 
670
            # TODO: jam 20060724 it might be faster to not issue seek if
694
671
            #       we are already at the right location. This should be
695
672
            #       benchmarked.
696
673
            fp.seek(c_offset.start)
877
854
                             dir_mode=None):
878
855
        """Copy the string into the target location.
879
856
 
880
 
        This function is not strictly safe to use. See 
 
857
        This function is not strictly safe to use. See
881
858
        Transport.put_bytes_non_atomic for more information.
882
859
 
883
860
        :param relpath: The remote location to put the contents.
965
942
        be synchronised with any internal buffering that may be present.
966
943
 
967
944
        :param relpath: The relative path to the file.
968
 
        :param mode: The mode for the newly created file, 
 
945
        :param mode: The mode for the newly created file,
969
946
                     None means just use the default
970
947
        :return: A FileStream. FileStream objects have two methods, write() and
971
948
            close(). There is no guarantee that data is committed to the file
1020
997
 
1021
998
    def copy(self, rel_from, rel_to):
1022
999
        """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 
 
1000
 
 
1001
        Override this for efficiency if a specific transport can do it
1025
1002
        faster than this default implementation.
1026
1003
        """
1027
1004
        self.put_file(rel_to, self.get(rel_from))
1028
1005
 
1029
1006
    def copy_multi(self, relpaths, pb=None):
1030
1007
        """Copy a bunch of entries.
1031
 
        
 
1008
 
1032
1009
        :param relpaths: A list of tuples of the form [(from, to), (from, to),...]
1033
1010
        """
1034
1011
        # This is the non-pipelined implementation, so that
1052
1029
    def copy_tree(self, from_relpath, to_relpath):
1053
1030
        """Copy a subtree from one relpath to another.
1054
1031
 
1055
 
        If a faster implementation is available, specific transports should 
 
1032
        If a faster implementation is available, specific transports should
1056
1033
        implement it.
1057
1034
        """
1058
1035
        source = self.clone(from_relpath)
1106
1083
 
1107
1084
        The destination is deleted if possible, even if it's a non-empty
1108
1085
        directory tree.
1109
 
        
 
1086
 
1110
1087
        If a transport can directly implement this it is suggested that
1111
1088
        it do so for efficiency.
1112
1089
        """
1119
1096
 
1120
1097
    def move_multi(self, relpaths, pb=None):
1121
1098
        """Move a bunch of entries.
1122
 
        
 
1099
 
1123
1100
        :param relpaths: A list of tuples of the form [(from1, to1), (from2, to2),...]
1124
1101
        """
1125
1102
        return self._iterate_over(relpaths, self.move, pb, 'move', expand=True)
1178
1155
        NOTE: This returns an object with fields such as 'st_size'. It MAY
1179
1156
        or MAY NOT return the literal result of an os.stat() call, so all
1180
1157
        access should be via named fields.
1181
 
        ALSO NOTE: Stats of directories may not be supported on some 
 
1158
        ALSO NOTE: Stats of directories may not be supported on some
1182
1159
        transports.
1183
1160
        """
1184
1161
        raise NotImplementedError(self.stat)
1221
1198
        These methods may be removed in the future.
1222
1199
 
1223
1200
        Transports may raise TransportNotPossible if OS-level locks cannot be
1224
 
        taken over this transport.  
 
1201
        taken over this transport.
1225
1202
 
1226
1203
        :return: A lock object, which should contain an unlock() function.
1227
1204
        """
1248
1225
        """Return true if this transport can store and retrieve unix modebits.
1249
1226
 
1250
1227
        (For example, 0700 to make a directory owner-private.)
1251
 
        
1252
 
        Note: most callers will not want to switch on this, but should rather 
 
1228
 
 
1229
        Note: most callers will not want to switch on this, but should rather
1253
1230
        just try and set permissions and let them be either stored or not.
1254
1231
        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 
 
1232
 
 
1233
        Warning: this is not guaranteed to be accurate as sometimes we can't
1257
1234
        be sure: for example with vfat mounted on unix, or a windows sftp
1258
1235
        server."""
1259
1236
        # TODO: Perhaps return a e.g. TransportCharacteristics that can answer
1453
1430
 
1454
1431
    def abspath(self, relpath):
1455
1432
        """Return the full url to the given relative path.
1456
 
        
 
1433
 
1457
1434
        :param relpath: the relative path urlencoded
1458
1435
 
1459
1436
        :returns: the Unicode version of the absolute path for relpath.
1519
1496
 
1520
1497
        Some protocols can renegociate the credentials within a connection,
1521
1498
        this method allows daughter classes to share updated credentials.
1522
 
        
 
1499
 
1523
1500
        :param credentials: the updated credentials.
1524
1501
        """
1525
1502
        # We don't want to call _set_connection here as we are only updating
1593
1570
    def convert_path_to_url(base, error_str):
1594
1571
        m = _urlRE.match(base)
1595
1572
        if m:
1596
 
            # This looks like a URL, but we weren't able to 
 
1573
            # This looks like a URL, but we weren't able to
1597
1574
            # instantiate it as such raise an appropriate error
1598
1575
            # FIXME: we have a 'error_str' unused and we use last_err below
1599
1576
            raise errors.UnsupportedProtocol(base, last_err)
1665
1642
    :param action: A callable, what the caller want to do while catching
1666
1643
                  redirections.
1667
1644
    :param transport: The initial transport used.
1668
 
    :param redirected: A callable receiving the redirected transport and the 
 
1645
    :param redirected: A callable receiving the redirected transport and the
1669
1646
                  RedirectRequested exception.
1670
1647
 
1671
1648
    :return: Whatever 'action' returns
1698
1675
 
1699
1676
class Server(object):
1700
1677
    """A Transport Server.
1701
 
    
 
1678
 
1702
1679
    The Server interface provides a server for a given transport. We use
1703
1680
    these servers as loopback testing tools. For any given transport the
1704
1681
    Servers it provides must either allow writing, or serve the contents
1705
1682
    of os.getcwdu() at the time setUp is called.
1706
 
    
 
1683
 
1707
1684
    Note that these are real servers - they must implement all the things
1708
1685
    that we want bzr transports to take advantage of.
1709
1686
    """
1716
1693
 
1717
1694
    def get_url(self):
1718
1695
        """Return a url for this server.
1719
 
        
1720
 
        If the transport does not represent a disk directory (i.e. it is 
 
1696
 
 
1697
        If the transport does not represent a disk directory (i.e. it is
1721
1698
        a database like svn, or a memory only transport, it should return
1722
1699
        a connection to a newly established resource for this Server.
1723
1700
        Otherwise it should return a url that will provide access to the path
1724
1701
        that was os.getcwdu() when setUp() was called.
1725
 
        
 
1702
 
1726
1703
        Subsequent calls will return the same resource.
1727
1704
        """
1728
1705
        raise NotImplementedError
1729
1706
 
1730
1707
    def get_bogus_url(self):
1731
1708
        """Return a url for this protocol, that will fail to connect.
1732
 
        
 
1709
 
1733
1710
        This may raise NotImplementedError to indicate that this server cannot
1734
1711
        provide bogus urls.
1735
1712
        """
1787
1764
register_transport_proto('aftp://', help="Access using active FTP.")
1788
1765
register_lazy_transport('aftp://', 'bzrlib.transport.ftp', 'FtpTransport')
1789
1766
 
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')
 
1767
try:
 
1768
    import kerberos
 
1769
    kerberos_available = True
 
1770
except ImportError:
 
1771
    kerberos_available = False
 
1772
 
 
1773
if kerberos_available:
 
1774
    # Default to trying GSSAPI authentication (if the kerberos module is
 
1775
    # available)
 
1776
    register_transport_proto('ftp+gssapi://', register_netloc=True)
 
1777
    register_lazy_transport('ftp+gssapi://', 'bzrlib.transport.ftp._gssapi',
 
1778
                            'GSSAPIFtpTransport')
 
1779
    register_transport_proto('aftp+gssapi://', register_netloc=True)
 
1780
    register_lazy_transport('aftp+gssapi://', 'bzrlib.transport.ftp._gssapi',
 
1781
                            'GSSAPIFtpTransport')
 
1782
    register_transport_proto('ftp+nogssapi://', register_netloc=True)
 
1783
    register_transport_proto('aftp+nogssapi://', register_netloc=True)
 
1784
 
 
1785
    register_lazy_transport('ftp://', 'bzrlib.transport.ftp._gssapi',
 
1786
                            'GSSAPIFtpTransport')
 
1787
    register_lazy_transport('aftp://', 'bzrlib.transport.ftp._gssapi',
 
1788
                            'GSSAPIFtpTransport')
 
1789
    register_lazy_transport('ftp+nogssapi://', 'bzrlib.transport.ftp',
 
1790
                            'FtpTransport')
 
1791
    register_lazy_transport('aftp+nogssapi://', 'bzrlib.transport.ftp',
 
1792
                            'FtpTransport')
1808
1793
 
1809
1794
register_transport_proto('memory://')
1810
1795
register_lazy_transport('memory://', 'bzrlib.transport.memory',
1881
1866
                        'RemoteSSHTransport')
1882
1867
 
1883
1868
register_transport_proto('ssh:')
1884
 
register_lazy_transport('ssh:', 'bzrlib.transport.remote', 
 
1869
register_lazy_transport('ssh:', 'bzrlib.transport.remote',
1885
1870
                        'HintingSSHTransport')