356
358
# FIXME: share the common code across transports
357
359
assert isinstance(relpath, basestring)
358
relpath = urllib.unquote(relpath).split('/')
360
relpath = urlutils.unescape(relpath).split('/')
359
361
basepath = self._path.split('/')
360
362
if len(basepath) > 0 and basepath[-1] == '':
361
363
basepath = basepath[:-1]
702
704
vendor = _get_ssh_vendor()
703
705
if vendor == 'loopback':
704
706
sock = socket.socket()
705
sock.connect((self._host, self._port))
708
sock.connect((self._host, self._port))
709
except socket.error, e:
710
raise ConnectionError('Unable to connect to SSH host %s:%s: %s'
711
% (self._host, self._port, e))
706
712
self._sftp = SFTPClient(LoopbackSFTP(sock))
707
713
elif vendor != 'none':
708
714
sock = SFTPSubprocess(self._host, vendor, self._port,
723
729
t.set_log_channel('bzr.paramiko')
725
731
except paramiko.SSHException, e:
726
raise ConnectionError('Unable to reach SSH host %s:%d' %
727
(self._host, self._port), e)
732
raise ConnectionError('Unable to reach SSH host %s:%s: %s'
733
% (self._host, self._port, e))
729
735
server_key = t.get_remote_server_key()
730
736
server_key_hex = paramiko.util.hexify(server_key.get_fingerprint())
883
889
nvuQES5C9BMHjF39LZiGH1iLQy7FgdHyoP+eodI7
884
890
-----END RSA PRIVATE KEY-----
888
class SingleListener(threading.Thread):
894
class SocketListener(threading.Thread):
890
896
def __init__(self, callback):
891
897
threading.Thread.__init__(self)
895
901
self._socket.bind(('localhost', 0))
896
902
self._socket.listen(1)
897
903
self.port = self._socket.getsockname()[1]
898
self.stop_event = threading.Event()
901
s, _ = self._socket.accept()
902
# now close the listen socket
905
self._callback(s, self.stop_event)
907
pass #Ignore socket errors
909
# probably a failed test
910
warning('Exception from within unit test server thread: %r' % x)
904
self._stop_event = threading.Event()
913
self.stop_event.set()
907
# called from outside this thread
908
self._stop_event.set()
914
909
# use a timeout here, because if the test fails, the server thread may
915
910
# never notice the stop_event.
916
readable, writable_unused, exception_unused = \
917
select.select([self._socket], [], [], 0.1)
918
if self._stop_event.isSet():
920
if len(readable) == 0:
923
s, addr_unused = self._socket.accept()
924
# because the loopback socket is inline, and transports are
925
# never explicitly closed, best to launch a new thread.
926
threading.Thread(target=self._callback, args=(s,)).start()
927
except socket.error, x:
928
sys.excepthook(*sys.exc_info())
929
warning('Socket error during accept() within unit test server'
932
# probably a failed test; unit test thread will log the
934
sys.excepthook(*sys.exc_info())
935
warning('Exception from within unit test server thread: %r' %
919
939
class SFTPServer(Server):
937
957
"""StubServer uses this to log when a new server is created."""
938
958
self.logs.append(message)
940
def _run_server(self, s, stop_event):
960
def _run_server(self, s):
941
961
ssh_server = paramiko.Transport(s)
942
962
key_file = os.path.join(self._homedir, 'test_rsa.key')
943
file(key_file, 'w').write(STUB_SERVER_KEY)
963
f = open(key_file, 'w')
964
f.write(STUB_SERVER_KEY)
944
966
host_key = paramiko.RSAKey.from_private_key_file(key_file)
945
967
ssh_server.add_server_key(host_key)
946
968
server = StubServer(self)
950
972
event = threading.Event()
951
973
ssh_server.start_server(event, server)
953
stop_event.wait(30.0)
956
977
global _ssh_vendor
957
978
self._original_vendor = _ssh_vendor
958
979
_ssh_vendor = self._vendor
959
self._homedir = os.getcwdu()
980
self._homedir = os.getcwd()
960
981
if self._server_homedir is None:
961
982
self._server_homedir = self._homedir
963
984
# FIXME WINDOWS: _root should be _server_homedir[0]:/
964
self._listener = SingleListener(self._run_server)
985
self._listener = SocketListener(self._run_server)
965
986
self._listener.setDaemon(True)
966
987
self._listener.start()
971
992
self._listener.stop()
972
993
_ssh_vendor = self._original_vendor
995
def get_bogus_url(self):
996
"""See bzrlib.transport.Server.get_bogus_url."""
997
# this is chosen to try to prevent trouble with proxies, wierd dns,
999
return 'sftp://127.0.0.1:1/'
975
1003
class SFTPFullAbsoluteServer(SFTPServer):
976
1004
"""A test server for sftp transports, using absolute urls and ssh."""
978
1006
def get_url(self):
979
1007
"""See bzrlib.transport.Server.get_url."""
980
return self._get_sftp_url(urlescape(self._homedir[1:]))
1008
return self._get_sftp_url(urlutils.escape(self._homedir[1:]))
983
1011
class SFTPServerWithoutSSH(SFTPServer):
987
1015
super(SFTPServerWithoutSSH, self).__init__()
988
1016
self._vendor = 'loopback'
990
def _run_server(self, sock, stop_event):
1018
def _run_server(self, sock):
991
1019
class FakeChannel(object):
992
1020
def get_transport(self):
1012
1040
def get_url(self):
1013
1041
"""See bzrlib.transport.Server.get_url."""
1014
return self._get_sftp_url(urlescape(self._homedir[1:]))
1042
return self._get_sftp_url(urlutils.escape(self._homedir[1:]))
1017
1045
class SFTPHomeDirServer(SFTPServerWithoutSSH):