/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/tests/stub_sftp.py

  • Committer: Robert Collins
  • Date: 2010-05-06 23:41:35 UTC
  • mto: This revision was merged to the branch mainline in revision 5223.
  • Revision ID: robertc@robertcollins.net-20100506234135-yivbzczw1sejxnxc
Lock methods on ``Tree``, ``Branch`` and ``Repository`` are now
expected to return an object which can be used to unlock them. This reduces
duplicate code when using cleanups. The previous 'tokens's returned by
``Branch.lock_write`` and ``Repository.lock_write`` are now attributes
on the result of the lock_write. ``repository.RepositoryWriteLockResult``
and ``branch.BranchWriteLockResult`` document this. (Robert Collins)

``log._get_info_for_log_files`` now takes an add_cleanup callable.
(Robert Collins)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2008-2011 Robey Pointer <robey@lag.net>, Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2008, 2009, 2010 Robey Pointer <robey@lag.net>, 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
21
21
 
22
22
import os
23
23
import paramiko
 
24
import select
24
25
import socket
25
 
try:
26
 
    import socketserver
27
 
except ImportError:
28
 
    import SocketServer as socketserver
29
26
import sys
 
27
import threading
30
28
import time
31
29
 
32
 
from .. import (
 
30
from bzrlib import (
33
31
    osutils,
34
32
    trace,
35
33
    urlutils,
36
34
    )
37
 
from ..transport import (
 
35
from bzrlib.transport import (
38
36
    ssh,
39
37
    )
40
 
from . import test_server
41
 
 
42
 
 
43
 
class StubServer(paramiko.ServerInterface):
44
 
 
45
 
    def __init__(self, test_case_server):
 
38
from bzrlib.tests import test_server
 
39
 
 
40
 
 
41
class StubServer (paramiko.ServerInterface):
 
42
 
 
43
    def __init__(self, test_case):
46
44
        paramiko.ServerInterface.__init__(self)
47
 
        self.log = test_case_server.log
 
45
        self._test_case = test_case
48
46
 
49
47
    def check_auth_password(self, username, password):
50
48
        # all are allowed
51
 
        self.log('sftpserver - authorizing: %s' % (username,))
 
49
        self._test_case.log('sftpserver - authorizing: %s' % (username,))
52
50
        return paramiko.AUTH_SUCCESSFUL
53
51
 
54
52
    def check_channel_request(self, kind, chanid):
55
 
        self.log('sftpserver - channel request: %s, %s' % (kind, chanid))
 
53
        self._test_case.log(
 
54
            'sftpserver - channel request: %s, %s' % (kind, chanid))
56
55
        return paramiko.OPEN_SUCCEEDED
57
56
 
58
57
 
59
 
class StubSFTPHandle(paramiko.SFTPHandle):
60
 
 
 
58
class StubSFTPHandle (paramiko.SFTPHandle):
61
59
    def stat(self):
62
60
        try:
63
61
            return paramiko.SFTPAttributes.from_stat(
64
62
                os.fstat(self.readfile.fileno()))
65
 
        except OSError as e:
 
63
        except OSError, e:
66
64
            return paramiko.SFTPServer.convert_errno(e.errno)
67
65
 
68
66
    def chattr(self, attr):
71
69
        trace.mutter('Changing permissions on %s to %s', self.filename, attr)
72
70
        try:
73
71
            paramiko.SFTPServer.set_file_attr(self.filename, attr)
74
 
        except OSError as e:
 
72
        except OSError, e:
75
73
            return paramiko.SFTPServer.convert_errno(e.errno)
76
74
 
77
75
 
78
 
class StubSFTPServer(paramiko.SFTPServerInterface):
 
76
class StubSFTPServer (paramiko.SFTPServerInterface):
79
77
 
80
78
    def __init__(self, server, root, home=None):
81
79
        paramiko.SFTPServerInterface.__init__(self, server)
92
90
            self.home = home[len(self.root):]
93
91
        if self.home.startswith('/'):
94
92
            self.home = self.home[1:]
95
 
        server.log('sftpserver - new connection')
 
93
        server._test_case.log('sftpserver - new connection')
96
94
 
97
95
    def _realpath(self, path):
98
96
        # paths returned from self.canonicalize() always start with
121
119
    else:
122
120
        def canonicalize(self, path):
123
121
            if os.path.isabs(path):
124
 
                return osutils.normpath(path)
 
122
                return os.path.normpath(path)
125
123
            else:
126
 
                return osutils.normpath('/' + os.path.join(self.home, path))
 
124
                return os.path.normpath('/' + os.path.join(self.home, path))
127
125
 
128
126
    def chattr(self, path, attr):
129
127
        try:
130
128
            paramiko.SFTPServer.set_file_attr(path, attr)
131
 
        except OSError as e:
 
129
        except OSError, e:
132
130
            return paramiko.SFTPServer.convert_errno(e.errno)
133
131
        return paramiko.SFTP_OK
134
132
 
135
133
    def list_folder(self, path):
136
134
        path = self._realpath(path)
137
135
        try:
138
 
            out = []
 
136
            out = [ ]
139
137
            # TODO: win32 incorrectly lists paths with non-ascii if path is not
140
 
            # unicode. However on unix the server should only deal with
 
138
            # unicode. However on Linux the server should only deal with
141
139
            # bytestreams and posix.listdir does the right thing
142
140
            if sys.platform == 'win32':
143
141
                flist = [f.encode('utf8') for f in os.listdir(path)]
149
147
                attr.filename = fname
150
148
                out.append(attr)
151
149
            return out
152
 
        except OSError as e:
 
150
        except OSError, e:
153
151
            return paramiko.SFTPServer.convert_errno(e.errno)
154
152
 
155
153
    def stat(self, path):
156
154
        path = self._realpath(path)
157
155
        try:
158
156
            return paramiko.SFTPAttributes.from_stat(os.stat(path))
159
 
        except OSError as e:
 
157
        except OSError, e:
160
158
            return paramiko.SFTPServer.convert_errno(e.errno)
161
159
 
162
160
    def lstat(self, path):
163
161
        path = self._realpath(path)
164
162
        try:
165
163
            return paramiko.SFTPAttributes.from_stat(os.lstat(path))
166
 
        except OSError as e:
 
164
        except OSError, e:
167
165
            return paramiko.SFTPServer.convert_errno(e.errno)
168
166
 
169
167
    def open(self, path, flags, attr):
175
173
            else:
176
174
                # os.open() defaults to 0777 which is
177
175
                # an odd default mode for files
178
 
                fd = os.open(path, flags, 0o666)
179
 
        except OSError as e:
 
176
                fd = os.open(path, flags, 0666)
 
177
        except OSError, e:
180
178
            return paramiko.SFTPServer.convert_errno(e.errno)
181
179
 
182
180
        if (flags & os.O_CREAT) and (attr is not None):
191
189
            fstr = 'rb'
192
190
        try:
193
191
            f = os.fdopen(fd, fstr)
194
 
        except (IOError, OSError) as e:
 
192
        except (IOError, OSError), e:
195
193
            return paramiko.SFTPServer.convert_errno(e.errno)
196
194
        fobj = StubSFTPHandle()
197
195
        fobj.filename = path
203
201
        path = self._realpath(path)
204
202
        try:
205
203
            os.remove(path)
206
 
        except OSError as e:
 
204
        except OSError, e:
207
205
            return paramiko.SFTPServer.convert_errno(e.errno)
208
206
        return paramiko.SFTP_OK
209
207
 
212
210
        newpath = self._realpath(newpath)
213
211
        try:
214
212
            os.rename(oldpath, newpath)
215
 
        except OSError as e:
216
 
            return paramiko.SFTPServer.convert_errno(e.errno)
217
 
        return paramiko.SFTP_OK
218
 
 
219
 
    def symlink(self, target_path, path):
220
 
        path = self._realpath(path)
221
 
        try:
222
 
            os.symlink(target_path, path)
223
 
        except OSError as e:
224
 
            return paramiko.SFTPServer.convert_errno(e.errno)
225
 
        return paramiko.SFTP_OK
226
 
 
227
 
    def readlink(self, path):
228
 
        path = self._realpath(path)
229
 
        try:
230
 
            target_path = os.readlink(path)
231
 
        except OSError as e:
232
 
            return paramiko.SFTPServer.convert_errno(e.errno)
233
 
        return target_path
 
213
        except OSError, e:
 
214
            return paramiko.SFTPServer.convert_errno(e.errno)
 
215
        return paramiko.SFTP_OK
234
216
 
235
217
    def mkdir(self, path, attr):
236
218
        path = self._realpath(path)
244
226
            if attr is not None:
245
227
                attr._flags &= ~attr.FLAG_PERMISSIONS
246
228
                paramiko.SFTPServer.set_file_attr(path, attr)
247
 
        except OSError as e:
 
229
        except OSError, e:
248
230
            return paramiko.SFTPServer.convert_errno(e.errno)
249
231
        return paramiko.SFTP_OK
250
232
 
252
234
        path = self._realpath(path)
253
235
        try:
254
236
            os.rmdir(path)
255
 
        except OSError as e:
 
237
        except OSError, e:
256
238
            return paramiko.SFTPServer.convert_errno(e.errno)
257
239
        return paramiko.SFTP_OK
258
240
 
259
 
    # removed: chattr
 
241
    # removed: chattr, symlink, readlink
260
242
    # (nothing in bzr's sftp transport uses those)
261
243
 
262
 
 
263
244
# ------------- server test implementation --------------
264
245
 
265
 
STUB_SERVER_KEY = """\
 
246
STUB_SERVER_KEY = """
266
247
-----BEGIN RSA PRIVATE KEY-----
267
248
MIICWgIBAAKBgQDTj1bqB4WmayWNPB+8jVSYpZYk80Ujvj680pOTh2bORBjbIAyz
268
249
oWGW+GUjzKxTiiPvVmxFgx5wdsFvF03v34lEVVhMpouqPAYQ15N37K/ir5XY+9m/
281
262
"""
282
263
 
283
264
 
 
265
class SocketListener(threading.Thread):
 
266
 
 
267
    def __init__(self, callback):
 
268
        threading.Thread.__init__(self)
 
269
        self._callback = callback
 
270
        self._socket = socket.socket()
 
271
        self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
 
272
        self._socket.bind(('localhost', 0))
 
273
        self._socket.listen(1)
 
274
        self.host, self.port = self._socket.getsockname()[:2]
 
275
        self._stop_event = threading.Event()
 
276
 
 
277
    def stop(self):
 
278
        # called from outside this thread
 
279
        self._stop_event.set()
 
280
        # use a timeout here, because if the test fails, the server thread may
 
281
        # never notice the stop_event.
 
282
        self.join(5.0)
 
283
        self._socket.close()
 
284
 
 
285
    def run(self):
 
286
        while True:
 
287
            readable, writable_unused, exception_unused = \
 
288
                select.select([self._socket], [], [], 0.1)
 
289
            if self._stop_event.isSet():
 
290
                return
 
291
            if len(readable) == 0:
 
292
                continue
 
293
            try:
 
294
                s, addr_unused = self._socket.accept()
 
295
                # because the loopback socket is inline, and transports are
 
296
                # never explicitly closed, best to launch a new thread.
 
297
                threading.Thread(target=self._callback, args=(s,)).start()
 
298
            except socket.error, x:
 
299
                sys.excepthook(*sys.exc_info())
 
300
                trace.warning('Socket error during accept() '
 
301
                              'within unit test server thread: %r' % x)
 
302
            except Exception, x:
 
303
                # probably a failed test; unit test thread will log the
 
304
                # failure/error
 
305
                sys.excepthook(*sys.exc_info())
 
306
                trace.warning(
 
307
                    'Exception from within unit test server thread: %r' % x)
 
308
 
 
309
 
284
310
class SocketDelay(object):
285
311
    """A socket decorator to make TCP appear slower.
286
312
 
356
382
        return bytes_sent
357
383
 
358
384
 
359
 
class TestingSFTPConnectionHandler(socketserver.BaseRequestHandler):
360
 
 
361
 
    def setup(self):
362
 
        self.wrap_for_latency()
363
 
        tcs = self.server.test_case_server
364
 
        ptrans = paramiko.Transport(self.request)
365
 
        self.paramiko_transport = ptrans
366
 
        # Set it to a channel under 'bzr' so that we get debug info
367
 
        ptrans.set_log_channel('brz.paramiko.transport')
368
 
        ptrans.add_server_key(tcs.get_host_key())
369
 
        ptrans.set_subsystem_handler('sftp', paramiko.SFTPServer,
370
 
                                     StubSFTPServer, root=tcs._root,
371
 
                                     home=tcs._server_homedir)
372
 
        server = tcs._server_interface(tcs)
373
 
        # This blocks until the key exchange has been done
374
 
        ptrans.start_server(None, server)
375
 
 
376
 
    def finish(self):
377
 
        # Wait for the conversation to finish, when the paramiko.Transport
378
 
        # thread finishes
379
 
        # TODO: Consider timing out after XX seconds rather than hanging.
380
 
        #       Also we could check paramiko_transport.active and possibly
381
 
        #       paramiko_transport.getException().
382
 
        self.paramiko_transport.join()
383
 
 
384
 
    def wrap_for_latency(self):
385
 
        tcs = self.server.test_case_server
386
 
        if tcs.add_latency:
387
 
            # Give the socket (which the request really is) a latency adding
388
 
            # decorator.
389
 
            self.request = SocketDelay(self.request, tcs.add_latency)
390
 
 
391
 
 
392
 
class TestingSFTPWithoutSSHConnectionHandler(TestingSFTPConnectionHandler):
393
 
 
394
 
    def setup(self):
395
 
        self.wrap_for_latency()
396
 
        # Re-import these as locals, so that they're still accessible during
397
 
        # interpreter shutdown (when all module globals get set to None, leading
398
 
        # to confusing errors like "'NoneType' object has no attribute 'error'".
399
 
 
400
 
        class FakeChannel(object):
401
 
            def get_transport(self):
402
 
                return self
403
 
 
404
 
            def get_log_channel(self):
405
 
                return 'brz.paramiko'
406
 
 
407
 
            def get_name(self):
408
 
                return '1'
409
 
 
410
 
            def get_hexdump(self):
411
 
                return False
412
 
 
413
 
            def close(self):
414
 
                pass
415
 
 
416
 
        tcs = self.server.test_case_server
417
 
        sftp_server = paramiko.SFTPServer(
418
 
            FakeChannel(), 'sftp', StubServer(tcs), StubSFTPServer,
419
 
            root=tcs._root, home=tcs._server_homedir)
420
 
        self.sftp_server = sftp_server
421
 
        sys_stderr = sys.stderr  # Used in error reporting during shutdown
422
 
        try:
423
 
            sftp_server.start_subsystem(
424
 
                'sftp', None, ssh.SocketAsChannelAdapter(self.request))
425
 
        except socket.error as e:
426
 
            if (len(e.args) > 0) and (e.args[0] == errno.EPIPE):
427
 
                # it's okay for the client to disconnect abruptly
428
 
                # (bug in paramiko 1.6: it should absorb this exception)
429
 
                pass
430
 
            else:
431
 
                raise
432
 
        except Exception as e:
433
 
            # This typically seems to happen during interpreter shutdown, so
434
 
            # most of the useful ways to report this error won't work.
435
 
            # Writing the exception type, and then the text of the exception,
436
 
            # seems to be the best we can do.
437
 
            # FIXME: All interpreter shutdown errors should have been related
438
 
            # to daemon threads, cleanup needed -- vila 20100623
439
 
            sys_stderr.write('\nEXCEPTION %r: ' % (e.__class__,))
440
 
            sys_stderr.write('%s\n\n' % (e,))
441
 
 
442
 
    def finish(self):
443
 
        self.sftp_server.finish_subsystem()
444
 
 
445
 
 
446
 
class TestingSFTPServer(test_server.TestingThreadingTCPServer):
447
 
 
448
 
    def __init__(self, server_address, request_handler_class, test_case_server):
449
 
        test_server.TestingThreadingTCPServer.__init__(
450
 
            self, server_address, request_handler_class)
451
 
        self.test_case_server = test_case_server
452
 
 
453
 
 
454
 
class SFTPServer(test_server.TestingTCPServerInAThread):
 
385
class SFTPServer(test_server.TestServer):
455
386
    """Common code for SFTP server facilities."""
456
387
 
457
388
    def __init__(self, server_interface=StubServer):
458
 
        self.host = '127.0.0.1'
459
 
        self.port = 0
460
 
        super(SFTPServer, self).__init__((self.host, self.port),
461
 
                                         TestingSFTPServer,
462
 
                                         TestingSFTPConnectionHandler)
463
389
        self._original_vendor = None
 
390
        self._homedir = None
 
391
        self._server_homedir = None
 
392
        self._listener = None
 
393
        self._root = None
464
394
        self._vendor = ssh.ParamikoVendor()
465
395
        self._server_interface = server_interface
466
 
        self._host_key = None
 
396
        # sftp server logs
467
397
        self.logs = []
468
398
        self.add_latency = 0
469
 
        self._homedir = None
470
 
        self._server_homedir = None
471
 
        self._root = None
472
399
 
473
400
    def _get_sftp_url(self, path):
474
401
        """Calculate an sftp url to this server for path."""
475
 
        return "sftp://foo:bar@%s:%s/%s" % (self.host, self.port, path)
 
402
        return 'sftp://foo:bar@%s:%d/%s' % (self._listener.host,
 
403
                                            self._listener.port, path)
476
404
 
477
405
    def log(self, message):
478
406
        """StubServer uses this to log when a new server is created."""
479
407
        self.logs.append(message)
480
408
 
481
 
    def create_server(self):
482
 
        server = self.server_class((self.host, self.port),
483
 
                                   self.request_handler_class,
484
 
                                   self)
485
 
        return server
486
 
 
487
 
    def get_host_key(self):
488
 
        if self._host_key is None:
489
 
            key_file = osutils.pathjoin(self._homedir, 'test_rsa.key')
490
 
            f = open(key_file, 'w')
491
 
            try:
492
 
                f.write(STUB_SERVER_KEY)
493
 
            finally:
494
 
                f.close()
495
 
            self._host_key = paramiko.RSAKey.from_private_key_file(key_file)
496
 
        return self._host_key
 
409
    def _run_server_entry(self, sock):
 
410
        """Entry point for all implementations of _run_server.
 
411
 
 
412
        If self.add_latency is > 0.000001 then sock is given a latency adding
 
413
        decorator.
 
414
        """
 
415
        if self.add_latency > 0.000001:
 
416
            sock = SocketDelay(sock, self.add_latency)
 
417
        return self._run_server(sock)
 
418
 
 
419
    def _run_server(self, s):
 
420
        ssh_server = paramiko.Transport(s)
 
421
        key_file = osutils.pathjoin(self._homedir, 'test_rsa.key')
 
422
        f = open(key_file, 'w')
 
423
        f.write(STUB_SERVER_KEY)
 
424
        f.close()
 
425
        host_key = paramiko.RSAKey.from_private_key_file(key_file)
 
426
        ssh_server.add_server_key(host_key)
 
427
        server = self._server_interface(self)
 
428
        ssh_server.set_subsystem_handler('sftp', paramiko.SFTPServer,
 
429
                                         StubSFTPServer, root=self._root,
 
430
                                         home=self._server_homedir)
 
431
        event = threading.Event()
 
432
        ssh_server.start_server(event, server)
 
433
        event.wait(5.0)
497
434
 
498
435
    def start_server(self, backing_server=None):
499
436
        # XXX: TODO: make sftpserver back onto backing_server rather than local
500
437
        # disk.
501
 
        if not (backing_server is None
502
 
                or isinstance(backing_server, test_server.LocalURLServer)):
 
438
        if not (backing_server is None or
 
439
                isinstance(backing_server, test_server.LocalURLServer)):
503
440
            raise AssertionError(
504
441
                'backing_server should not be %r, because this can only serve '
505
442
                'the local current working directory.' % (backing_server,))
506
443
        self._original_vendor = ssh._ssh_vendor_manager._cached_ssh_vendor
507
444
        ssh._ssh_vendor_manager._cached_ssh_vendor = self._vendor
508
 
        self._homedir = osutils.getcwd()
 
445
        # FIXME: the following block should certainly just be self._homedir =
 
446
        # osutils.getcwd() but that fails badly on Unix -- vila 20100224
509
447
        if sys.platform == 'win32':
510
 
            # Normalize the path or it will be wrongly escaped
511
 
            self._homedir = osutils.normpath(self._homedir)
 
448
            # Win32 needs to use the UNICODE api
 
449
            self._homedir = os.getcwdu()
512
450
        else:
513
 
            self._homedir = self._homedir
 
451
            # But Linux SFTP servers should just deal in bytestreams
 
452
            self._homedir = os.getcwd()
514
453
        if self._server_homedir is None:
515
454
            self._server_homedir = self._homedir
516
455
        self._root = '/'
517
456
        if sys.platform == 'win32':
518
457
            self._root = ''
519
 
        super(SFTPServer, self).start_server()
 
458
        self._listener = SocketListener(self._run_server_entry)
 
459
        self._listener.setDaemon(True)
 
460
        self._listener.start()
520
461
 
521
462
    def stop_server(self):
522
 
        try:
523
 
            super(SFTPServer, self).stop_server()
524
 
        finally:
525
 
            ssh._ssh_vendor_manager._cached_ssh_vendor = self._original_vendor
 
463
        self._listener.stop()
 
464
        ssh._ssh_vendor_manager._cached_ssh_vendor = self._original_vendor
526
465
 
527
466
    def get_bogus_url(self):
528
 
        """See breezy.transport.Server.get_bogus_url."""
529
 
        # this is chosen to try to prevent trouble with proxies, weird dns, etc
 
467
        """See bzrlib.transport.Server.get_bogus_url."""
 
468
        # this is chosen to try to prevent trouble with proxies, wierd dns, etc
530
469
        # we bind a random socket, so that we get a guaranteed unused port
531
470
        # we just never listen on that port
532
471
        s = socket.socket()
538
477
    """A test server for sftp transports, using absolute urls and ssh."""
539
478
 
540
479
    def get_url(self):
541
 
        """See breezy.transport.Server.get_url."""
 
480
        """See bzrlib.transport.Server.get_url."""
542
481
        homedir = self._homedir
543
482
        if sys.platform != 'win32':
544
483
            # Remove the initial '/' on all platforms but win32
552
491
    def __init__(self):
553
492
        super(SFTPServerWithoutSSH, self).__init__()
554
493
        self._vendor = ssh.LoopbackVendor()
555
 
        self.request_handler_class = TestingSFTPWithoutSSHConnectionHandler
556
 
 
557
 
    def get_host_key():
558
 
        return None
 
494
 
 
495
    def _run_server(self, sock):
 
496
        # Re-import these as locals, so that they're still accessible during
 
497
        # interpreter shutdown (when all module globals get set to None, leading
 
498
        # to confusing errors like "'NoneType' object has no attribute 'error'".
 
499
        class FakeChannel(object):
 
500
            def get_transport(self):
 
501
                return self
 
502
            def get_log_channel(self):
 
503
                return 'paramiko'
 
504
            def get_name(self):
 
505
                return '1'
 
506
            def get_hexdump(self):
 
507
                return False
 
508
            def close(self):
 
509
                pass
 
510
 
 
511
        server = paramiko.SFTPServer(
 
512
            FakeChannel(), 'sftp', StubServer(self), StubSFTPServer,
 
513
            root=self._root, home=self._server_homedir)
 
514
        try:
 
515
            server.start_subsystem(
 
516
                'sftp', None, ssh.SocketAsChannelAdapter(sock))
 
517
        except socket.error, e:
 
518
            if (len(e.args) > 0) and (e.args[0] == errno.EPIPE):
 
519
                # it's okay for the client to disconnect abruptly
 
520
                # (bug in paramiko 1.6: it should absorb this exception)
 
521
                pass
 
522
            else:
 
523
                raise
 
524
        except Exception, e:
 
525
            # This typically seems to happen during interpreter shutdown, so
 
526
            # most of the useful ways to report this error are won't work.
 
527
            # Writing the exception type, and then the text of the exception,
 
528
            # seems to be the best we can do.
 
529
            import sys
 
530
            sys.stderr.write('\nEXCEPTION %r: ' % (e.__class__,))
 
531
            sys.stderr.write('%s\n\n' % (e,))
 
532
        server.finish_subsystem()
559
533
 
560
534
 
561
535
class SFTPAbsoluteServer(SFTPServerWithoutSSH):
562
536
    """A test server for sftp transports, using absolute urls."""
563
537
 
564
538
    def get_url(self):
565
 
        """See breezy.transport.Server.get_url."""
 
539
        """See bzrlib.transport.Server.get_url."""
566
540
        homedir = self._homedir
567
541
        if sys.platform != 'win32':
568
542
            # Remove the initial '/' on all platforms but win32
574
548
    """A test server for sftp transports, using homedir relative urls."""
575
549
 
576
550
    def get_url(self):
577
 
        """See breezy.transport.Server.get_url."""
578
 
        return self._get_sftp_url("%7E/")
 
551
        """See bzrlib.transport.Server.get_url."""
 
552
        return self._get_sftp_url("~/")
579
553
 
580
554
 
581
555
class SFTPSiblingAbsoluteServer(SFTPAbsoluteServer):
584
558
    It does this by serving from a deeply-nested directory that doesn't exist.
585
559
    """
586
560
 
587
 
    def create_server(self):
588
 
        # FIXME: Can't we do that in a cleaner way ? -- vila 20100623
589
 
        server = super(SFTPSiblingAbsoluteServer, self).create_server()
590
 
        server._server_homedir = '/dev/noone/runs/tests/here'
591
 
        return server
 
561
    def start_server(self, backing_server=None):
 
562
        self._server_homedir = '/dev/noone/runs/tests/here'
 
563
        super(SFTPSiblingAbsoluteServer, self).start_server(backing_server)
 
564