~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/sftp.py

  • Committer: Robey Pointer
  • Date: 2006-07-01 19:03:33 UTC
  • mfrom: (1829 +trunk)
  • mto: This revision was merged to the branch mainline in revision 1830.
  • Revision ID: robey@lag.net-20060701190333-f58465aec4bd3412
merge from bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
import random
24
24
import re
25
25
import select
 
26
import socket
26
27
import stat
27
28
import subprocess
28
29
import sys
40
41
                           PathError,
41
42
                           ParamikoNotPresent,
42
43
                           )
43
 
from bzrlib.osutils import pathjoin, fancy_rename
 
44
from bzrlib.osutils import pathjoin, fancy_rename, getcwd
44
45
from bzrlib.trace import mutter, warning, error
45
46
from bzrlib.transport import (
46
47
    register_urlparse_netloc_protocol,
101
102
                }
102
103
 
103
104
 
104
 
# don't use prefetch unless paramiko version >= 1.5.2 (there were bugs earlier)
105
 
_default_do_prefetch = False
106
 
if getattr(paramiko, '__version_info__', (0, 0, 0)) >= (1, 5, 5):
107
 
    _default_do_prefetch = True
 
105
_paramiko_version = getattr(paramiko, '__version_info__', (0, 0, 0))
 
106
# don't use prefetch unless paramiko version >= 1.5.5 (there were bugs earlier)
 
107
_default_do_prefetch = (_paramiko_version >= (1, 5, 5))
 
108
 
 
109
# Paramiko 1.5 tries to open a socket.AF_UNIX in order to connect
 
110
# to ssh-agent. That attribute doesn't exist on win32 (it does in cygwin)
 
111
# so we get an AttributeError exception. So we will not try to
 
112
# connect to an agent if we are on win32 and using Paramiko older than 1.6
 
113
_use_ssh_agent = (sys.platform != 'win32' or _paramiko_version >= (1, 6, 0)) 
108
114
 
109
115
 
110
116
_ssh_vendor = None
375
381
                basepath.append(p)
376
382
 
377
383
        path = '/'.join(basepath)
 
384
        # mutter('relpath => remotepath %s => %s', relpath, path)
378
385
        return path
379
386
 
380
387
    def relpath(self, abspath):
498
505
 
499
506
    def mkdir(self, relpath, mode=None):
500
507
        """Create a directory at the given path."""
 
508
        path = self._remote_path(relpath)
501
509
        try:
502
 
            path = self._remote_path(relpath)
503
510
            # In the paramiko documentation, it says that passing a mode flag 
504
511
            # will filtered against the server umask.
505
512
            # StubSFTPServer does not do this, which would be nice, because it is
773
780
        # Also, it would mess up the self.relpath() functionality
774
781
        username = self._username or getpass.getuser()
775
782
 
776
 
        # Paramiko tries to open a socket.AF_UNIX in order to connect
777
 
        # to ssh-agent. That attribute doesn't exist on win32 (it does in cygwin)
778
 
        # so we get an AttributeError exception. For now, just don't try to
779
 
        # connect to an agent if we are on win32
780
 
        if sys.platform != 'win32':
 
783
        if _use_ssh_agent:
781
784
            agent = paramiko.Agent()
782
785
            for key in agent.get_keys():
783
786
                mutter('Trying SSH agent key %s' % paramiko.util.hexify(key.get_fingerprint()))
850
853
        :param mode: The mode permissions bits for the new file
851
854
        """
852
855
        path = self._sftp._adjust_cwd(abspath)
 
856
        # mutter('sftp abspath %s => %s', abspath, path)
853
857
        attr = SFTPAttributes()
854
858
        if mode is not None:
855
859
            attr.st_mode = mode
959
963
 
960
964
    def _run_server(self, s):
961
965
        ssh_server = paramiko.Transport(s)
962
 
        key_file = os.path.join(self._homedir, 'test_rsa.key')
 
966
        key_file = pathjoin(self._homedir, 'test_rsa.key')
963
967
        f = open(key_file, 'w')
964
968
        f.write(STUB_SERVER_KEY)
965
969
        f.close()
977
981
        global _ssh_vendor
978
982
        self._original_vendor = _ssh_vendor
979
983
        _ssh_vendor = self._vendor
980
 
        self._homedir = os.getcwd()
 
984
        if sys.platform == 'win32':
 
985
            # Win32 needs to use the UNICODE api
 
986
            self._homedir = getcwd()
 
987
        else:
 
988
            # But Linux SFTP servers should just deal in bytestreams
 
989
            self._homedir = os.getcwd()
981
990
        if self._server_homedir is None:
982
991
            self._server_homedir = self._homedir
983
992
        self._root = '/'
984
 
        # FIXME WINDOWS: _root should be _server_homedir[0]:/
 
993
        if sys.platform == 'win32':
 
994
            self._root = ''
985
995
        self._listener = SocketListener(self._run_server)
986
996
        self._listener.setDaemon(True)
987
997
        self._listener.start()
1030
1040
 
1031
1041
        server = paramiko.SFTPServer(FakeChannel(), 'sftp', StubServer(self), StubSFTPServer,
1032
1042
                                     root=self._root, home=self._server_homedir)
1033
 
        server.start_subsystem('sftp', None, sock)
 
1043
        try:
 
1044
            server.start_subsystem('sftp', None, sock)
 
1045
        except socket.error, e:
 
1046
            if (len(e.args) > 0) and (e.args[0] == errno.EPIPE):
 
1047
                # it's okay for the client to disconnect abruptly
 
1048
                # (bug in paramiko 1.6: it should absorb this exception)
 
1049
                pass
 
1050
            else:
 
1051
                raise
 
1052
        except Exception, e:
 
1053
            import sys; sys.stderr.write('\nEXCEPTION %r\n\n' % e.__class__)
1034
1054
        server.finish_subsystem()
1035
1055
 
1036
1056
 
1039
1059
 
1040
1060
    def get_url(self):
1041
1061
        """See bzrlib.transport.Server.get_url."""
1042
 
        return self._get_sftp_url(urlutils.escape(self._homedir[1:]))
 
1062
        if sys.platform == 'win32':
 
1063
            return self._get_sftp_url(urlutils.escape(self._homedir))
 
1064
        else:
 
1065
            return self._get_sftp_url(urlutils.escape(self._homedir[1:]))
1043
1066
 
1044
1067
 
1045
1068
class SFTPHomeDirServer(SFTPServerWithoutSSH):