bzr branch
http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
| 
1662.1.12
by Martin Pool
 Translate unknown sftp errors to PathError, no NoSuchFile  | 
1  | 
# Copyright (C) 2005 Robey Pointer <robey@lag.net>
 | 
| 
2221.5.1
by Dmitry Vasiliev
 Added support for Putty's SSH implementation  | 
2  | 
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 | 
| 
1887.1.1
by Adeodato Simó
 Do not separate paragraphs in the copyright statement with blank lines,  | 
3  | 
#
 | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
4  | 
# This program is free software; you can redistribute it and/or modify
 | 
5  | 
# it under the terms of the GNU General Public License as published by
 | 
|
6  | 
# the Free Software Foundation; either version 2 of the License, or
 | 
|
7  | 
# (at your option) any later version.
 | 
|
| 
1887.1.1
by Adeodato Simó
 Do not separate paragraphs in the copyright statement with blank lines,  | 
8  | 
#
 | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
9  | 
# This program is distributed in the hope that it will be useful,
 | 
10  | 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|
11  | 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|
12  | 
# GNU General Public License for more details.
 | 
|
| 
1887.1.1
by Adeodato Simó
 Do not separate paragraphs in the copyright statement with blank lines,  | 
13  | 
#
 | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
14  | 
# You should have received a copy of the GNU General Public License
 | 
15  | 
# along with this program; if not, write to the Free Software
 | 
|
16  | 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
|
17  | 
||
18  | 
"""Implementation of Transport over SFTP, using paramiko."""
 | 
|
19  | 
||
| 
1910.7.17
by Andrew Bennetts
 Various cosmetic changes.  | 
20  | 
# TODO: Remove the transport-based lock_read and lock_write methods.  They'll
 | 
21  | 
# then raise TransportNotPossible, which will break remote access to any
 | 
|
22  | 
# formats which rely on OS-level locks.  That should be fine as those formats
 | 
|
23  | 
# are pretty old, but these combinations may have to be removed from the test
 | 
|
| 
1910.7.19
by Andrew Bennetts
 Expand comment about lock_read/lock_write.  | 
24  | 
# suite.  Those formats all date back to 0.7; so we should be able to remove
 | 
25  | 
# these methods when we officially drop support for those formats.
 | 
|
| 
1910.7.17
by Andrew Bennetts
 Various cosmetic changes.  | 
26  | 
|
| 
1489
by Robert Collins
 Make the paramiko tests pass. Nice huh.  | 
27  | 
import errno  | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
28  | 
import os  | 
| 
1540.2.2
by Röbey Pointer
 allow forcing the use of paramiko via environ var; use prefetch on paramiko >= 1.5.2  | 
29  | 
import random  | 
| 
1551.6.39
by Aaron Bentley
 Apply Robey Pointer's listener patch  | 
30  | 
import select  | 
| 
1806.1.1
by Robey Pointer
 absorb a broken-pipe exception from paramiko when running the unit tests. it's okay for the client to vanish abruptly and paramiko really ought to mask the exception itself.  | 
31  | 
import socket  | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
32  | 
import stat  | 
33  | 
import sys  | 
|
| 
1540.2.2
by Röbey Pointer
 allow forcing the use of paramiko via environ var; use prefetch on paramiko >= 1.5.2  | 
34  | 
import time  | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
35  | 
import urllib  | 
| 
1185.48.1
by James Henstridge
 Use /usr/bin/ssh if we can.  | 
36  | 
import urlparse  | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
37  | 
|
| 
2001.3.2
by John Arbash Meinel
 Force all transports to raise ShortReadvError if they can  | 
38  | 
from bzrlib import (  | 
39  | 
errors,  | 
|
40  | 
urlutils,  | 
|
41  | 
    )
 | 
|
| 
1996.2.1
by Andrew Bennetts
 Fix NameError reported by Alexander Belchenko.  | 
42  | 
from bzrlib.errors import (FileExists,  | 
| 
1951.1.6
by Andrew Bennetts
 Tidy up some unused imports.  | 
43  | 
NoSuchFile, PathNotChild,  | 
| 
1185.49.3
by John Arbash Meinel
 Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path  | 
44  | 
TransportError,  | 
| 
1996.2.1
by Andrew Bennetts
 Fix NameError reported by Alexander Belchenko.  | 
45  | 
LockError,  | 
| 
1662.1.12
by Martin Pool
 Translate unknown sftp errors to PathError, no NoSuchFile  | 
46  | 
PathError,  | 
47  | 
ParamikoNotPresent,  | 
|
| 
1530.1.3
by Robert Collins
 transport implementations now tested consistently.  | 
48  | 
                           )
 | 
| 
1711.5.1
by John Arbash Meinel
 Get most SFTP tests to pass. StubSFTPServer now talks the same path protocol that SFTPTransport talks. on win32  | 
49  | 
from bzrlib.osutils import pathjoin, fancy_rename, getcwd  | 
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
50  | 
from bzrlib.symbol_versioning import (  | 
51  | 
deprecated_function,  | 
|
| 
2485.8.52
by Vincent Ladeuil
 Update deprecation version.  | 
52  | 
zero_nineteen,  | 
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
53  | 
        )
 | 
| 
1951.1.6
by Andrew Bennetts
 Tidy up some unused imports.  | 
54  | 
from bzrlib.trace import mutter, warning  | 
| 
1636.1.2
by Robert Collins
 More review fixen to the relpath at '/' fixes.  | 
55  | 
from bzrlib.transport import (  | 
| 
2018.5.114
by Robert Collins
 Commit current test pass improvements.  | 
56  | 
local,  | 
| 
1636.1.2
by Robert Collins
 More review fixen to the relpath at '/' fixes.  | 
57  | 
register_urlparse_netloc_protocol,  | 
58  | 
Server,  | 
|
| 
1951.1.4
by Andrew Bennetts
 Start moving SSH connection code into bzrlib/transport/ssh.py  | 
59  | 
ssh,  | 
| 
2485.8.16
by Vincent Ladeuil
 Create a new, empty, ConnectedTransport class.  | 
60  | 
ConnectedTransport,  | 
| 
1636.1.2
by Robert Collins
 More review fixen to the relpath at '/' fixes.  | 
61  | 
    )
 | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
62  | 
|
63  | 
try:  | 
|
64  | 
import paramiko  | 
|
| 
1185.62.24
by John Arbash Meinel
 Changing the exception that sftp.py throws when it can't find paramiko, so that the test suite can handle it.  | 
65  | 
except ImportError, e:  | 
66  | 
raise ParamikoNotPresent(e)  | 
|
| 
1185.49.2
by John Arbash Meinel
 Adding a open_exclusive function since paramiko supports it, but doesn't expose it  | 
67  | 
else:  | 
68  | 
from paramiko.sftp import (SFTP_FLAG_WRITE, SFTP_FLAG_CREATE,  | 
|
69  | 
SFTP_FLAG_EXCL, SFTP_FLAG_TRUNC,  | 
|
70  | 
CMD_HANDLE, CMD_OPEN)  | 
|
71  | 
from paramiko.sftp_attr import SFTPAttributes  | 
|
72  | 
from paramiko.sftp_file import SFTPFile  | 
|
| 
1636.1.1
by Robert Collins
 Fix calling relpath() and abspath() on transports at their root.  | 
73  | 
|
| 
1883.1.3
by Stefan (metze) Metzmacher
 - fix typo  | 
74  | 
|
| 
1636.1.2
by Robert Collins
 More review fixen to the relpath at '/' fixes.  | 
75  | 
register_urlparse_netloc_protocol('sftp')  | 
| 
1636.1.1
by Robert Collins
 Fix calling relpath() and abspath() on transports at their root.  | 
76  | 
|
| 
1185.48.1
by James Henstridge
 Use /usr/bin/ssh if we can.  | 
77  | 
|
| 
1711.6.2
by John Arbash Meinel
 Clean up paramiko agent support.  | 
78  | 
_paramiko_version = getattr(paramiko, '__version_info__', (0, 0, 0))  | 
79  | 
# don't use prefetch unless paramiko version >= 1.5.5 (there were bugs earlier)
 | 
|
80  | 
_default_do_prefetch = (_paramiko_version >= (1, 5, 5))  | 
|
| 
1540.2.3
by Robey Pointer
 move the paramiko version check up to the top and use getattr instead of hasattr. use BZR_SSH instead of BZR_USE_PARAMIKO, to allow overriding the ssh vendor check in a general way.  | 
81  | 
|
| 
1185.48.1
by James Henstridge
 Use /usr/bin/ssh if we can.  | 
82  | 
|
| 
2485.8.52
by Vincent Ladeuil
 Update deprecation version.  | 
83  | 
@deprecated_function(zero_nineteen)  | 
| 
1607.1.13
by Robert Collins
 Add a clear_connection_cache to the SFTP transport and use it in fixing the bound branch test speed performance problem which was cause by the server thread timing out - it was blocked on a read and closing the client side causes the server to unblock and exit.  | 
84  | 
def clear_connection_cache():  | 
85  | 
"""Remove all hosts from the SFTP connection cache.  | 
|
86  | 
||
87  | 
    Primarily useful for test cases wanting to force garbage collection.
 | 
|
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
88  | 
    We don't have a global connection cache anymore.
 | 
| 
1607.1.13
by Robert Collins
 Add a clear_connection_cache to the SFTP transport and use it in fixing the bound branch test speed performance problem which was cause by the server thread timing out - it was blocked on a read and closing the client side causes the server to unblock and exit.  | 
89  | 
    """
 | 
| 
1547.1.1
by Robey Pointer
 modify the sftp unit tests to perform sftp over a direct localhost socket instead of over an actual ssh2 transport  | 
90  | 
|
| 
1185.49.3
by John Arbash Meinel
 Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path  | 
91  | 
class SFTPLock(object):  | 
| 
1910.7.17
by Andrew Bennetts
 Various cosmetic changes.  | 
92  | 
"""This fakes a lock in a remote location.  | 
93  | 
    
 | 
|
94  | 
    A present lock is indicated just by the existence of a file.  This
 | 
|
95  | 
    doesn't work well on all transports and they are only used in 
 | 
|
96  | 
    deprecated storage formats.
 | 
|
97  | 
    """
 | 
|
98  | 
||
| 
1185.49.3
by John Arbash Meinel
 Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path  | 
99  | 
__slots__ = ['path', 'lock_path', 'lock_file', 'transport']  | 
| 
1910.7.17
by Andrew Bennetts
 Various cosmetic changes.  | 
100  | 
|
| 
1185.49.3
by John Arbash Meinel
 Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path  | 
101  | 
def __init__(self, path, transport):  | 
102  | 
assert isinstance(transport, SFTPTransport)  | 
|
103  | 
||
104  | 
self.lock_file = None  | 
|
105  | 
self.path = path  | 
|
106  | 
self.lock_path = path + '.write-lock'  | 
|
107  | 
self.transport = transport  | 
|
108  | 
try:  | 
|
| 
1530.1.7
by Robert Collins
 merge integration.  | 
109  | 
            # RBC 20060103 FIXME should we be using private methods here ?
 | 
110  | 
abspath = transport._remote_path(self.lock_path)  | 
|
| 
1185.58.2
by John Arbash Meinel
 Added mode to the appropriate transport functions, and tests to make sure they work.  | 
111  | 
self.lock_file = transport._sftp_open_exclusive(abspath)  | 
| 
1185.49.3
by John Arbash Meinel
 Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path  | 
112  | 
except FileExists:  | 
113  | 
raise LockError('File %r already locked' % (self.path,))  | 
|
114  | 
||
115  | 
def __del__(self):  | 
|
116  | 
"""Should this warn, or actually try to cleanup?"""  | 
|
117  | 
if self.lock_file:  | 
|
| 
1547.1.3
by Robey Pointer
 spell warning correctly :) and move recv_ready close to recv for readability  | 
118  | 
warning("SFTPLock %r not explicitly unlocked" % (self.path,))  | 
| 
1185.49.3
by John Arbash Meinel
 Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path  | 
119  | 
self.unlock()  | 
120  | 
||
121  | 
def unlock(self):  | 
|
122  | 
if not self.lock_file:  | 
|
123  | 
            return
 | 
|
124  | 
self.lock_file.close()  | 
|
125  | 
self.lock_file = None  | 
|
126  | 
try:  | 
|
127  | 
self.transport.delete(self.lock_path)  | 
|
128  | 
except (NoSuchFile,):  | 
|
129  | 
            # What specific errors should we catch here?
 | 
|
130  | 
            pass
 | 
|
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
131  | 
|
| 
1551.6.39
by Aaron Bentley
 Apply Robey Pointer's listener patch  | 
132  | 
|
| 
2485.8.27
by Vincent Ladeuil
 Hearing jam saying "vila, you're trying too hard", I simplified again.  | 
133  | 
class SFTPTransport(ConnectedTransport):  | 
| 
1752.2.40
by Andrew Bennetts
 Merge from bzr.dev.  | 
134  | 
"""Transport implementation for SFTP access."""  | 
| 
1864.5.2
by John Arbash Meinel
 always read in sorted order, and return in requested order, but only cache what is currently out of order  | 
135  | 
|
| 
1540.2.3
by Robey Pointer
 move the paramiko version check up to the top and use getattr instead of hasattr. use BZR_SSH instead of BZR_USE_PARAMIKO, to allow overriding the ssh vendor check in a general way.  | 
136  | 
_do_prefetch = _default_do_prefetch  | 
| 
1864.5.6
by John Arbash Meinel
 Setting defaults based on benchmarking data.  | 
137  | 
    # TODO: jam 20060717 Conceivably these could be configurable, either
 | 
138  | 
    #       by auto-tuning at run-time, or by a configuration (per host??)
 | 
|
139  | 
    #       but the performance curve is pretty flat, so just going with
 | 
|
140  | 
    #       reasonable defaults.
 | 
|
| 
1864.5.18
by John Arbash Meinel
 Remove benchmarking stipple.  | 
141  | 
_max_readv_combine = 200  | 
| 
1864.5.6
by John Arbash Meinel
 Setting defaults based on benchmarking data.  | 
142  | 
    # Having to round trip to the server means waiting for a response,
 | 
143  | 
    # so it is better to download extra bytes.
 | 
|
144  | 
    # 8KiB had good performance for both local and remote network operations
 | 
|
| 
1864.5.18
by John Arbash Meinel
 Remove benchmarking stipple.  | 
145  | 
_bytes_to_read_before_seek = 8192  | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
146  | 
|
| 
1864.5.20
by John Arbash Meinel
 Some small cleanups.  | 
147  | 
    # The sftp spec says that implementations SHOULD allow reads
 | 
148  | 
    # to be at least 32K. paramiko.readv() does an async request
 | 
|
149  | 
    # for the chunks. So we need to keep it within a single request
 | 
|
150  | 
    # size for paramiko <= 1.6.1. paramiko 1.6.2 will probably chop
 | 
|
151  | 
    # up the request itself, rather than us having to worry about it
 | 
|
152  | 
_max_request_size = 32768  | 
|
| 
1864.5.17
by John Arbash Meinel
 A little cleanup, and restrict to 32K to conform better to sftp spec  | 
153  | 
|
| 
2485.8.59
by Vincent Ladeuil
 Update from review comments.  | 
154  | 
def __init__(self, base, _from_transport=None):  | 
| 
2485.8.23
by Vincent Ladeuil
 Assert the accepted schemes for sftp and ftp.  | 
155  | 
assert base.startswith('sftp://')  | 
| 
2485.8.59
by Vincent Ladeuil
 Update from review comments.  | 
156  | 
super(SFTPTransport, self).__init__(base,  | 
157  | 
_from_transport=_from_transport)  | 
|
| 
2485.8.27
by Vincent Ladeuil
 Hearing jam saying "vila, you're trying too hard", I simplified again.  | 
158  | 
|
159  | 
def _remote_path(self, relpath):  | 
|
160  | 
"""Return the path to be passed along the sftp protocol for relpath.  | 
|
161  | 
        
 | 
|
162  | 
        :param relpath: is a urlencoded string.
 | 
|
163  | 
        """
 | 
|
164  | 
relative = urlutils.unescape(relpath).encode('utf-8')  | 
|
165  | 
remote_path = self._combine_paths(self._path, relative)  | 
|
166  | 
        # the initial slash should be removed from the path, and treated as a
 | 
|
167  | 
        # homedir relative path (the path begins with a double slash if it is
 | 
|
168  | 
        # absolute).  see draft-ietf-secsh-scp-sftp-ssh-uri-03.txt
 | 
|
169  | 
        # RBC 20060118 we are not using this as its too user hostile. instead
 | 
|
170  | 
        # we are following lftp and using /~/foo to mean '~/foo'
 | 
|
171  | 
        # vila--20070602 and leave absolute paths begin with a single slash.
 | 
|
172  | 
if remote_path.startswith('/~/'):  | 
|
173  | 
remote_path = remote_path[3:]  | 
|
174  | 
elif remote_path == '/~':  | 
|
175  | 
remote_path = ''  | 
|
176  | 
return remote_path  | 
|
177  | 
||
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
178  | 
def _create_connection(self, credentials=None):  | 
179  | 
"""Create a new connection with the provided credentials.  | 
|
180  | 
||
181  | 
        :param credentials: The credentials needed to establish the connection.
 | 
|
182  | 
||
183  | 
        :return: The created connection and its associated credentials.
 | 
|
184  | 
||
185  | 
        The credentials are only the password as it may have been entered
 | 
|
186  | 
        interactively by the user and may be different from the one provided
 | 
|
187  | 
        in base url at transport creation time.
 | 
|
188  | 
        """
 | 
|
189  | 
if credentials is None:  | 
|
190  | 
password = self._password  | 
|
191  | 
else:  | 
|
192  | 
password = credentials  | 
|
193  | 
||
194  | 
vendor = ssh._get_ssh_vendor()  | 
|
195  | 
connection = vendor.connect_sftp(self._user, password,  | 
|
196  | 
self._host, self._port)  | 
|
197  | 
return connection, password  | 
|
198  | 
||
199  | 
def _get_sftp(self):  | 
|
200  | 
"""Ensures that a connection is established"""  | 
|
201  | 
connection = self._get_connection()  | 
|
202  | 
if connection is None:  | 
|
203  | 
            # First connection ever
 | 
|
204  | 
connection, credentials = self._create_connection()  | 
|
205  | 
self._set_connection(connection, credentials)  | 
|
206  | 
return connection  | 
|
207  | 
||
208  | 
||
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
209  | 
def should_cache(self):  | 
210  | 
"""  | 
|
211  | 
        Return True if the data pulled across should be cached locally.
 | 
|
212  | 
        """
 | 
|
213  | 
return True  | 
|
214  | 
||
215  | 
def has(self, relpath):  | 
|
216  | 
"""  | 
|
217  | 
        Does the target location exist?
 | 
|
218  | 
        """
 | 
|
219  | 
try:  | 
|
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
220  | 
self._get_sftp().stat(self._remote_path(relpath))  | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
221  | 
return True  | 
222  | 
except IOError:  | 
|
223  | 
return False  | 
|
224  | 
||
| 
2164.2.15
by Vincent Ladeuil
 Http redirections are not followed by default. Do not use hints  | 
225  | 
def get(self, relpath):  | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
226  | 
"""  | 
227  | 
        Get the file at the given relative path.
 | 
|
228  | 
||
229  | 
        :param relpath: The relative path to the file
 | 
|
230  | 
        """
 | 
|
231  | 
try:  | 
|
| 
1524.1.1
by Robert Collins
 Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir  | 
232  | 
path = self._remote_path(relpath)  | 
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
233  | 
f = self._get_sftp().file(path, mode='rb')  | 
| 
1540.2.3
by Robey Pointer
 move the paramiko version check up to the top and use getattr instead of hasattr. use BZR_SSH instead of BZR_USE_PARAMIKO, to allow overriding the ssh vendor check in a general way.  | 
234  | 
if self._do_prefetch and (getattr(f, 'prefetch', None) is not None):  | 
| 
1185.40.1
by Robey Pointer
 prefetch files under paramiko 1.5.1 for improved speed  | 
235  | 
f.prefetch()  | 
236  | 
return f  | 
|
| 
1185.50.13
by John Arbash Meinel
 Expanded the Transport test suite. Including delete, copy, move, etc. Updated SftpTransport to conform.  | 
237  | 
except (IOError, paramiko.SSHException), e:  | 
| 
2052.6.1
by Robert Collins
 ``Transport.get`` has had its interface made more clear for ease of use.  | 
238  | 
self._translate_io_exception(e, path, ': error retrieving',  | 
| 
2052.6.4
by Robert Collins
 Tidier SFTP code (feedback from Aaron).  | 
239  | 
failure_exc=errors.ReadError)  | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
240  | 
|
| 
1864.5.11
by John Arbash Meinel
 Factor out the workhorse of Transport.readv() into a helper function, and re-use that function in sftp but with a non-prefetch file.  | 
241  | 
def readv(self, relpath, offsets):  | 
242  | 
"""See Transport.readv()"""  | 
|
243  | 
        # We overload the default readv() because we want to use a file
 | 
|
244  | 
        # that does not have prefetch enabled.
 | 
|
| 
1864.5.15
by John Arbash Meinel
 Cleanup and document the new sftp readv implementation  | 
245  | 
        # Also, if we have a new paramiko, it implements an async readv()
 | 
| 
1864.5.11
by John Arbash Meinel
 Factor out the workhorse of Transport.readv() into a helper function, and re-use that function in sftp but with a non-prefetch file.  | 
246  | 
if not offsets:  | 
247  | 
            return
 | 
|
248  | 
||
249  | 
try:  | 
|
250  | 
path = self._remote_path(relpath)  | 
|
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
251  | 
fp = self._get_sftp().file(path, mode='rb')  | 
| 
1864.5.15
by John Arbash Meinel
 Cleanup and document the new sftp readv implementation  | 
252  | 
readv = getattr(fp, 'readv', None)  | 
| 
1864.5.18
by John Arbash Meinel
 Remove benchmarking stipple.  | 
253  | 
if readv:  | 
| 
2001.3.2
by John Arbash Meinel
 Force all transports to raise ShortReadvError if they can  | 
254  | 
return self._sftp_readv(fp, offsets, relpath)  | 
| 
1864.5.16
by John Arbash Meinel
 instrument to enable/disable readv support for testing  | 
255  | 
mutter('seek and read %s offsets', len(offsets))  | 
| 
2001.3.2
by John Arbash Meinel
 Force all transports to raise ShortReadvError if they can  | 
256  | 
return self._seek_and_read(fp, offsets, relpath)  | 
| 
1864.5.11
by John Arbash Meinel
 Factor out the workhorse of Transport.readv() into a helper function, and re-use that function in sftp but with a non-prefetch file.  | 
257  | 
except (IOError, paramiko.SSHException), e:  | 
258  | 
self._translate_io_exception(e, path, ': error retrieving')  | 
|
259  | 
||
| 
2001.3.2
by John Arbash Meinel
 Force all transports to raise ShortReadvError if they can  | 
260  | 
def _sftp_readv(self, fp, offsets, relpath='<unknown>'):  | 
| 
1864.5.15
by John Arbash Meinel
 Cleanup and document the new sftp readv implementation  | 
261  | 
"""Use the readv() member of fp to do async readv.  | 
| 
1864.5.13
by John Arbash Meinel
 Try using paramiko.readv()  | 
262  | 
|
263  | 
        And then read them using paramiko.readv(). paramiko.readv()
 | 
|
264  | 
        does not support ranges > 64K, so it caps the request size, and
 | 
|
265  | 
        just reads until it gets all the stuff it wants
 | 
|
266  | 
        """
 | 
|
| 
1864.5.15
by John Arbash Meinel
 Cleanup and document the new sftp readv implementation  | 
267  | 
offsets = list(offsets)  | 
| 
1864.5.13
by John Arbash Meinel
 Try using paramiko.readv()  | 
268  | 
sorted_offsets = sorted(offsets)  | 
269  | 
||
| 
1864.5.15
by John Arbash Meinel
 Cleanup and document the new sftp readv implementation  | 
270  | 
        # The algorithm works as follows:
 | 
271  | 
        # 1) Coalesce nearby reads into a single chunk
 | 
|
272  | 
        #    This generates a list of combined regions, the total size
 | 
|
273  | 
        #    and the size of the sub regions. This coalescing step is limited
 | 
|
274  | 
        #    in the number of nearby chunks to combine, and is allowed to
 | 
|
275  | 
        #    skip small breaks in the requests. Limiting it makes sure that
 | 
|
276  | 
        #    we can start yielding some data earlier, and skipping means we
 | 
|
277  | 
        #    make fewer requests. (Beneficial even when using async)
 | 
|
278  | 
        # 2) Break up this combined regions into chunks that are smaller
 | 
|
279  | 
        #    than 64KiB. Technically the limit is 65536, but we are a
 | 
|
280  | 
        #    little bit conservative. This is because sftp has a maximum
 | 
|
281  | 
        #    return chunk size of 64KiB (max size of an unsigned short)
 | 
|
282  | 
        # 3) Issue a readv() to paramiko to create an async request for
 | 
|
283  | 
        #    all of this data
 | 
|
284  | 
        # 4) Read in the data as it comes back, until we've read one
 | 
|
285  | 
        #    continuous section as determined in step 1
 | 
|
286  | 
        # 5) Break up the full sections into hunks for the original requested
 | 
|
287  | 
        #    offsets. And put them in a cache
 | 
|
288  | 
        # 6) Check if the next request is in the cache, and if it is, remove
 | 
|
289  | 
        #    it from the cache, and yield its data. Continue until no more
 | 
|
290  | 
        #    entries are in the cache.
 | 
|
291  | 
        # 7) loop back to step 4 until all data has been read
 | 
|
| 
1864.5.16
by John Arbash Meinel
 instrument to enable/disable readv support for testing  | 
292  | 
        #
 | 
293  | 
        # TODO: jam 20060725 This could be optimized one step further, by
 | 
|
294  | 
        #       attempting to yield whatever data we have read, even before
 | 
|
| 
1864.5.20
by John Arbash Meinel
 Some small cleanups.  | 
295  | 
        #       the first coallesced section has been fully processed.
 | 
| 
1864.5.15
by John Arbash Meinel
 Cleanup and document the new sftp readv implementation  | 
296  | 
|
| 
1864.5.17
by John Arbash Meinel
 A little cleanup, and restrict to 32K to conform better to sftp spec  | 
297  | 
        # When coalescing for use with readv(), we don't really need to
 | 
298  | 
        # use any fudge factor, because the requests are made asynchronously
 | 
|
| 
1864.5.13
by John Arbash Meinel
 Try using paramiko.readv()  | 
299  | 
coalesced = list(self._coalesce_offsets(sorted_offsets,  | 
300  | 
limit=self._max_readv_combine,  | 
|
| 
1864.5.17
by John Arbash Meinel
 A little cleanup, and restrict to 32K to conform better to sftp spec  | 
301  | 
fudge_factor=0,  | 
| 
1864.5.13
by John Arbash Meinel
 Try using paramiko.readv()  | 
302  | 
                               ))
 | 
303  | 
requests = []  | 
|
304  | 
for c_offset in coalesced:  | 
|
305  | 
start = c_offset.start  | 
|
| 
1864.5.17
by John Arbash Meinel
 A little cleanup, and restrict to 32K to conform better to sftp spec  | 
306  | 
size = c_offset.length  | 
| 
1864.5.13
by John Arbash Meinel
 Try using paramiko.readv()  | 
307  | 
|
308  | 
            # We need to break this up into multiple requests
 | 
|
| 
1864.5.17
by John Arbash Meinel
 A little cleanup, and restrict to 32K to conform better to sftp spec  | 
309  | 
while size > 0:  | 
| 
1864.5.20
by John Arbash Meinel
 Some small cleanups.  | 
310  | 
next_size = min(size, self._max_request_size)  | 
| 
1864.5.17
by John Arbash Meinel
 A little cleanup, and restrict to 32K to conform better to sftp spec  | 
311  | 
requests.append((start, next_size))  | 
312  | 
size -= next_size  | 
|
313  | 
start += next_size  | 
|
| 
1864.5.13
by John Arbash Meinel
 Try using paramiko.readv()  | 
314  | 
|
| 
1864.5.16
by John Arbash Meinel
 instrument to enable/disable readv support for testing  | 
315  | 
mutter('SFTP.readv() %s offsets => %s coalesced => %s requests',  | 
316  | 
len(offsets), len(coalesced), len(requests))  | 
|
317  | 
||
| 
1864.5.15
by John Arbash Meinel
 Cleanup and document the new sftp readv implementation  | 
318  | 
        # Queue the current read until we have read the full coalesced section
 | 
| 
1864.5.13
by John Arbash Meinel
 Try using paramiko.readv()  | 
319  | 
cur_data = []  | 
320  | 
cur_data_len = 0  | 
|
321  | 
cur_coalesced_stack = iter(coalesced)  | 
|
322  | 
cur_coalesced = cur_coalesced_stack.next()  | 
|
323  | 
||
| 
1864.5.15
by John Arbash Meinel
 Cleanup and document the new sftp readv implementation  | 
324  | 
        # Cache the results, but only until they have been fulfilled
 | 
325  | 
data_map = {}  | 
|
326  | 
        # turn the list of offsets into a stack
 | 
|
327  | 
offset_stack = iter(offsets)  | 
|
328  | 
cur_offset_and_size = offset_stack.next()  | 
|
329  | 
||
| 
1864.5.13
by John Arbash Meinel
 Try using paramiko.readv()  | 
330  | 
for data in fp.readv(requests):  | 
331  | 
cur_data += data  | 
|
332  | 
cur_data_len += len(data)  | 
|
333  | 
||
334  | 
if cur_data_len < cur_coalesced.length:  | 
|
335  | 
                continue
 | 
|
336  | 
assert cur_data_len == cur_coalesced.length, \  | 
|
337  | 
"Somehow we read too much: %s != %s" % (cur_data_len,  | 
|
338  | 
cur_coalesced.length)  | 
|
| 
1864.5.20
by John Arbash Meinel
 Some small cleanups.  | 
339  | 
all_data = ''.join(cur_data)  | 
| 
1864.5.13
by John Arbash Meinel
 Try using paramiko.readv()  | 
340  | 
cur_data = []  | 
341  | 
cur_data_len = 0  | 
|
342  | 
||
343  | 
for suboffset, subsize in cur_coalesced.ranges:  | 
|
344  | 
key = (cur_coalesced.start+suboffset, subsize)  | 
|
| 
1864.5.20
by John Arbash Meinel
 Some small cleanups.  | 
345  | 
data_map[key] = all_data[suboffset:suboffset+subsize]  | 
| 
1864.5.13
by John Arbash Meinel
 Try using paramiko.readv()  | 
346  | 
|
347  | 
            # Now that we've read some data, see if we can yield anything back
 | 
|
348  | 
while cur_offset_and_size in data_map:  | 
|
349  | 
this_data = data_map.pop(cur_offset_and_size)  | 
|
350  | 
yield cur_offset_and_size[0], this_data  | 
|
351  | 
cur_offset_and_size = offset_stack.next()  | 
|
352  | 
||
| 
2001.3.2
by John Arbash Meinel
 Force all transports to raise ShortReadvError if they can  | 
353  | 
            # We read a coalesced entry, so mark it as done
 | 
354  | 
cur_coalesced = None  | 
|
| 
1864.5.13
by John Arbash Meinel
 Try using paramiko.readv()  | 
355  | 
            # Now that we've read all of the data for this coalesced section
 | 
356  | 
            # on to the next
 | 
|
357  | 
cur_coalesced = cur_coalesced_stack.next()  | 
|
| 
1864.5.12
by John Arbash Meinel
 Using a simple sftp_file.readv() request if possible.  | 
358  | 
|
| 
2001.3.2
by John Arbash Meinel
 Force all transports to raise ShortReadvError if they can  | 
359  | 
if cur_coalesced is not None:  | 
360  | 
raise errors.ShortReadvError(relpath, cur_coalesced.start,  | 
|
| 
2001.3.3
by John Arbash Meinel
 review feedback: add the actual count written to ShortReadvError  | 
361  | 
cur_coalesced.length, len(data))  | 
| 
2001.3.2
by John Arbash Meinel
 Force all transports to raise ShortReadvError if they can  | 
362  | 
|
| 
1955.3.6
by John Arbash Meinel
 Lots of deprecation warnings, but no errors  | 
363  | 
def put_file(self, relpath, f, mode=None):  | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
364  | 
"""  | 
| 
1955.3.6
by John Arbash Meinel
 Lots of deprecation warnings, but no errors  | 
365  | 
        Copy the file-like object into the location.
 | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
366  | 
|
367  | 
        :param relpath: Location to put the contents, relative to base.
 | 
|
| 
1955.3.6
by John Arbash Meinel
 Lots of deprecation warnings, but no errors  | 
368  | 
        :param f:       File-like object.
 | 
| 
1185.58.2
by John Arbash Meinel
 Added mode to the appropriate transport functions, and tests to make sure they work.  | 
369  | 
        :param mode: The final mode for the file
 | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
370  | 
        """
 | 
| 
1524.1.1
by Robert Collins
 Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir  | 
371  | 
final_path = self._remote_path(relpath)  | 
| 
1185.58.2
by John Arbash Meinel
 Added mode to the appropriate transport functions, and tests to make sure they work.  | 
372  | 
self._put(final_path, f, mode=mode)  | 
373  | 
||
374  | 
def _put(self, abspath, f, mode=None):  | 
|
375  | 
"""Helper function so both put() and copy_abspaths can reuse the code"""  | 
|
376  | 
tmp_abspath = '%s.tmp.%.9f.%d.%d' % (abspath, time.time(),  | 
|
| 
1185.49.3
by John Arbash Meinel
 Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path  | 
377  | 
os.getpid(), random.randint(0,0x7FFFFFFF))  | 
| 
1185.58.2
by John Arbash Meinel
 Added mode to the appropriate transport functions, and tests to make sure they work.  | 
378  | 
fout = self._sftp_open_exclusive(tmp_abspath, mode=mode)  | 
| 
1185.31.47
by John Arbash Meinel
 Added a fancy footwork rename to osutils, made SftpTransport use it.  | 
379  | 
closed = False  | 
| 
1185.41.6
by Robey Pointer
 modified version of john's patch to add atomic put and locking to the sftp transport  | 
380  | 
try:  | 
| 
1185.49.1
by John Arbash Meinel
 Updating SftpTransport.put() so that it is atomic  | 
381  | 
try:  | 
| 
1185.58.2
by John Arbash Meinel
 Added mode to the appropriate transport functions, and tests to make sure they work.  | 
382  | 
fout.set_pipelined(True)  | 
| 
1185.49.1
by John Arbash Meinel
 Updating SftpTransport.put() so that it is atomic  | 
383  | 
self._pump(f, fout)  | 
| 
1185.31.47
by John Arbash Meinel
 Added a fancy footwork rename to osutils, made SftpTransport use it.  | 
384  | 
except (IOError, paramiko.SSHException), e:  | 
385  | 
self._translate_io_exception(e, tmp_abspath)  | 
|
| 
1946.1.8
by John Arbash Meinel
 Update non_atomic_put to have a create_parent_dir flag  | 
386  | 
            # XXX: This doesn't truly help like we would like it to.
 | 
387  | 
            #      The problem is that openssh strips sticky bits. So while we
 | 
|
388  | 
            #      can properly set group write permission, we lose the group
 | 
|
389  | 
            #      sticky bit. So it is probably best to stop chmodding, and
 | 
|
390  | 
            #      just tell users that they need to set the umask correctly.
 | 
|
391  | 
            #      The attr.st_mode = mode, in _sftp_open_exclusive
 | 
|
392  | 
            #      will handle when the user wants the final mode to be more 
 | 
|
393  | 
            #      restrictive. And then we avoid a round trip. Unless 
 | 
|
394  | 
            #      paramiko decides to expose an async chmod()
 | 
|
395  | 
||
396  | 
            # This is designed to chmod() right before we close.
 | 
|
397  | 
            # Because we set_pipelined() earlier, theoretically we might 
 | 
|
398  | 
            # avoid the round trip for fout.close()
 | 
|
| 
1185.50.20
by John Arbash Meinel
 merge permissions branch, also fixup tests so they are lined up with bzr.dev to help prevent conflicts.  | 
399  | 
if mode is not None:  | 
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
400  | 
self._get_sftp().chmod(tmp_abspath, mode)  | 
| 
1185.31.47
by John Arbash Meinel
 Added a fancy footwork rename to osutils, made SftpTransport use it.  | 
401  | 
fout.close()  | 
402  | 
closed = True  | 
|
| 
1553.5.13
by Martin Pool
 New Transport.rename that mustn't overwrite  | 
403  | 
self._rename_and_overwrite(tmp_abspath, abspath)  | 
| 
1185.49.1
by John Arbash Meinel
 Updating SftpTransport.put() so that it is atomic  | 
404  | 
except Exception, e:  | 
405  | 
            # If we fail, try to clean up the temporary file
 | 
|
406  | 
            # before we throw the exception
 | 
|
407  | 
            # but don't let another exception mess things up
 | 
|
| 
1185.50.20
by John Arbash Meinel
 merge permissions branch, also fixup tests so they are lined up with bzr.dev to help prevent conflicts.  | 
408  | 
            # Write out the traceback, because otherwise
 | 
409  | 
            # the catch and throw destroys it
 | 
|
| 
1185.58.2
by John Arbash Meinel
 Added mode to the appropriate transport functions, and tests to make sure they work.  | 
410  | 
import traceback  | 
411  | 
mutter(traceback.format_exc())  | 
|
| 
1185.49.1
by John Arbash Meinel
 Updating SftpTransport.put() so that it is atomic  | 
412  | 
try:  | 
| 
1185.31.47
by John Arbash Meinel
 Added a fancy footwork rename to osutils, made SftpTransport use it.  | 
413  | 
if not closed:  | 
414  | 
fout.close()  | 
|
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
415  | 
self._get_sftp().remove(tmp_abspath)  | 
| 
1185.49.1
by John Arbash Meinel
 Updating SftpTransport.put() so that it is atomic  | 
416  | 
except:  | 
| 
1532
by Robert Collins
 Merge in John Meinels integration branch.  | 
417  | 
                # raise the saved except
 | 
418  | 
raise e  | 
|
419  | 
            # raise the original with its traceback if we can.
 | 
|
420  | 
            raise
 | 
|
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
421  | 
|
| 
1955.3.27
by John Arbash Meinel
 rename non_atomic_put_* to put_*non_atomic, and re-order the functions  | 
422  | 
def _put_non_atomic_helper(self, relpath, writer, mode=None,  | 
| 
1946.2.12
by John Arbash Meinel
 Add ability to pass a directory mode to non_atomic_put  | 
423  | 
create_parent_dir=False,  | 
424  | 
dir_mode=None):  | 
|
| 
1946.1.6
by John Arbash Meinel
 Basic implementation of non_atomic_put for sftp  | 
425  | 
abspath = self._remote_path(relpath)  | 
| 
1946.1.8
by John Arbash Meinel
 Update non_atomic_put to have a create_parent_dir flag  | 
426  | 
|
427  | 
        # TODO: jam 20060816 paramiko doesn't publicly expose a way to
 | 
|
428  | 
        #       set the file mode at create time. If it does, use it.
 | 
|
429  | 
        #       But for now, we just chmod later anyway.
 | 
|
| 
1946.1.6
by John Arbash Meinel
 Basic implementation of non_atomic_put for sftp  | 
430  | 
|
| 
1946.1.8
by John Arbash Meinel
 Update non_atomic_put to have a create_parent_dir flag  | 
431  | 
def _open_and_write_file():  | 
432  | 
"""Try to open the target file, raise error on failure"""  | 
|
| 
1946.1.10
by John Arbash Meinel
 make sure to always close the file object.  | 
433  | 
fout = None  | 
| 
1946.1.8
by John Arbash Meinel
 Update non_atomic_put to have a create_parent_dir flag  | 
434  | 
try:  | 
| 
1946.1.10
by John Arbash Meinel
 make sure to always close the file object.  | 
435  | 
try:  | 
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
436  | 
fout = self._get_sftp().file(abspath, mode='wb')  | 
| 
1946.1.10
by John Arbash Meinel
 make sure to always close the file object.  | 
437  | 
fout.set_pipelined(True)  | 
| 
1955.3.21
by John Arbash Meinel
 Update the LocalTransport and SftpTransport to implement non_atomic_*  | 
438  | 
writer(fout)  | 
| 
1946.1.10
by John Arbash Meinel
 make sure to always close the file object.  | 
439  | 
except (paramiko.SSHException, IOError), e:  | 
| 
1955.3.21
by John Arbash Meinel
 Update the LocalTransport and SftpTransport to implement non_atomic_*  | 
440  | 
self._translate_io_exception(e, abspath,  | 
441  | 
': unable to open')  | 
|
| 
1946.1.8
by John Arbash Meinel
 Update non_atomic_put to have a create_parent_dir flag  | 
442  | 
|
| 
1946.1.10
by John Arbash Meinel
 make sure to always close the file object.  | 
443  | 
                # This is designed to chmod() right before we close.
 | 
444  | 
                # Because we set_pipelined() earlier, theoretically we might 
 | 
|
445  | 
                # avoid the round trip for fout.close()
 | 
|
446  | 
if mode is not None:  | 
|
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
447  | 
self._get_sftp().chmod(abspath, mode)  | 
| 
1946.1.10
by John Arbash Meinel
 make sure to always close the file object.  | 
448  | 
finally:  | 
449  | 
if fout is not None:  | 
|
450  | 
fout.close()  | 
|
| 
1946.1.8
by John Arbash Meinel
 Update non_atomic_put to have a create_parent_dir flag  | 
451  | 
|
452  | 
if not create_parent_dir:  | 
|
453  | 
_open_and_write_file()  | 
|
454  | 
            return
 | 
|
455  | 
||
456  | 
        # Try error handling to create the parent directory if we need to
 | 
|
457  | 
try:  | 
|
458  | 
_open_and_write_file()  | 
|
459  | 
except NoSuchFile:  | 
|
460  | 
            # Try to create the parent directory, and then go back to
 | 
|
461  | 
            # writing the file
 | 
|
462  | 
parent_dir = os.path.dirname(abspath)  | 
|
| 
1946.2.15
by John Arbash Meinel
 Fix the sftp mkdir mode code  | 
463  | 
self._mkdir(parent_dir, dir_mode)  | 
| 
1946.1.8
by John Arbash Meinel
 Update non_atomic_put to have a create_parent_dir flag  | 
464  | 
_open_and_write_file()  | 
| 
1946.1.6
by John Arbash Meinel
 Basic implementation of non_atomic_put for sftp  | 
465  | 
|
| 
1955.3.27
by John Arbash Meinel
 rename non_atomic_put_* to put_*non_atomic, and re-order the functions  | 
466  | 
def put_file_non_atomic(self, relpath, f, mode=None,  | 
| 
1946.2.12
by John Arbash Meinel
 Add ability to pass a directory mode to non_atomic_put  | 
467  | 
create_parent_dir=False,  | 
468  | 
dir_mode=None):  | 
|
| 
1955.3.21
by John Arbash Meinel
 Update the LocalTransport and SftpTransport to implement non_atomic_*  | 
469  | 
"""Copy the file-like object into the target location.  | 
470  | 
||
471  | 
        This function is not strictly safe to use. It is only meant to
 | 
|
472  | 
        be used when you already know that the target does not exist.
 | 
|
473  | 
        It is not safe, because it will open and truncate the remote
 | 
|
474  | 
        file. So there may be a time when the file has invalid contents.
 | 
|
475  | 
||
476  | 
        :param relpath: The remote location to put the contents.
 | 
|
477  | 
        :param f:       File-like object.
 | 
|
478  | 
        :param mode:    Possible access permissions for new file.
 | 
|
479  | 
                        None means do not set remote permissions.
 | 
|
480  | 
        :param create_parent_dir: If we cannot create the target file because
 | 
|
481  | 
                        the parent directory does not exist, go ahead and
 | 
|
482  | 
                        create it, and then try again.
 | 
|
483  | 
        """
 | 
|
484  | 
def writer(fout):  | 
|
485  | 
self._pump(f, fout)  | 
|
| 
1955.3.27
by John Arbash Meinel
 rename non_atomic_put_* to put_*non_atomic, and re-order the functions  | 
486  | 
self._put_non_atomic_helper(relpath, writer, mode=mode,  | 
| 
1946.2.12
by John Arbash Meinel
 Add ability to pass a directory mode to non_atomic_put  | 
487  | 
create_parent_dir=create_parent_dir,  | 
488  | 
dir_mode=dir_mode)  | 
|
| 
1955.3.21
by John Arbash Meinel
 Update the LocalTransport and SftpTransport to implement non_atomic_*  | 
489  | 
|
| 
1955.3.27
by John Arbash Meinel
 rename non_atomic_put_* to put_*non_atomic, and re-order the functions  | 
490  | 
def put_bytes_non_atomic(self, relpath, bytes, mode=None,  | 
| 
1946.2.12
by John Arbash Meinel
 Add ability to pass a directory mode to non_atomic_put  | 
491  | 
create_parent_dir=False,  | 
492  | 
dir_mode=None):  | 
|
| 
1955.3.21
by John Arbash Meinel
 Update the LocalTransport and SftpTransport to implement non_atomic_*  | 
493  | 
def writer(fout):  | 
494  | 
fout.write(bytes)  | 
|
| 
1955.3.27
by John Arbash Meinel
 rename non_atomic_put_* to put_*non_atomic, and re-order the functions  | 
495  | 
self._put_non_atomic_helper(relpath, writer, mode=mode,  | 
| 
1946.2.12
by John Arbash Meinel
 Add ability to pass a directory mode to non_atomic_put  | 
496  | 
create_parent_dir=create_parent_dir,  | 
497  | 
dir_mode=dir_mode)  | 
|
| 
1955.3.21
by John Arbash Meinel
 Update the LocalTransport and SftpTransport to implement non_atomic_*  | 
498  | 
|
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
499  | 
def iter_files_recursive(self):  | 
500  | 
"""Walk the relative paths of all files in this transport."""  | 
|
501  | 
queue = list(self.list_dir('.'))  | 
|
502  | 
while queue:  | 
|
| 
1959.2.1
by John Arbash Meinel
 David Allouche: Make transports return escaped paths  | 
503  | 
relpath = queue.pop(0)  | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
504  | 
st = self.stat(relpath)  | 
505  | 
if stat.S_ISDIR(st.st_mode):  | 
|
506  | 
for i, basename in enumerate(self.list_dir(relpath)):  | 
|
507  | 
queue.insert(i, relpath+'/'+basename)  | 
|
508  | 
else:  | 
|
509  | 
yield relpath  | 
|
510  | 
||
| 
1988.1.1
by John Arbash Meinel
 Restore mode bit tests for sftp, and track down bugs  | 
511  | 
def _mkdir(self, abspath, mode=None):  | 
512  | 
if mode is None:  | 
|
513  | 
local_mode = 0777  | 
|
514  | 
else:  | 
|
515  | 
local_mode = mode  | 
|
516  | 
try:  | 
|
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
517  | 
self._get_sftp().mkdir(abspath, local_mode)  | 
| 
1988.1.1
by John Arbash Meinel
 Restore mode bit tests for sftp, and track down bugs  | 
518  | 
if mode is not None:  | 
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
519  | 
self._get_sftp().chmod(abspath, mode=mode)  | 
| 
1988.1.1
by John Arbash Meinel
 Restore mode bit tests for sftp, and track down bugs  | 
520  | 
except (paramiko.SSHException, IOError), e:  | 
521  | 
self._translate_io_exception(e, abspath, ': unable to mkdir',  | 
|
522  | 
failure_exc=FileExists)  | 
|
523  | 
||
| 
1185.58.2
by John Arbash Meinel
 Added mode to the appropriate transport functions, and tests to make sure they work.  | 
524  | 
def mkdir(self, relpath, mode=None):  | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
525  | 
"""Create a directory at the given path."""  | 
| 
1988.1.1
by John Arbash Meinel
 Restore mode bit tests for sftp, and track down bugs  | 
526  | 
self._mkdir(self._remote_path(relpath), mode=mode)  | 
| 
1185.50.13
by John Arbash Meinel
 Expanded the Transport test suite. Including delete, copy, move, etc. Updated SftpTransport to conform.  | 
527  | 
|
| 
2052.6.4
by Robert Collins
 Tidier SFTP code (feedback from Aaron).  | 
528  | 
def _translate_io_exception(self, e, path, more_info='',  | 
529  | 
failure_exc=PathError):  | 
|
| 
1185.50.13
by John Arbash Meinel
 Expanded the Transport test suite. Including delete, copy, move, etc. Updated SftpTransport to conform.  | 
530  | 
"""Translate a paramiko or IOError into a friendlier exception.  | 
531  | 
||
532  | 
        :param e: The original exception
 | 
|
533  | 
        :param path: The path in question when the error is raised
 | 
|
534  | 
        :param more_info: Extra information that can be included,
 | 
|
535  | 
                          such as what was going on
 | 
|
536  | 
        :param failure_exc: Paramiko has the super fun ability to raise completely
 | 
|
537  | 
                           opaque errors that just set "e.args = ('Failure',)" with
 | 
|
538  | 
                           no more information.
 | 
|
| 
1662.1.12
by Martin Pool
 Translate unknown sftp errors to PathError, no NoSuchFile  | 
539  | 
                           If this parameter is set, it defines the exception 
 | 
540  | 
                           to raise in these cases.
 | 
|
| 
1185.50.13
by John Arbash Meinel
 Expanded the Transport test suite. Including delete, copy, move, etc. Updated SftpTransport to conform.  | 
541  | 
        """
 | 
| 
1489
by Robert Collins
 Make the paramiko tests pass. Nice huh.  | 
542  | 
        # paramiko seems to generate detailless errors.
 | 
| 
1185.50.13
by John Arbash Meinel
 Expanded the Transport test suite. Including delete, copy, move, etc. Updated SftpTransport to conform.  | 
543  | 
self._translate_error(e, path, raise_generic=False)  | 
| 
1963.2.6
by Robey Pointer
 pychecker is on crack; go back to using 'is None'.  | 
544  | 
if getattr(e, 'args', None) is not None:  | 
| 
1185.31.44
by John Arbash Meinel
 Cleaned up Exceptions for all transports.  | 
545  | 
if (e.args == ('No such file or directory',) or  | 
546  | 
e.args == ('No such file',)):  | 
|
| 
1185.50.13
by John Arbash Meinel
 Expanded the Transport test suite. Including delete, copy, move, etc. Updated SftpTransport to conform.  | 
547  | 
raise NoSuchFile(path, str(e) + more_info)  | 
| 
1185.31.44
by John Arbash Meinel
 Cleaned up Exceptions for all transports.  | 
548  | 
if (e.args == ('mkdir failed',)):  | 
| 
1185.50.13
by John Arbash Meinel
 Expanded the Transport test suite. Including delete, copy, move, etc. Updated SftpTransport to conform.  | 
549  | 
raise FileExists(path, str(e) + more_info)  | 
| 
1185.31.44
by John Arbash Meinel
 Cleaned up Exceptions for all transports.  | 
550  | 
            # strange but true, for the paramiko server.
 | 
551  | 
if (e.args == ('Failure',)):  | 
|
| 
2052.6.4
by Robert Collins
 Tidier SFTP code (feedback from Aaron).  | 
552  | 
raise failure_exc(path, str(e) + more_info)  | 
| 
1185.58.2
by John Arbash Meinel
 Added mode to the appropriate transport functions, and tests to make sure they work.  | 
553  | 
mutter('Raising exception with args %s', e.args)  | 
| 
1963.2.6
by Robey Pointer
 pychecker is on crack; go back to using 'is None'.  | 
554  | 
if getattr(e, 'errno', None) is not None:  | 
| 
1185.58.2
by John Arbash Meinel
 Added mode to the appropriate transport functions, and tests to make sure they work.  | 
555  | 
mutter('Raising exception with errno %s', e.errno)  | 
| 
1185.31.44
by John Arbash Meinel
 Cleaned up Exceptions for all transports.  | 
556  | 
raise e  | 
| 
1489
by Robert Collins
 Make the paramiko tests pass. Nice huh.  | 
557  | 
|
| 
1955.3.15
by John Arbash Meinel
 Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes  | 
558  | 
def append_file(self, relpath, f, mode=None):  | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
559  | 
"""  | 
560  | 
        Append the text in the file-like object into the final
 | 
|
561  | 
        location.
 | 
|
562  | 
        """
 | 
|
563  | 
try:  | 
|
| 
1524.1.1
by Robert Collins
 Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir  | 
564  | 
path = self._remote_path(relpath)  | 
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
565  | 
fout = self._get_sftp().file(path, 'ab')  | 
| 
1666.1.6
by Robert Collins
 Make knit the default format.  | 
566  | 
if mode is not None:  | 
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
567  | 
self._get_sftp().chmod(path, mode)  | 
| 
1563.2.3
by Robert Collins
 Change the return signature of transport.append and append_multi to return the length of the pre-append content.  | 
568  | 
result = fout.tell()  | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
569  | 
self._pump(f, fout)  | 
| 
1563.2.3
by Robert Collins
 Change the return signature of transport.append and append_multi to return the length of the pre-append content.  | 
570  | 
return result  | 
| 
1185.50.13
by John Arbash Meinel
 Expanded the Transport test suite. Including delete, copy, move, etc. Updated SftpTransport to conform.  | 
571  | 
except (IOError, paramiko.SSHException), e:  | 
572  | 
self._translate_io_exception(e, relpath, ': unable to append')  | 
|
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
573  | 
|
| 
1553.5.13
by Martin Pool
 New Transport.rename that mustn't overwrite  | 
574  | 
def rename(self, rel_from, rel_to):  | 
575  | 
"""Rename without special overwriting"""  | 
|
576  | 
try:  | 
|
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
577  | 
self._get_sftp().rename(self._remote_path(rel_from),  | 
| 
1553.5.13
by Martin Pool
 New Transport.rename that mustn't overwrite  | 
578  | 
self._remote_path(rel_to))  | 
579  | 
except (IOError, paramiko.SSHException), e:  | 
|
580  | 
self._translate_io_exception(e, rel_from,  | 
|
581  | 
': unable to rename to %r' % (rel_to))  | 
|
582  | 
||
583  | 
def _rename_and_overwrite(self, abs_from, abs_to):  | 
|
| 
1185.31.47
by John Arbash Meinel
 Added a fancy footwork rename to osutils, made SftpTransport use it.  | 
584  | 
"""Do a fancy rename on the remote server.  | 
585  | 
        
 | 
|
586  | 
        Using the implementation provided by osutils.
 | 
|
587  | 
        """
 | 
|
588  | 
try:  | 
|
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
589  | 
sftp = self._get_sftp()  | 
| 
1185.31.47
by John Arbash Meinel
 Added a fancy footwork rename to osutils, made SftpTransport use it.  | 
590  | 
fancy_rename(abs_from, abs_to,  | 
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
591  | 
rename_func=sftp.rename,  | 
592  | 
unlink_func=sftp.remove)  | 
|
| 
1185.31.47
by John Arbash Meinel
 Added a fancy footwork rename to osutils, made SftpTransport use it.  | 
593  | 
except (IOError, paramiko.SSHException), e:  | 
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
594  | 
self._translate_io_exception(e, abs_from,  | 
595  | 
': unable to rename to %r' % (abs_to))  | 
|
| 
1185.31.47
by John Arbash Meinel
 Added a fancy footwork rename to osutils, made SftpTransport use it.  | 
596  | 
|
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
597  | 
def move(self, rel_from, rel_to):  | 
598  | 
"""Move the item at rel_from to the location at rel_to"""  | 
|
| 
1524.1.1
by Robert Collins
 Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir  | 
599  | 
path_from = self._remote_path(rel_from)  | 
600  | 
path_to = self._remote_path(rel_to)  | 
|
| 
1553.5.13
by Martin Pool
 New Transport.rename that mustn't overwrite  | 
601  | 
self._rename_and_overwrite(path_from, path_to)  | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
602  | 
|
603  | 
def delete(self, relpath):  | 
|
604  | 
"""Delete the item at relpath"""  | 
|
| 
1524.1.1
by Robert Collins
 Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir  | 
605  | 
path = self._remote_path(relpath)  | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
606  | 
try:  | 
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
607  | 
self._get_sftp().remove(path)  | 
| 
1185.50.13
by John Arbash Meinel
 Expanded the Transport test suite. Including delete, copy, move, etc. Updated SftpTransport to conform.  | 
608  | 
except (IOError, paramiko.SSHException), e:  | 
609  | 
self._translate_io_exception(e, path, ': unable to delete')  | 
|
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
610  | 
|
| 
2634.1.1
by Robert Collins
 (robertc) Reinstate the accidentally backed out external_url patch.  | 
611  | 
def external_url(self):  | 
612  | 
"""See bzrlib.transport.Transport.external_url."""  | 
|
613  | 
        # the external path for SFTP is the base
 | 
|
614  | 
return self.base  | 
|
615  | 
||
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
616  | 
def listable(self):  | 
617  | 
"""Return True if this store supports listing."""  | 
|
618  | 
return True  | 
|
619  | 
||
620  | 
def list_dir(self, relpath):  | 
|
621  | 
"""  | 
|
622  | 
        Return a list of all files at the given location.
 | 
|
623  | 
        """
 | 
|
624  | 
        # does anything actually use this?
 | 
|
| 
1959.2.1
by John Arbash Meinel
 David Allouche: Make transports return escaped paths  | 
625  | 
        # -- Unknown
 | 
626  | 
        # This is at least used by copy_tree for remote upgrades.
 | 
|
627  | 
        # -- David Allouche 2006-08-11
 | 
|
| 
1524.1.1
by Robert Collins
 Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir  | 
628  | 
path = self._remote_path(relpath)  | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
629  | 
try:  | 
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
630  | 
entries = self._get_sftp().listdir(path)  | 
| 
1185.50.13
by John Arbash Meinel
 Expanded the Transport test suite. Including delete, copy, move, etc. Updated SftpTransport to conform.  | 
631  | 
except (IOError, paramiko.SSHException), e:  | 
632  | 
self._translate_io_exception(e, path, ': failed to list_dir')  | 
|
| 
1959.2.2
by John Arbash Meinel
 Apply Andrew Bennetts list_dir fixes  | 
633  | 
return [urlutils.escape(entry) for entry in entries]  | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
634  | 
|
| 
1534.4.15
by Robert Collins
 Remove shutil dependency in upgrade - create a delete_tree method for transports.  | 
635  | 
def rmdir(self, relpath):  | 
636  | 
"""See Transport.rmdir."""  | 
|
637  | 
path = self._remote_path(relpath)  | 
|
638  | 
try:  | 
|
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
639  | 
return self._get_sftp().rmdir(path)  | 
| 
1534.4.15
by Robert Collins
 Remove shutil dependency in upgrade - create a delete_tree method for transports.  | 
640  | 
except (IOError, paramiko.SSHException), e:  | 
641  | 
self._translate_io_exception(e, path, ': failed to rmdir')  | 
|
642  | 
||
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
643  | 
def stat(self, relpath):  | 
644  | 
"""Return the stat information for a file."""  | 
|
| 
1524.1.1
by Robert Collins
 Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir  | 
645  | 
path = self._remote_path(relpath)  | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
646  | 
try:  | 
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
647  | 
return self._get_sftp().stat(path)  | 
| 
1185.50.13
by John Arbash Meinel
 Expanded the Transport test suite. Including delete, copy, move, etc. Updated SftpTransport to conform.  | 
648  | 
except (IOError, paramiko.SSHException), e:  | 
649  | 
self._translate_io_exception(e, path, ': unable to stat')  | 
|
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
650  | 
|
651  | 
def lock_read(self, relpath):  | 
|
652  | 
"""  | 
|
653  | 
        Lock the given file for shared (read) access.
 | 
|
| 
1185.49.3
by John Arbash Meinel
 Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path  | 
654  | 
        :return: A lock object, which has an unlock() member function
 | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
655  | 
        """
 | 
656  | 
        # FIXME: there should be something clever i can do here...
 | 
|
657  | 
class BogusLock(object):  | 
|
658  | 
def __init__(self, path):  | 
|
659  | 
self.path = path  | 
|
660  | 
def unlock(self):  | 
|
661  | 
                pass
 | 
|
662  | 
return BogusLock(relpath)  | 
|
663  | 
||
664  | 
def lock_write(self, relpath):  | 
|
665  | 
"""  | 
|
666  | 
        Lock the given file for exclusive (write) access.
 | 
|
667  | 
        WARNING: many transports do not support this, so trying avoid using it
 | 
|
668  | 
||
| 
1185.49.3
by John Arbash Meinel
 Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path  | 
669  | 
        :return: A lock object, which has an unlock() member function
 | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
670  | 
        """
 | 
| 
1185.49.2
by John Arbash Meinel
 Adding a open_exclusive function since paramiko supports it, but doesn't expose it  | 
671  | 
        # This is a little bit bogus, but basically, we create a file
 | 
672  | 
        # which should not already exist, and if it does, we assume
 | 
|
673  | 
        # that there is a lock, and if it doesn't, the we assume
 | 
|
674  | 
        # that we have taken the lock.
 | 
|
| 
1185.49.3
by John Arbash Meinel
 Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path  | 
675  | 
return SFTPLock(relpath, self)  | 
| 
1185.16.87
by mbp at sourcefrog
 - fix line endings in sftp transport  | 
676  | 
|
| 
1185.58.2
by John Arbash Meinel
 Added mode to the appropriate transport functions, and tests to make sure they work.  | 
677  | 
def _sftp_open_exclusive(self, abspath, mode=None):  | 
| 
1185.49.2
by John Arbash Meinel
 Adding a open_exclusive function since paramiko supports it, but doesn't expose it  | 
678  | 
"""Open a remote path exclusively.  | 
679  | 
||
680  | 
        SFTP supports O_EXCL (SFTP_FLAG_EXCL), which fails if
 | 
|
681  | 
        the file already exists. However it does not expose this
 | 
|
682  | 
        at the higher level of SFTPClient.open(), so we have to
 | 
|
683  | 
        sneak away with it.
 | 
|
684  | 
||
685  | 
        WARNING: This breaks the SFTPClient abstraction, so it
 | 
|
686  | 
        could easily break against an updated version of paramiko.
 | 
|
687  | 
||
| 
1185.58.2
by John Arbash Meinel
 Added mode to the appropriate transport functions, and tests to make sure they work.  | 
688  | 
        :param abspath: The remote absolute path where the file should be opened
 | 
689  | 
        :param mode: The mode permissions bits for the new file
 | 
|
| 
1185.49.2
by John Arbash Meinel
 Adding a open_exclusive function since paramiko supports it, but doesn't expose it  | 
690  | 
        """
 | 
| 
1946.1.8
by John Arbash Meinel
 Update non_atomic_put to have a create_parent_dir flag  | 
691  | 
        # TODO: jam 20060816 Paramiko >= 1.6.2 (probably earlier) supports
 | 
692  | 
        #       using the 'x' flag to indicate SFTP_FLAG_EXCL.
 | 
|
693  | 
        #       However, there is no way to set the permission mode at open 
 | 
|
694  | 
        #       time using the sftp_client.file() functionality.
 | 
|
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
695  | 
path = self._get_sftp()._adjust_cwd(abspath)  | 
| 
1711.5.1
by John Arbash Meinel
 Get most SFTP tests to pass. StubSFTPServer now talks the same path protocol that SFTPTransport talks. on win32  | 
696  | 
        # mutter('sftp abspath %s => %s', abspath, path)
 | 
| 
1185.49.2
by John Arbash Meinel
 Adding a open_exclusive function since paramiko supports it, but doesn't expose it  | 
697  | 
attr = SFTPAttributes()  | 
| 
1185.58.2
by John Arbash Meinel
 Added mode to the appropriate transport functions, and tests to make sure they work.  | 
698  | 
if mode is not None:  | 
699  | 
attr.st_mode = mode  | 
|
700  | 
omode = (SFTP_FLAG_WRITE | SFTP_FLAG_CREATE  | 
|
| 
1185.49.2
by John Arbash Meinel
 Adding a open_exclusive function since paramiko supports it, but doesn't expose it  | 
701  | 
| SFTP_FLAG_TRUNC | SFTP_FLAG_EXCL)  | 
702  | 
try:  | 
|
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
703  | 
t, msg = self._get_sftp()._request(CMD_OPEN, path, omode, attr)  | 
| 
1185.49.2
by John Arbash Meinel
 Adding a open_exclusive function since paramiko supports it, but doesn't expose it  | 
704  | 
if t != CMD_HANDLE:  | 
| 
1185.31.44
by John Arbash Meinel
 Cleaned up Exceptions for all transports.  | 
705  | 
raise TransportError('Expected an SFTP handle')  | 
| 
1185.49.2
by John Arbash Meinel
 Adding a open_exclusive function since paramiko supports it, but doesn't expose it  | 
706  | 
handle = msg.get_string()  | 
| 
2485.8.38
by Vincent Ladeuil
 Finish sftp refactoring. Test suite passing.  | 
707  | 
return SFTPFile(self._get_sftp(), handle, 'wb', -1)  | 
| 
1185.31.44
by John Arbash Meinel
 Cleaned up Exceptions for all transports.  | 
708  | 
except (paramiko.SSHException, IOError), e:  | 
| 
1185.58.2
by John Arbash Meinel
 Added mode to the appropriate transport functions, and tests to make sure they work.  | 
709  | 
self._translate_io_exception(e, abspath, ': unable to open',  | 
| 
1185.50.13
by John Arbash Meinel
 Expanded the Transport test suite. Including delete, copy, move, etc. Updated SftpTransport to conform.  | 
710  | 
failure_exc=FileExists)  | 
| 
1185.49.2
by John Arbash Meinel
 Adding a open_exclusive function since paramiko supports it, but doesn't expose it  | 
711  | 
|
| 
1988.1.1
by John Arbash Meinel
 Restore mode bit tests for sftp, and track down bugs  | 
712  | 
def _can_roundtrip_unix_modebits(self):  | 
713  | 
if sys.platform == 'win32':  | 
|
714  | 
            # anyone else?
 | 
|
715  | 
return False  | 
|
716  | 
else:  | 
|
717  | 
return True  | 
|
| 
1530.1.1
by Robert Collins
 Minimal infrastructure to test TransportTestProviderAdapter.  | 
718  | 
|
| 
1530.1.3
by Robert Collins
 transport implementations now tested consistently.  | 
719  | 
# ------------- server test implementation --------------
 | 
720  | 
import threading  | 
|
721  | 
||
722  | 
from bzrlib.tests.stub_sftp import StubServer, StubSFTPServer  | 
|
723  | 
||
724  | 
STUB_SERVER_KEY = """  | 
|
725  | 
-----BEGIN RSA PRIVATE KEY-----
 | 
|
726  | 
MIICWgIBAAKBgQDTj1bqB4WmayWNPB+8jVSYpZYk80Ujvj680pOTh2bORBjbIAyz
 | 
|
727  | 
oWGW+GUjzKxTiiPvVmxFgx5wdsFvF03v34lEVVhMpouqPAYQ15N37K/ir5XY+9m/
 | 
|
728  | 
d8ufMCkjeXsQkKqFbAlQcnWMCRnOoPHS3I4vi6hmnDDeeYTSRvfLbW0fhwIBIwKB
 | 
|
729  | 
gBIiOqZYaoqbeD9OS9z2K9KR2atlTxGxOJPXiP4ESqP3NVScWNwyZ3NXHpyrJLa0
 | 
|
730  | 
EbVtzsQhLn6rF+TzXnOlcipFvjsem3iYzCpuChfGQ6SovTcOjHV9z+hnpXvQ/fon
 | 
|
731  | 
soVRZY65wKnF7IAoUwTmJS9opqgrN6kRgCd3DASAMd1bAkEA96SBVWFt/fJBNJ9H
 | 
|
732  | 
tYnBKZGw0VeHOYmVYbvMSstssn8un+pQpUm9vlG/bp7Oxd/m+b9KWEh2xPfv6zqU
 | 
|
733  | 
avNwHwJBANqzGZa/EpzF4J8pGti7oIAPUIDGMtfIcmqNXVMckrmzQ2vTfqtkEZsA
 | 
|
734  | 
4rE1IERRyiJQx6EJsz21wJmGV9WJQ5kCQQDwkS0uXqVdFzgHO6S++tjmjYcxwr3g
 | 
|
735  | 
H0CoFYSgbddOT6miqRskOQF3DZVkJT3kyuBgU2zKygz52ukQZMqxCb1fAkASvuTv
 | 
|
736  | 
qfpH87Qq5kQhNKdbbwbmd2NxlNabazPijWuphGTdW0VfJdWfklyS2Kr+iqrs/5wV
 | 
|
737  | 
HhathJt636Eg7oIjAkA8ht3MQ+XSl9yIJIS8gVpbPxSw5OMfw0PjVE7tBdQruiSc
 | 
|
738  | 
nvuQES5C9BMHjF39LZiGH1iLQy7FgdHyoP+eodI7
 | 
|
739  | 
-----END RSA PRIVATE KEY-----
 | 
|
740  | 
"""
 | 
|
| 
1551.6.39
by Aaron Bentley
 Apply Robey Pointer's listener patch  | 
741  | 
|
742  | 
||
743  | 
class SocketListener(threading.Thread):  | 
|
| 
1530.1.3
by Robert Collins
 transport implementations now tested consistently.  | 
744  | 
|
745  | 
def __init__(self, callback):  | 
|
746  | 
threading.Thread.__init__(self)  | 
|
747  | 
self._callback = callback  | 
|
748  | 
self._socket = socket.socket()  | 
|
749  | 
self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  | 
|
750  | 
self._socket.bind(('localhost', 0))  | 
|
751  | 
self._socket.listen(1)  | 
|
752  | 
self.port = self._socket.getsockname()[1]  | 
|
| 
1551.6.39
by Aaron Bentley
 Apply Robey Pointer's listener patch  | 
753  | 
self._stop_event = threading.Event()  | 
| 
1547.1.1
by Robey Pointer
 modify the sftp unit tests to perform sftp over a direct localhost socket instead of over an actual ssh2 transport  | 
754  | 
|
| 
1530.1.3
by Robert Collins
 transport implementations now tested consistently.  | 
755  | 
def stop(self):  | 
| 
1551.6.39
by Aaron Bentley
 Apply Robey Pointer's listener patch  | 
756  | 
        # called from outside this thread
 | 
757  | 
self._stop_event.set()  | 
|
| 
1547.1.1
by Robey Pointer
 modify the sftp unit tests to perform sftp over a direct localhost socket instead of over an actual ssh2 transport  | 
758  | 
        # use a timeout here, because if the test fails, the server thread may
 | 
759  | 
        # never notice the stop_event.
 | 
|
760  | 
self.join(5.0)  | 
|
| 
1551.6.39
by Aaron Bentley
 Apply Robey Pointer's listener patch  | 
761  | 
self._socket.close()  | 
762  | 
||
763  | 
def run(self):  | 
|
764  | 
while True:  | 
|
| 
1551.6.40
by Aaron Bentley
 Wrapped long lines in Robey's patch  | 
765  | 
readable, writable_unused, exception_unused = \  | 
766  | 
select.select([self._socket], [], [], 0.1)  | 
|
| 
1551.6.39
by Aaron Bentley
 Apply Robey Pointer's listener patch  | 
767  | 
if self._stop_event.isSet():  | 
768  | 
                return
 | 
|
769  | 
if len(readable) == 0:  | 
|
770  | 
                continue
 | 
|
771  | 
try:  | 
|
772  | 
s, addr_unused = self._socket.accept()  | 
|
773  | 
                # because the loopback socket is inline, and transports are
 | 
|
774  | 
                # never explicitly closed, best to launch a new thread.
 | 
|
775  | 
threading.Thread(target=self._callback, args=(s,)).start()  | 
|
776  | 
except socket.error, x:  | 
|
777  | 
sys.excepthook(*sys.exc_info())  | 
|
| 
1551.6.40
by Aaron Bentley
 Wrapped long lines in Robey's patch  | 
778  | 
warning('Socket error during accept() within unit test server'  | 
779  | 
' thread: %r' % x)  | 
|
| 
1551.6.39
by Aaron Bentley
 Apply Robey Pointer's listener patch  | 
780  | 
except Exception, x:  | 
| 
1551.6.40
by Aaron Bentley
 Wrapped long lines in Robey's patch  | 
781  | 
                # probably a failed test; unit test thread will log the
 | 
782  | 
                # failure/error
 | 
|
| 
1551.6.39
by Aaron Bentley
 Apply Robey Pointer's listener patch  | 
783  | 
sys.excepthook(*sys.exc_info())  | 
| 
1551.6.40
by Aaron Bentley
 Wrapped long lines in Robey's patch  | 
784  | 
warning('Exception from within unit test server thread: %r' %  | 
785  | 
x)  | 
|
| 
1547.1.1
by Robey Pointer
 modify the sftp unit tests to perform sftp over a direct localhost socket instead of over an actual ssh2 transport  | 
786  | 
|
787  | 
||
| 
1871.1.3
by Robert Collins
 proof of concept slowsocket wrapper.  | 
788  | 
class SocketDelay(object):  | 
789  | 
"""A socket decorator to make TCP appear slower.  | 
|
790  | 
||
| 
1874.1.2
by Carl Friedrich Bolz
 Refined the SocketDelay to charge latency only once per round-trip and to  | 
791  | 
    This changes recv, send, and sendall to add a fixed latency to each python
 | 
792  | 
    call if a new roundtrip is detected. That is, when a recv is called and the
 | 
|
793  | 
    flag new_roundtrip is set, latency is charged. Every send and send_all
 | 
|
794  | 
    sets this flag.
 | 
|
795  | 
||
796  | 
    In addition every send, sendall and recv sleeps a bit per character send to
 | 
|
797  | 
    simulate bandwidth.
 | 
|
798  | 
||
799  | 
    Not all methods are implemented, this is deliberate as this class is not a
 | 
|
800  | 
    replacement for the builtin sockets layer. fileno is not implemented to
 | 
|
801  | 
    prevent the proxy being bypassed. 
 | 
|
| 
1871.1.3
by Robert Collins
 proof of concept slowsocket wrapper.  | 
802  | 
    """
 | 
803  | 
||
| 
1874.1.2
by Carl Friedrich Bolz
 Refined the SocketDelay to charge latency only once per round-trip and to  | 
804  | 
simulated_time = 0  | 
| 
1874.1.9
by Carl Friedrich Bolz
 Try to fix all the issues outline by john and Robert.  | 
805  | 
_proxied_arguments = dict.fromkeys([  | 
806  | 
"close", "getpeername", "getsockname", "getsockopt", "gettimeout",  | 
|
807  | 
"setblocking", "setsockopt", "settimeout", "shutdown"])  | 
|
| 
1874.1.2
by Carl Friedrich Bolz
 Refined the SocketDelay to charge latency only once per round-trip and to  | 
808  | 
|
| 
1874.1.5
by holger krekel
 (cfbolz, hpk) Refactored bandwidth parameter. Fixed indentation bug in 'send'.  | 
809  | 
def __init__(self, sock, latency, bandwidth=1.0,  | 
| 
1874.1.9
by Carl Friedrich Bolz
 Try to fix all the issues outline by john and Robert.  | 
810  | 
really_sleep=True):  | 
| 
1874.1.5
by holger krekel
 (cfbolz, hpk) Refactored bandwidth parameter. Fixed indentation bug in 'send'.  | 
811  | 
"""  | 
812  | 
        :param bandwith: simulated bandwith (MegaBit)
 | 
|
| 
1874.1.9
by Carl Friedrich Bolz
 Try to fix all the issues outline by john and Robert.  | 
813  | 
        :param really_sleep: If set to false, the SocketDelay will just
 | 
814  | 
        increase a counter, instead of calling time.sleep. This is useful for
 | 
|
815  | 
        unittesting the SocketDelay.
 | 
|
| 
1874.1.5
by holger krekel
 (cfbolz, hpk) Refactored bandwidth parameter. Fixed indentation bug in 'send'.  | 
816  | 
        """
 | 
| 
1871.1.3
by Robert Collins
 proof of concept slowsocket wrapper.  | 
817  | 
self.sock = sock  | 
818  | 
self.latency = latency  | 
|
| 
1874.1.2
by Carl Friedrich Bolz
 Refined the SocketDelay to charge latency only once per round-trip and to  | 
819  | 
self.really_sleep = really_sleep  | 
| 
1874.1.5
by holger krekel
 (cfbolz, hpk) Refactored bandwidth parameter. Fixed indentation bug in 'send'.  | 
820  | 
self.time_per_byte = 1 / (bandwidth / 8.0 * 1024 * 1024)  | 
| 
1874.1.2
by Carl Friedrich Bolz
 Refined the SocketDelay to charge latency only once per round-trip and to  | 
821  | 
self.new_roundtrip = False  | 
822  | 
||
823  | 
def sleep(self, s):  | 
|
824  | 
if self.really_sleep:  | 
|
825  | 
time.sleep(s)  | 
|
| 
1874.1.9
by Carl Friedrich Bolz
 Try to fix all the issues outline by john and Robert.  | 
826  | 
else:  | 
827  | 
SocketDelay.simulated_time += s  | 
|
| 
1871.1.3
by Robert Collins
 proof of concept slowsocket wrapper.  | 
828  | 
|
| 
1874.1.9
by Carl Friedrich Bolz
 Try to fix all the issues outline by john and Robert.  | 
829  | 
def __getattr__(self, attr):  | 
830  | 
if attr in SocketDelay._proxied_arguments:  | 
|
831  | 
return getattr(self.sock, attr)  | 
|
832  | 
raise AttributeError("'SocketDelay' object has no attribute %r" %  | 
|
833  | 
attr)  | 
|
| 
1871.1.3
by Robert Collins
 proof of concept slowsocket wrapper.  | 
834  | 
|
835  | 
def dup(self):  | 
|
| 
1874.1.5
by holger krekel
 (cfbolz, hpk) Refactored bandwidth parameter. Fixed indentation bug in 'send'.  | 
836  | 
return SocketDelay(self.sock.dup(), self.latency, self.time_per_byte,  | 
| 
1874.1.2
by Carl Friedrich Bolz
 Refined the SocketDelay to charge latency only once per round-trip and to  | 
837  | 
self._sleep)  | 
| 
1871.1.3
by Robert Collins
 proof of concept slowsocket wrapper.  | 
838  | 
|
839  | 
def recv(self, *args):  | 
|
840  | 
data = self.sock.recv(*args)  | 
|
| 
1874.1.2
by Carl Friedrich Bolz
 Refined the SocketDelay to charge latency only once per round-trip and to  | 
841  | 
if data and self.new_roundtrip:  | 
842  | 
self.new_roundtrip = False  | 
|
843  | 
self.sleep(self.latency)  | 
|
| 
1874.1.5
by holger krekel
 (cfbolz, hpk) Refactored bandwidth parameter. Fixed indentation bug in 'send'.  | 
844  | 
self.sleep(len(data) * self.time_per_byte)  | 
| 
1871.1.3
by Robert Collins
 proof of concept slowsocket wrapper.  | 
845  | 
return data  | 
846  | 
||
| 
1874.1.2
by Carl Friedrich Bolz
 Refined the SocketDelay to charge latency only once per round-trip and to  | 
847  | 
def sendall(self, data, flags=0):  | 
848  | 
if not self.new_roundtrip:  | 
|
849  | 
self.new_roundtrip = True  | 
|
850  | 
self.sleep(self.latency)  | 
|
| 
1874.1.5
by holger krekel
 (cfbolz, hpk) Refactored bandwidth parameter. Fixed indentation bug in 'send'.  | 
851  | 
self.sleep(len(data) * self.time_per_byte)  | 
| 
1874.1.2
by Carl Friedrich Bolz
 Refined the SocketDelay to charge latency only once per round-trip and to  | 
852  | 
return self.sock.sendall(data, flags)  | 
| 
1871.1.3
by Robert Collins
 proof of concept slowsocket wrapper.  | 
853  | 
|
| 
1874.1.2
by Carl Friedrich Bolz
 Refined the SocketDelay to charge latency only once per round-trip and to  | 
854  | 
def send(self, data, flags=0):  | 
855  | 
if not self.new_roundtrip:  | 
|
856  | 
self.new_roundtrip = True  | 
|
857  | 
self.sleep(self.latency)  | 
|
858  | 
bytes_sent = self.sock.send(data, flags)  | 
|
| 
1874.1.5
by holger krekel
 (cfbolz, hpk) Refactored bandwidth parameter. Fixed indentation bug in 'send'.  | 
859  | 
self.sleep(bytes_sent * self.time_per_byte)  | 
| 
1874.1.2
by Carl Friedrich Bolz
 Refined the SocketDelay to charge latency only once per round-trip and to  | 
860  | 
return bytes_sent  | 
| 
1871.1.3
by Robert Collins
 proof of concept slowsocket wrapper.  | 
861  | 
|
862  | 
||
| 
1530.1.3
by Robert Collins
 transport implementations now tested consistently.  | 
863  | 
class SFTPServer(Server):  | 
864  | 
"""Common code for SFTP server facilities."""  | 
|
865  | 
||
| 
2018.1.1
by Andrew Bennetts
 Make bzr+ssh:// actually work (at least with absolute paths).  | 
866  | 
def __init__(self, server_interface=StubServer):  | 
| 
1530.1.3
by Robert Collins
 transport implementations now tested consistently.  | 
867  | 
self._original_vendor = None  | 
868  | 
self._homedir = None  | 
|
| 
1530.1.8
by Robert Collins
 More NEWS, move sibling sftp tests into new framework, nuke legacy local transport tests.  | 
869  | 
self._server_homedir = None  | 
| 
1530.1.3
by Robert Collins
 transport implementations now tested consistently.  | 
870  | 
self._listener = None  | 
871  | 
self._root = None  | 
|
| 
1951.1.8
by Andrew Bennetts
 Make _get_ssh_vendor return the vendor object, rather than just a string.  | 
872  | 
self._vendor = ssh.ParamikoVendor()  | 
| 
2018.1.1
by Andrew Bennetts
 Make bzr+ssh:// actually work (at least with absolute paths).  | 
873  | 
self._server_interface = server_interface  | 
| 
1530.1.6
by Robert Collins
 Trim duplicate sftp tests.  | 
874  | 
        # sftp server logs
 | 
875  | 
self.logs = []  | 
|
| 
1871.1.3
by Robert Collins
 proof of concept slowsocket wrapper.  | 
876  | 
self.add_latency = 0  | 
| 
1530.1.3
by Robert Collins
 transport implementations now tested consistently.  | 
877  | 
|
| 
1547.1.1
by Robey Pointer
 modify the sftp unit tests to perform sftp over a direct localhost socket instead of over an actual ssh2 transport  | 
878  | 
def _get_sftp_url(self, path):  | 
879  | 
"""Calculate an sftp url to this server for path."""  | 
|
880  | 
return 'sftp://foo:bar@localhost:%d/%s' % (self._listener.port, path)  | 
|
881  | 
||
| 
1530.1.6
by Robert Collins
 Trim duplicate sftp tests.  | 
882  | 
def log(self, message):  | 
| 
1547.1.1
by Robey Pointer
 modify the sftp unit tests to perform sftp over a direct localhost socket instead of over an actual ssh2 transport  | 
883  | 
"""StubServer uses this to log when a new server is created."""  | 
| 
1530.1.6
by Robert Collins
 Trim duplicate sftp tests.  | 
884  | 
self.logs.append(message)  | 
| 
1530.1.3
by Robert Collins
 transport implementations now tested consistently.  | 
885  | 
|
| 
1871.1.3
by Robert Collins
 proof of concept slowsocket wrapper.  | 
886  | 
def _run_server_entry(self, sock):  | 
887  | 
"""Entry point for all implementations of _run_server.  | 
|
888  | 
        
 | 
|
889  | 
        If self.add_latency is > 0.000001 then sock is given a latency adding
 | 
|
890  | 
        decorator.
 | 
|
891  | 
        """
 | 
|
892  | 
if self.add_latency > 0.000001:  | 
|
893  | 
sock = SocketDelay(sock, self.add_latency)  | 
|
894  | 
return self._run_server(sock)  | 
|
895  | 
||
| 
1551.6.39
by Aaron Bentley
 Apply Robey Pointer's listener patch  | 
896  | 
def _run_server(self, s):  | 
| 
1530.1.3
by Robert Collins
 transport implementations now tested consistently.  | 
897  | 
ssh_server = paramiko.Transport(s)  | 
| 
1711.5.1
by John Arbash Meinel
 Get most SFTP tests to pass. StubSFTPServer now talks the same path protocol that SFTPTransport talks. on win32  | 
898  | 
key_file = pathjoin(self._homedir, 'test_rsa.key')  | 
| 
1551.6.39
by Aaron Bentley
 Apply Robey Pointer's listener patch  | 
899  | 
f = open(key_file, 'w')  | 
900  | 
f.write(STUB_SERVER_KEY)  | 
|
901  | 
f.close()  | 
|
| 
1530.1.3
by Robert Collins
 transport implementations now tested consistently.  | 
902  | 
host_key = paramiko.RSAKey.from_private_key_file(key_file)  | 
903  | 
ssh_server.add_server_key(host_key)  | 
|
| 
2018.1.1
by Andrew Bennetts
 Make bzr+ssh:// actually work (at least with absolute paths).  | 
904  | 
server = self._server_interface(self)  | 
| 
1530.1.3
by Robert Collins
 transport implementations now tested consistently.  | 
905  | 
ssh_server.set_subsystem_handler('sftp', paramiko.SFTPServer,  | 
906  | 
StubSFTPServer, root=self._root,  | 
|
| 
1530.1.8
by Robert Collins
 More NEWS, move sibling sftp tests into new framework, nuke legacy local transport tests.  | 
907  | 
home=self._server_homedir)  | 
| 
1530.1.3
by Robert Collins
 transport implementations now tested consistently.  | 
908  | 
event = threading.Event()  | 
909  | 
ssh_server.start_server(event, server)  | 
|
910  | 
event.wait(5.0)  | 
|
| 
2221.5.21
by Dmitry Vasiliev
 Reverted trailing whitespace removal  | 
911  | 
|
| 
2018.5.114
by Robert Collins
 Commit current test pass improvements.  | 
912  | 
def setUp(self, backing_server=None):  | 
913  | 
        # XXX: TODO: make sftpserver back onto backing_server rather than local
 | 
|
914  | 
        # disk.
 | 
|
915  | 
assert (backing_server is None or  | 
|
916  | 
isinstance(backing_server, local.LocalURLServer)), (  | 
|
917  | 
"backing_server should not be %r, because this can only serve the "  | 
|
918  | 
"local current working directory." % (backing_server,))  | 
|
| 
2221.5.18
by Dmitry Vasiliev
 Fixed variable name  | 
919  | 
self._original_vendor = ssh._ssh_vendor_manager._cached_ssh_vendor  | 
920  | 
ssh._ssh_vendor_manager._cached_ssh_vendor = self._vendor  | 
|
| 
1711.6.3
by John Arbash Meinel
 Fix regression on unicode tests for SFTP under Linux  | 
921  | 
if sys.platform == 'win32':  | 
922  | 
            # Win32 needs to use the UNICODE api
 | 
|
923  | 
self._homedir = getcwd()  | 
|
924  | 
else:  | 
|
925  | 
            # But Linux SFTP servers should just deal in bytestreams
 | 
|
926  | 
self._homedir = os.getcwd()  | 
|
| 
1530.1.8
by Robert Collins
 More NEWS, move sibling sftp tests into new framework, nuke legacy local transport tests.  | 
927  | 
if self._server_homedir is None:  | 
928  | 
self._server_homedir = self._homedir  | 
|
| 
1530.1.3
by Robert Collins
 transport implementations now tested consistently.  | 
929  | 
self._root = '/'  | 
| 
1711.5.1
by John Arbash Meinel
 Get most SFTP tests to pass. StubSFTPServer now talks the same path protocol that SFTPTransport talks. on win32  | 
930  | 
if sys.platform == 'win32':  | 
931  | 
self._root = ''  | 
|
| 
1871.1.3
by Robert Collins
 proof of concept slowsocket wrapper.  | 
932  | 
self._listener = SocketListener(self._run_server_entry)  | 
| 
1530.1.3
by Robert Collins
 transport implementations now tested consistently.  | 
933  | 
self._listener.setDaemon(True)  | 
934  | 
self._listener.start()  | 
|
935  | 
||
936  | 
def tearDown(self):  | 
|
937  | 
"""See bzrlib.transport.Server.tearDown."""  | 
|
938  | 
self._listener.stop()  | 
|
| 
2221.5.18
by Dmitry Vasiliev
 Fixed variable name  | 
939  | 
ssh._ssh_vendor_manager._cached_ssh_vendor = self._original_vendor  | 
| 
1530.1.3
by Robert Collins
 transport implementations now tested consistently.  | 
940  | 
|
| 
1711.2.42
by John Arbash Meinel
 enable bogus_url support for SFTP tests  | 
941  | 
def get_bogus_url(self):  | 
942  | 
"""See bzrlib.transport.Server.get_bogus_url."""  | 
|
| 
1185.49.35
by John Arbash Meinel
 Update tests to use a truly unused port  | 
943  | 
        # this is chosen to try to prevent trouble with proxies, wierd dns, etc
 | 
944  | 
        # we bind a random socket, so that we get a guaranteed unused port
 | 
|
945  | 
        # we just never listen on that port
 | 
|
946  | 
s = socket.socket()  | 
|
947  | 
s.bind(('localhost', 0))  | 
|
948  | 
return 'sftp://%s:%s/' % s.getsockname()  | 
|
| 
1711.2.42
by John Arbash Meinel
 enable bogus_url support for SFTP tests  | 
949  | 
|
950  | 
||
| 
1534.4.50
by Robert Collins
 Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.  | 
951  | 
class SFTPFullAbsoluteServer(SFTPServer):  | 
952  | 
"""A test server for sftp transports, using absolute urls and ssh."""  | 
|
953  | 
||
954  | 
def get_url(self):  | 
|
955  | 
"""See bzrlib.transport.Server.get_url."""  | 
|
| 
2321.3.7
by Alexander Belchenko
 fixes for passing test_sftp_transport on win32 (thankyou John)  | 
956  | 
homedir = self._homedir  | 
957  | 
if sys.platform != 'win32':  | 
|
958  | 
            # Remove the initial '/' on all platforms but win32
 | 
|
959  | 
homedir = homedir[1:]  | 
|
960  | 
return self._get_sftp_url(urlutils.escape(homedir))  | 
|
| 
1534.4.50
by Robert Collins
 Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.  | 
961  | 
|
962  | 
||
| 
1547.1.1
by Robey Pointer
 modify the sftp unit tests to perform sftp over a direct localhost socket instead of over an actual ssh2 transport  | 
963  | 
class SFTPServerWithoutSSH(SFTPServer):  | 
| 
1534.4.50
by Robert Collins
 Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.  | 
964  | 
"""An SFTP server that uses a simple TCP socket pair rather than SSH."""  | 
| 
1547.1.1
by Robey Pointer
 modify the sftp unit tests to perform sftp over a direct localhost socket instead of over an actual ssh2 transport  | 
965  | 
|
966  | 
def __init__(self):  | 
|
967  | 
super(SFTPServerWithoutSSH, self).__init__()  | 
|
| 
1951.1.8
by Andrew Bennetts
 Make _get_ssh_vendor return the vendor object, rather than just a string.  | 
968  | 
self._vendor = ssh.LoopbackVendor()  | 
| 
1547.1.1
by Robey Pointer
 modify the sftp unit tests to perform sftp over a direct localhost socket instead of over an actual ssh2 transport  | 
969  | 
|
| 
1551.6.39
by Aaron Bentley
 Apply Robey Pointer's listener patch  | 
970  | 
def _run_server(self, sock):  | 
| 
1951.1.10
by Andrew Bennetts
 Move register_ssh_vendor, _ssh_vendor and _get_ssh_vendor into ssh.py  | 
971  | 
        # Re-import these as locals, so that they're still accessible during
 | 
972  | 
        # interpreter shutdown (when all module globals get set to None, leading
 | 
|
973  | 
        # to confusing errors like "'NoneType' object has no attribute 'error'".
 | 
|
| 
1547.1.1
by Robey Pointer
 modify the sftp unit tests to perform sftp over a direct localhost socket instead of over an actual ssh2 transport  | 
974  | 
class FakeChannel(object):  | 
975  | 
def get_transport(self):  | 
|
976  | 
return self  | 
|
977  | 
def get_log_channel(self):  | 
|
978  | 
return 'paramiko'  | 
|
979  | 
def get_name(self):  | 
|
980  | 
return '1'  | 
|
981  | 
def get_hexdump(self):  | 
|
982  | 
return False  | 
|
| 
1711.2.1
by John Arbash Meinel
 [patch] Marien Zwart: paramiko-1.6 compatibility fix  | 
983  | 
def close(self):  | 
984  | 
                pass
 | 
|
| 
1547.1.1
by Robey Pointer
 modify the sftp unit tests to perform sftp over a direct localhost socket instead of over an actual ssh2 transport  | 
985  | 
|
986  | 
server = paramiko.SFTPServer(FakeChannel(), 'sftp', StubServer(self), StubSFTPServer,  | 
|
987  | 
root=self._root, home=self._server_homedir)  | 
|
| 
1806.1.1
by Robey Pointer
 absorb a broken-pipe exception from paramiko when running the unit tests. it's okay for the client to vanish abruptly and paramiko really ought to mask the exception itself.  | 
988  | 
try:  | 
989  | 
server.start_subsystem('sftp', None, sock)  | 
|
990  | 
except socket.error, e:  | 
|
991  | 
if (len(e.args) > 0) and (e.args[0] == errno.EPIPE):  | 
|
992  | 
                # it's okay for the client to disconnect abruptly
 | 
|
993  | 
                # (bug in paramiko 1.6: it should absorb this exception)
 | 
|
994  | 
                pass
 | 
|
995  | 
else:  | 
|
996  | 
                raise
 | 
|
997  | 
except Exception, e:  | 
|
| 
2018.11.2
by Andrew Bennetts
 Hookup RemoteBranch for testing by bzrlib/tests/branch_implementations tests.  | 
998  | 
            # This typically seems to happen during interpreter shutdown, so
 | 
999  | 
            # most of the useful ways to report this error are won't work.
 | 
|
1000  | 
            # Writing the exception type, and then the text of the exception,
 | 
|
1001  | 
            # seems to be the best we can do.
 | 
|
1002  | 
import sys  | 
|
1003  | 
sys.stderr.write('\nEXCEPTION %r: ' % (e.__class__,))  | 
|
1004  | 
sys.stderr.write('%s\n\n' % (e,))  | 
|
| 
1547.1.1
by Robey Pointer
 modify the sftp unit tests to perform sftp over a direct localhost socket instead of over an actual ssh2 transport  | 
1005  | 
server.finish_subsystem()  | 
1006  | 
||
1007  | 
||
1008  | 
class SFTPAbsoluteServer(SFTPServerWithoutSSH):  | 
|
| 
1530.1.1
by Robert Collins
 Minimal infrastructure to test TransportTestProviderAdapter.  | 
1009  | 
"""A test server for sftp transports, using absolute urls."""  | 
1010  | 
||
| 
1530.1.3
by Robert Collins
 transport implementations now tested consistently.  | 
1011  | 
def get_url(self):  | 
1012  | 
"""See bzrlib.transport.Server.get_url."""  | 
|
| 
2321.3.7
by Alexander Belchenko
 fixes for passing test_sftp_transport on win32 (thankyou John)  | 
1013  | 
homedir = self._homedir  | 
1014  | 
if sys.platform != 'win32':  | 
|
1015  | 
            # Remove the initial '/' on all platforms but win32
 | 
|
1016  | 
homedir = homedir[1:]  | 
|
1017  | 
return self._get_sftp_url(urlutils.escape(homedir))  | 
|
| 
1530.1.3
by Robert Collins
 transport implementations now tested consistently.  | 
1018  | 
|
1019  | 
||
| 
1547.1.1
by Robey Pointer
 modify the sftp unit tests to perform sftp over a direct localhost socket instead of over an actual ssh2 transport  | 
1020  | 
class SFTPHomeDirServer(SFTPServerWithoutSSH):  | 
| 
1530.1.1
by Robert Collins
 Minimal infrastructure to test TransportTestProviderAdapter.  | 
1021  | 
"""A test server for sftp transports, using homedir relative urls."""  | 
| 
1530.1.3
by Robert Collins
 transport implementations now tested consistently.  | 
1022  | 
|
1023  | 
def get_url(self):  | 
|
1024  | 
"""See bzrlib.transport.Server.get_url."""  | 
|
| 
1534.1.8
by Robert Collins
 Update SFTP Urls as per mailing list thread.  | 
1025  | 
return self._get_sftp_url("~/")  | 
| 
1530.1.8
by Robert Collins
 More NEWS, move sibling sftp tests into new framework, nuke legacy local transport tests.  | 
1026  | 
|
1027  | 
||
1028  | 
class SFTPSiblingAbsoluteServer(SFTPAbsoluteServer):  | 
|
| 
2018.5.114
by Robert Collins
 Commit current test pass improvements.  | 
1029  | 
"""A test server for sftp transports where only absolute paths will work.  | 
1030  | 
||
1031  | 
    It does this by serving from a deeply-nested directory that doesn't exist.
 | 
|
1032  | 
    """
 | 
|
1033  | 
||
1034  | 
def setUp(self, backing_server=None):  | 
|
| 
1530.1.8
by Robert Collins
 More NEWS, move sibling sftp tests into new framework, nuke legacy local transport tests.  | 
1035  | 
self._server_homedir = '/dev/noone/runs/tests/here'  | 
| 
2018.5.114
by Robert Collins
 Commit current test pass improvements.  | 
1036  | 
super(SFTPSiblingAbsoluteServer, self).setUp(backing_server)  | 
| 
1530.1.11
by Robert Collins
 Push the transport permutations list into each transport module allowing for automatic testing of new modules that are registered as transports.  | 
1037  | 
|
1038  | 
||
1039  | 
def get_test_permutations():  | 
|
1040  | 
"""Return the permutations to be used in testing."""  | 
|
1041  | 
return [(SFTPTransport, SFTPAbsoluteServer),  | 
|
1042  | 
(SFTPTransport, SFTPHomeDirServer),  | 
|
1043  | 
(SFTPTransport, SFTPSiblingAbsoluteServer),  | 
|
1044  | 
            ]
 |