34
34
from bzrlib.branch import Branch
35
35
from bzrlib.bzrdir import BzrDir
36
from bzrlib.errors import ParamikoNotPresent
37
36
from bzrlib.smart import client, medium
38
37
from bzrlib.smart.server import SmartTCPServer
39
from bzrlib.tests import TestCaseWithTransport, TestSkipped
38
from bzrlib.tests import ParamikoFeature, TestCaseWithTransport, TestSkipped
40
39
from bzrlib.trace import mutter
41
40
from bzrlib.transport import get_transport, remote
162
161
self.make_read_requests(branch)
163
162
self.assertServerFinishesCleanly(process)
165
def test_bzr_connect_to_bzr_ssh(self):
166
"""User acceptance that get_transport of a bzr+ssh:// behaves correctly.
168
bzr+ssh:// should cause bzr to run a remote bzr smart server over SSH.
171
# SFTPFullAbsoluteServer has a get_url method, and doesn't
172
# override the interface (doesn't change self._vendor).
173
from bzrlib.transport.sftp import SFTPFullAbsoluteServer
174
except ParamikoNotPresent:
175
raise TestSkipped('Paramiko not installed')
176
from bzrlib.tests.stub_sftp import StubServer
179
self.make_branch('a_branch')
181
# Start an SSH server
182
self.command_executed = []
183
# XXX: This is horrible -- we define a really dumb SSH server that
184
# executes commands, and manage the hooking up of stdin/out/err to the
185
# SSH channel ourselves. Surely this has already been implemented
187
class StubSSHServer(StubServer):
191
def check_channel_exec_request(self, channel, command):
192
self.test.command_executed.append(command)
193
proc = subprocess.Popen(
194
command, shell=True, stdin=subprocess.PIPE,
195
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
197
# XXX: horribly inefficient, not to mention ugly.
198
# Start a thread for each of stdin/out/err, and relay bytes from
199
# the subprocess to channel and vice versa.
200
def ferry_bytes(read, write, close):
209
(channel.recv, proc.stdin.write, proc.stdin.close),
210
(proc.stdout.read, channel.sendall, channel.close),
211
(proc.stderr.read, channel.sendall_stderr, channel.close)]
212
for read, write, close in file_functions:
213
t = threading.Thread(
214
target=ferry_bytes, args=(read, write, close))
219
ssh_server = SFTPFullAbsoluteServer(StubSSHServer)
220
# XXX: We *don't* want to override the default SSH vendor, so we set
221
# _vendor to what _get_ssh_vendor returns.
222
self.start_server(ssh_server)
223
port = ssh_server._listener.port
225
# Access the branch via a bzr+ssh URL. The BZR_REMOTE_PATH environment
226
# variable is used to tell bzr what command to run on the remote end.
227
path_to_branch = osutils.abspath('a_branch')
229
orig_bzr_remote_path = os.environ.get('BZR_REMOTE_PATH')
230
bzr_remote_path = self.get_bzr_path()
231
if sys.platform == 'win32':
232
bzr_remote_path = sys.executable + ' ' + self.get_bzr_path()
233
os.environ['BZR_REMOTE_PATH'] = bzr_remote_path
235
if sys.platform == 'win32':
236
path_to_branch = os.path.splitdrive(path_to_branch)[1]
237
url_suffix = '@localhost:%d%s' % (port, path_to_branch)
238
self.permit_url('bzr+ssh://fred' + url_suffix)
239
branch = Branch.open('bzr+ssh://fred:secret' + url_suffix)
240
self.make_read_requests(branch)
241
# Check we can perform write operations
242
branch.bzrdir.root_transport.mkdir('foo')
244
# Restore the BZR_REMOTE_PATH environment variable back to its
246
if orig_bzr_remote_path is None:
247
del os.environ['BZR_REMOTE_PATH']
249
os.environ['BZR_REMOTE_PATH'] = orig_bzr_remote_path
252
['%s serve --inet --directory=/ --allow-writes'
254
self.command_executed)
257
165
class TestCmdServeChrooting(TestCaseWithTransport):