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

  • Committer: Jelmer Vernooij
  • Date: 2020-04-05 19:11:34 UTC
  • mto: (7490.7.16 work)
  • mto: This revision was merged to the branch mainline in revision 7501.
  • Revision ID: jelmer@jelmer.uk-20200405191134-0aebh8ikiwygxma5
Populate the .gitignore file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2008, 2009, 2010 Robey Pointer <robey@lag.net>, Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2008-2011 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
25
24
import socket
 
25
try:
 
26
    import socketserver
 
27
except ImportError:
 
28
    import SocketServer as socketserver
26
29
import sys
27
 
import threading
28
30
import time
29
31
 
30
 
from bzrlib import (
 
32
from .. import (
31
33
    osutils,
32
34
    trace,
33
35
    urlutils,
34
36
    )
35
 
from bzrlib.transport import (
 
37
from ..transport import (
36
38
    ssh,
37
39
    )
38
 
from bzrlib.tests import test_server
39
 
 
40
 
 
41
 
class StubServer (paramiko.ServerInterface):
42
 
 
43
 
    def __init__(self, test_case):
 
40
from . import test_server
 
41
 
 
42
 
 
43
class StubServer(paramiko.ServerInterface):
 
44
 
 
45
    def __init__(self, test_case_server):
44
46
        paramiko.ServerInterface.__init__(self)
45
 
        self._test_case = test_case
 
47
        self.log = test_case_server.log
46
48
 
47
49
    def check_auth_password(self, username, password):
48
50
        # all are allowed
49
 
        self._test_case.log('sftpserver - authorizing: %s' % (username,))
 
51
        self.log('sftpserver - authorizing: %s' % (username,))
50
52
        return paramiko.AUTH_SUCCESSFUL
51
53
 
52
54
    def check_channel_request(self, kind, chanid):
53
 
        self._test_case.log(
54
 
            'sftpserver - channel request: %s, %s' % (kind, chanid))
 
55
        self.log('sftpserver - channel request: %s, %s' % (kind, chanid))
55
56
        return paramiko.OPEN_SUCCEEDED
56
57
 
57
58
 
58
 
class StubSFTPHandle (paramiko.SFTPHandle):
 
59
class StubSFTPHandle(paramiko.SFTPHandle):
 
60
 
59
61
    def stat(self):
60
62
        try:
61
63
            return paramiko.SFTPAttributes.from_stat(
62
64
                os.fstat(self.readfile.fileno()))
63
 
        except OSError, e:
 
65
        except OSError as e:
64
66
            return paramiko.SFTPServer.convert_errno(e.errno)
65
67
 
66
68
    def chattr(self, attr):
69
71
        trace.mutter('Changing permissions on %s to %s', self.filename, attr)
70
72
        try:
71
73
            paramiko.SFTPServer.set_file_attr(self.filename, attr)
72
 
        except OSError, e:
 
74
        except OSError as e:
73
75
            return paramiko.SFTPServer.convert_errno(e.errno)
74
76
 
75
77
 
76
 
class StubSFTPServer (paramiko.SFTPServerInterface):
 
78
class StubSFTPServer(paramiko.SFTPServerInterface):
77
79
 
78
80
    def __init__(self, server, root, home=None):
79
81
        paramiko.SFTPServerInterface.__init__(self, server)
90
92
            self.home = home[len(self.root):]
91
93
        if self.home.startswith('/'):
92
94
            self.home = self.home[1:]
93
 
        server._test_case.log('sftpserver - new connection')
 
95
        server.log('sftpserver - new connection')
94
96
 
95
97
    def _realpath(self, path):
96
98
        # paths returned from self.canonicalize() always start with
119
121
    else:
120
122
        def canonicalize(self, path):
121
123
            if os.path.isabs(path):
122
 
                return os.path.normpath(path)
 
124
                return osutils.normpath(path)
123
125
            else:
124
 
                return os.path.normpath('/' + os.path.join(self.home, path))
 
126
                return osutils.normpath('/' + os.path.join(self.home, path))
125
127
 
126
128
    def chattr(self, path, attr):
127
129
        try:
128
130
            paramiko.SFTPServer.set_file_attr(path, attr)
129
 
        except OSError, e:
 
131
        except OSError as e:
130
132
            return paramiko.SFTPServer.convert_errno(e.errno)
131
133
        return paramiko.SFTP_OK
132
134
 
133
135
    def list_folder(self, path):
134
136
        path = self._realpath(path)
135
137
        try:
136
 
            out = [ ]
 
138
            out = []
137
139
            # TODO: win32 incorrectly lists paths with non-ascii if path is not
138
 
            # unicode. However on Linux the server should only deal with
 
140
            # unicode. However on unix the server should only deal with
139
141
            # bytestreams and posix.listdir does the right thing
140
142
            if sys.platform == 'win32':
141
143
                flist = [f.encode('utf8') for f in os.listdir(path)]
147
149
                attr.filename = fname
148
150
                out.append(attr)
149
151
            return out
150
 
        except OSError, e:
 
152
        except OSError as e:
151
153
            return paramiko.SFTPServer.convert_errno(e.errno)
152
154
 
153
155
    def stat(self, path):
154
156
        path = self._realpath(path)
155
157
        try:
156
158
            return paramiko.SFTPAttributes.from_stat(os.stat(path))
157
 
        except OSError, e:
 
159
        except OSError as e:
158
160
            return paramiko.SFTPServer.convert_errno(e.errno)
159
161
 
160
162
    def lstat(self, path):
161
163
        path = self._realpath(path)
162
164
        try:
163
165
            return paramiko.SFTPAttributes.from_stat(os.lstat(path))
164
 
        except OSError, e:
 
166
        except OSError as e:
165
167
            return paramiko.SFTPServer.convert_errno(e.errno)
166
168
 
167
169
    def open(self, path, flags, attr):
173
175
            else:
174
176
                # os.open() defaults to 0777 which is
175
177
                # an odd default mode for files
176
 
                fd = os.open(path, flags, 0666)
177
 
        except OSError, e:
 
178
                fd = os.open(path, flags, 0o666)
 
179
        except OSError as e:
178
180
            return paramiko.SFTPServer.convert_errno(e.errno)
179
181
 
180
182
        if (flags & os.O_CREAT) and (attr is not None):
189
191
            fstr = 'rb'
190
192
        try:
191
193
            f = os.fdopen(fd, fstr)
192
 
        except (IOError, OSError), e:
 
194
        except (IOError, OSError) as e:
193
195
            return paramiko.SFTPServer.convert_errno(e.errno)
194
196
        fobj = StubSFTPHandle()
195
197
        fobj.filename = path
201
203
        path = self._realpath(path)
202
204
        try:
203
205
            os.remove(path)
204
 
        except OSError, e:
 
206
        except OSError as e:
205
207
            return paramiko.SFTPServer.convert_errno(e.errno)
206
208
        return paramiko.SFTP_OK
207
209
 
210
212
        newpath = self._realpath(newpath)
211
213
        try:
212
214
            os.rename(oldpath, newpath)
213
 
        except OSError, e:
214
 
            return paramiko.SFTPServer.convert_errno(e.errno)
215
 
        return paramiko.SFTP_OK
 
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
216
234
 
217
235
    def mkdir(self, path, attr):
218
236
        path = self._realpath(path)
226
244
            if attr is not None:
227
245
                attr._flags &= ~attr.FLAG_PERMISSIONS
228
246
                paramiko.SFTPServer.set_file_attr(path, attr)
229
 
        except OSError, e:
 
247
        except OSError as e:
230
248
            return paramiko.SFTPServer.convert_errno(e.errno)
231
249
        return paramiko.SFTP_OK
232
250
 
234
252
        path = self._realpath(path)
235
253
        try:
236
254
            os.rmdir(path)
237
 
        except OSError, e:
 
255
        except OSError as e:
238
256
            return paramiko.SFTPServer.convert_errno(e.errno)
239
257
        return paramiko.SFTP_OK
240
258
 
241
 
    # removed: chattr, symlink, readlink
 
259
    # removed: chattr
242
260
    # (nothing in bzr's sftp transport uses those)
243
261
 
 
262
 
244
263
# ------------- server test implementation --------------
245
264
 
246
 
STUB_SERVER_KEY = """
 
265
STUB_SERVER_KEY = """\
247
266
-----BEGIN RSA PRIVATE KEY-----
248
267
MIICWgIBAAKBgQDTj1bqB4WmayWNPB+8jVSYpZYk80Ujvj680pOTh2bORBjbIAyz
249
268
oWGW+GUjzKxTiiPvVmxFgx5wdsFvF03v34lEVVhMpouqPAYQ15N37K/ir5XY+9m/
262
281
"""
263
282
 
264
283
 
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
 
 
310
284
class SocketDelay(object):
311
285
    """A socket decorator to make TCP appear slower.
312
286
 
382
356
        return bytes_sent
383
357
 
384
358
 
385
 
class SFTPServer(test_server.TestServer):
 
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):
386
455
    """Common code for SFTP server facilities."""
387
456
 
388
457
    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)
389
463
        self._original_vendor = None
390
 
        self._homedir = None
391
 
        self._server_homedir = None
392
 
        self._listener = None
393
 
        self._root = None
394
464
        self._vendor = ssh.ParamikoVendor()
395
465
        self._server_interface = server_interface
396
 
        # sftp server logs
 
466
        self._host_key = None
397
467
        self.logs = []
398
468
        self.add_latency = 0
 
469
        self._homedir = None
 
470
        self._server_homedir = None
 
471
        self._root = None
399
472
 
400
473
    def _get_sftp_url(self, path):
401
474
        """Calculate an sftp url to this server for path."""
402
 
        return 'sftp://foo:bar@%s:%d/%s' % (self._listener.host,
403
 
                                            self._listener.port, path)
 
475
        return "sftp://foo:bar@%s:%s/%s" % (self.host, self.port, path)
404
476
 
405
477
    def log(self, message):
406
478
        """StubServer uses this to log when a new server is created."""
407
479
        self.logs.append(message)
408
480
 
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)
 
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
434
497
 
435
498
    def start_server(self, backing_server=None):
436
499
        # XXX: TODO: make sftpserver back onto backing_server rather than local
437
500
        # disk.
438
 
        if not (backing_server is None or
439
 
                isinstance(backing_server, test_server.LocalURLServer)):
 
501
        if not (backing_server is None
 
502
                or isinstance(backing_server, test_server.LocalURLServer)):
440
503
            raise AssertionError(
441
504
                'backing_server should not be %r, because this can only serve '
442
505
                'the local current working directory.' % (backing_server,))
443
506
        self._original_vendor = ssh._ssh_vendor_manager._cached_ssh_vendor
444
507
        ssh._ssh_vendor_manager._cached_ssh_vendor = self._vendor
445
 
        # FIXME: the following block should certainly just be self._homedir =
446
 
        # osutils.getcwd() but that fails badly on Unix -- vila 20100224
 
508
        self._homedir = osutils.getcwd()
447
509
        if sys.platform == 'win32':
448
 
            # Win32 needs to use the UNICODE api
449
 
            self._homedir = os.getcwdu()
 
510
            # Normalize the path or it will be wrongly escaped
 
511
            self._homedir = osutils.normpath(self._homedir)
450
512
        else:
451
 
            # But Linux SFTP servers should just deal in bytestreams
452
 
            self._homedir = os.getcwd()
 
513
            self._homedir = self._homedir
453
514
        if self._server_homedir is None:
454
515
            self._server_homedir = self._homedir
455
516
        self._root = '/'
456
517
        if sys.platform == 'win32':
457
518
            self._root = ''
458
 
        self._listener = SocketListener(self._run_server_entry)
459
 
        self._listener.setDaemon(True)
460
 
        self._listener.start()
 
519
        super(SFTPServer, self).start_server()
461
520
 
462
521
    def stop_server(self):
463
 
        self._listener.stop()
464
 
        ssh._ssh_vendor_manager._cached_ssh_vendor = self._original_vendor
 
522
        try:
 
523
            super(SFTPServer, self).stop_server()
 
524
        finally:
 
525
            ssh._ssh_vendor_manager._cached_ssh_vendor = self._original_vendor
465
526
 
466
527
    def get_bogus_url(self):
467
 
        """See bzrlib.transport.Server.get_bogus_url."""
468
 
        # this is chosen to try to prevent trouble with proxies, wierd dns, etc
 
528
        """See breezy.transport.Server.get_bogus_url."""
 
529
        # this is chosen to try to prevent trouble with proxies, weird dns, etc
469
530
        # we bind a random socket, so that we get a guaranteed unused port
470
531
        # we just never listen on that port
471
532
        s = socket.socket()
477
538
    """A test server for sftp transports, using absolute urls and ssh."""
478
539
 
479
540
    def get_url(self):
480
 
        """See bzrlib.transport.Server.get_url."""
 
541
        """See breezy.transport.Server.get_url."""
481
542
        homedir = self._homedir
482
543
        if sys.platform != 'win32':
483
544
            # Remove the initial '/' on all platforms but win32
491
552
    def __init__(self):
492
553
        super(SFTPServerWithoutSSH, self).__init__()
493
554
        self._vendor = ssh.LoopbackVendor()
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()
 
555
        self.request_handler_class = TestingSFTPWithoutSSHConnectionHandler
 
556
 
 
557
    def get_host_key():
 
558
        return None
533
559
 
534
560
 
535
561
class SFTPAbsoluteServer(SFTPServerWithoutSSH):
536
562
    """A test server for sftp transports, using absolute urls."""
537
563
 
538
564
    def get_url(self):
539
 
        """See bzrlib.transport.Server.get_url."""
 
565
        """See breezy.transport.Server.get_url."""
540
566
        homedir = self._homedir
541
567
        if sys.platform != 'win32':
542
568
            # Remove the initial '/' on all platforms but win32
548
574
    """A test server for sftp transports, using homedir relative urls."""
549
575
 
550
576
    def get_url(self):
551
 
        """See bzrlib.transport.Server.get_url."""
552
 
        return self._get_sftp_url("~/")
 
577
        """See breezy.transport.Server.get_url."""
 
578
        return self._get_sftp_url("%7E/")
553
579
 
554
580
 
555
581
class SFTPSiblingAbsoluteServer(SFTPAbsoluteServer):
558
584
    It does this by serving from a deeply-nested directory that doesn't exist.
559
585
    """
560
586
 
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
 
 
 
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