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>
|
2 |
# Copyright (C) 2005, 2006 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 |
|
1951.1.9
by Andrew Bennetts
Add docstrings and tweak method names in ssh.py |
37 |
import weakref |
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
38 |
|
|
2001.3.2
by John Arbash Meinel
Force all transports to raise ShortReadvError if they can |
39 |
from bzrlib import ( |
40 |
errors, |
|
41 |
urlutils, |
|
42 |
)
|
|
|
1996.2.1
by Andrew Bennetts
Fix NameError reported by Alexander Belchenko. |
43 |
from bzrlib.errors import (FileExists, |
|
1951.1.6
by Andrew Bennetts
Tidy up some unused imports. |
44 |
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 |
45 |
TransportError, |
|
1996.2.1
by Andrew Bennetts
Fix NameError reported by Alexander Belchenko. |
46 |
LockError, |
|
1662.1.12
by Martin Pool
Translate unknown sftp errors to PathError, no NoSuchFile |
47 |
PathError, |
48 |
ParamikoNotPresent, |
|
|
1530.1.3
by Robert Collins
transport implementations now tested consistently. |
49 |
)
|
|
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 |
50 |
from bzrlib.osutils import pathjoin, fancy_rename, getcwd |
|
1951.1.6
by Andrew Bennetts
Tidy up some unused imports. |
51 |
from bzrlib.trace import mutter, warning |
|
1636.1.2
by Robert Collins
More review fixen to the relpath at '/' fixes. |
52 |
from bzrlib.transport import ( |
53 |
register_urlparse_netloc_protocol, |
|
54 |
Server, |
|
|
1707.3.4
by John Arbash Meinel
Moved most of sftp.split_url into a Transport function. |
55 |
split_url, |
|
1951.1.4
by Andrew Bennetts
Start moving SSH connection code into bzrlib/transport/ssh.py |
56 |
ssh, |
|
1636.1.2
by Robert Collins
More review fixen to the relpath at '/' fixes. |
57 |
Transport, |
58 |
)
|
|
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
59 |
|
60 |
try: |
|
61 |
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. |
62 |
except ImportError, e: |
63 |
raise ParamikoNotPresent(e) |
|
|
1185.49.2
by John Arbash Meinel
Adding a open_exclusive function since paramiko supports it, but doesn't expose it |
64 |
else: |
65 |
from paramiko.sftp import (SFTP_FLAG_WRITE, SFTP_FLAG_CREATE, |
|
66 |
SFTP_FLAG_EXCL, SFTP_FLAG_TRUNC, |
|
67 |
CMD_HANDLE, CMD_OPEN) |
|
68 |
from paramiko.sftp_attr import SFTPAttributes |
|
69 |
from paramiko.sftp_file import SFTPFile |
|
|
1636.1.1
by Robert Collins
Fix calling relpath() and abspath() on transports at their root. |
70 |
|
|
1883.1.3
by Stefan (metze) Metzmacher
- fix typo |
71 |
|
|
1636.1.2
by Robert Collins
More review fixen to the relpath at '/' fixes. |
72 |
register_urlparse_netloc_protocol('sftp') |
|
1636.1.1
by Robert Collins
Fix calling relpath() and abspath() on transports at their root. |
73 |
|
|
1185.48.1
by James Henstridge
Use /usr/bin/ssh if we can. |
74 |
|
|
1951.1.9
by Andrew Bennetts
Add docstrings and tweak method names in ssh.py |
75 |
# This is a weakref dictionary, so that we can reuse connections
|
76 |
# that are still active. Long term, it might be nice to have some
|
|
77 |
# sort of expiration policy, such as disconnect if inactive for
|
|
78 |
# X seconds. But that requires a lot more fanciness.
|
|
79 |
_connected_hosts = weakref.WeakValueDictionary() |
|
80 |
||
81 |
||
|
1711.6.2
by John Arbash Meinel
Clean up paramiko agent support. |
82 |
_paramiko_version = getattr(paramiko, '__version_info__', (0, 0, 0)) |
83 |
# don't use prefetch unless paramiko version >= 1.5.5 (there were bugs earlier)
|
|
84 |
_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. |
85 |
|
|
1185.48.1
by James Henstridge
Use /usr/bin/ssh if we can. |
86 |
|
|
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. |
87 |
def clear_connection_cache(): |
88 |
"""Remove all hosts from the SFTP connection cache. |
|
89 |
||
90 |
Primarily useful for test cases wanting to force garbage collection.
|
|
91 |
"""
|
|
|
1951.1.9
by Andrew Bennetts
Add docstrings and tweak method names in ssh.py |
92 |
_connected_hosts.clear() |
|
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. |
93 |
|
|
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 |
94 |
|
|
1185.49.3
by John Arbash Meinel
Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path |
95 |
class SFTPLock(object): |
|
1910.7.17
by Andrew Bennetts
Various cosmetic changes. |
96 |
"""This fakes a lock in a remote location. |
97 |
|
|
98 |
A present lock is indicated just by the existence of a file. This
|
|
99 |
doesn't work well on all transports and they are only used in
|
|
100 |
deprecated storage formats.
|
|
101 |
"""
|
|
102 |
||
|
1185.49.3
by John Arbash Meinel
Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path |
103 |
__slots__ = ['path', 'lock_path', 'lock_file', 'transport'] |
|
1910.7.17
by Andrew Bennetts
Various cosmetic changes. |
104 |
|
|
1185.49.3
by John Arbash Meinel
Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path |
105 |
def __init__(self, path, transport): |
106 |
assert isinstance(transport, SFTPTransport) |
|
107 |
||
108 |
self.lock_file = None |
|
109 |
self.path = path |
|
110 |
self.lock_path = path + '.write-lock' |
|
111 |
self.transport = transport |
|
112 |
try: |
|
|
1530.1.7
by Robert Collins
merge integration. |
113 |
# RBC 20060103 FIXME should we be using private methods here ?
|
114 |
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. |
115 |
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 |
116 |
except FileExists: |
117 |
raise LockError('File %r already locked' % (self.path,)) |
|
118 |
||
119 |
def __del__(self): |
|
120 |
"""Should this warn, or actually try to cleanup?""" |
|
121 |
if self.lock_file: |
|
|
1547.1.3
by Robey Pointer
spell warning correctly :) and move recv_ready close to recv for readability |
122 |
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 |
123 |
self.unlock() |
124 |
||
125 |
def unlock(self): |
|
126 |
if not self.lock_file: |
|
127 |
return
|
|
128 |
self.lock_file.close() |
|
129 |
self.lock_file = None |
|
130 |
try: |
|
131 |
self.transport.delete(self.lock_path) |
|
132 |
except (NoSuchFile,): |
|
133 |
# What specific errors should we catch here?
|
|
134 |
pass
|
|
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
135 |
|
|
1551.6.39
by Aaron Bentley
Apply Robey Pointer's listener patch |
136 |
|
|
1910.16.2
by Andrew Bennetts
Reduce transport code duplication by creating a '_combine_paths' method to Transport. |
137 |
class SFTPUrlHandling(Transport): |
138 |
"""Mix-in that does common handling of SSH/SFTP URLs.""" |
|
139 |
||
140 |
def __init__(self, base): |
|
141 |
self._parse_url(base) |
|
142 |
base = self._unparse_url(self._path) |
|
143 |
if base[-1] != '/': |
|
144 |
base += '/' |
|
145 |
super(SFTPUrlHandling, self).__init__(base) |
|
146 |
||
147 |
def _parse_url(self, url): |
|
148 |
(self._scheme, |
|
149 |
self._username, self._password, |
|
150 |
self._host, self._port, self._path) = self._split_url(url) |
|
151 |
||
152 |
def _unparse_url(self, path): |
|
153 |
"""Return a URL for a path relative to this transport. |
|
154 |
"""
|
|
155 |
path = urllib.quote(path) |
|
156 |
# handle homedir paths
|
|
157 |
if not path.startswith('/'): |
|
158 |
path = "/~/" + path |
|
159 |
netloc = urllib.quote(self._host) |
|
160 |
if self._username is not None: |
|
161 |
netloc = '%s@%s' % (urllib.quote(self._username), netloc) |
|
162 |
if self._port is not None: |
|
163 |
netloc = '%s:%d' % (netloc, self._port) |
|
164 |
return urlparse.urlunparse((self._scheme, netloc, path, '', '', '')) |
|
165 |
||
166 |
def _split_url(self, url): |
|
167 |
(scheme, username, password, host, port, path) = split_url(url) |
|
168 |
## assert scheme == 'sftp'
|
|
169 |
||
170 |
# the initial slash should be removed from the path, and treated
|
|
171 |
# as a homedir relative path (the path begins with a double slash
|
|
172 |
# if it is absolute).
|
|
173 |
# see draft-ietf-secsh-scp-sftp-ssh-uri-03.txt
|
|
174 |
# RBC 20060118 we are not using this as its too user hostile. instead
|
|
175 |
# we are following lftp and using /~/foo to mean '~/foo'.
|
|
176 |
# handle homedir paths
|
|
177 |
if path.startswith('/~/'): |
|
178 |
path = path[3:] |
|
179 |
elif path == '/~': |
|
180 |
path = '' |
|
181 |
return (scheme, username, password, host, port, path) |
|
182 |
||
|
1910.19.1
by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used |
183 |
def abspath(self, relpath): |
|
1910.19.3
by Andrew Bennetts
Add SSH support. |
184 |
"""Return the full url to the given relative path. |
|
1910.19.1
by Andrew Bennetts
Support bzr:// urls to work with the new RPC-based transport which will be used |
185 |
|
186 |
@param relpath: the relative path or path components
|
|
187 |
@type relpath: str or list
|
|
188 |
"""
|
|
189 |
return self._unparse_url(self._remote_path(relpath)) |
|
190 |
||
|
1910.16.2
by Andrew Bennetts
Reduce transport code duplication by creating a '_combine_paths' method to Transport. |
191 |
def _remote_path(self, relpath): |
192 |
"""Return the path to be passed along the sftp protocol for relpath. |
|
193 |
|
|
194 |
:param relpath: is a urlencoded string.
|
|
195 |
"""
|
|
196 |
return self._combine_paths(self._path, relpath) |
|
197 |
||
198 |
||
199 |
class SFTPTransport(SFTPUrlHandling): |
|
|
1910.3.1
by Andrew Bennetts
PEP 8 nits. |
200 |
"""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 |
201 |
|
|
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. |
202 |
_do_prefetch = _default_do_prefetch |
|
1864.5.6
by John Arbash Meinel
Setting defaults based on benchmarking data. |
203 |
# TODO: jam 20060717 Conceivably these could be configurable, either
|
204 |
# by auto-tuning at run-time, or by a configuration (per host??)
|
|
205 |
# but the performance curve is pretty flat, so just going with
|
|
206 |
# reasonable defaults.
|
|
|
1864.5.18
by John Arbash Meinel
Remove benchmarking stipple. |
207 |
_max_readv_combine = 200 |
|
1864.5.6
by John Arbash Meinel
Setting defaults based on benchmarking data. |
208 |
# Having to round trip to the server means waiting for a response,
|
209 |
# so it is better to download extra bytes.
|
|
210 |
# 8KiB had good performance for both local and remote network operations
|
|
|
1864.5.18
by John Arbash Meinel
Remove benchmarking stipple. |
211 |
_bytes_to_read_before_seek = 8192 |
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
212 |
|
|
1864.5.20
by John Arbash Meinel
Some small cleanups. |
213 |
# The sftp spec says that implementations SHOULD allow reads
|
214 |
# to be at least 32K. paramiko.readv() does an async request
|
|
215 |
# for the chunks. So we need to keep it within a single request
|
|
216 |
# size for paramiko <= 1.6.1. paramiko 1.6.2 will probably chop
|
|
217 |
# up the request itself, rather than us having to worry about it
|
|
218 |
_max_request_size = 32768 |
|
|
1864.5.17
by John Arbash Meinel
A little cleanup, and restrict to 32K to conform better to sftp spec |
219 |
|
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
220 |
def __init__(self, base, clone_from=None): |
221 |
super(SFTPTransport, self).__init__(base) |
|
222 |
if clone_from is None: |
|
223 |
self._sftp_connect() |
|
224 |
else: |
|
225 |
# use the same ssh connection, etc
|
|
226 |
self._sftp = clone_from._sftp |
|
227 |
# super saves 'self.base'
|
|
228 |
||
229 |
def should_cache(self): |
|
230 |
""" |
|
231 |
Return True if the data pulled across should be cached locally.
|
|
232 |
"""
|
|
233 |
return True |
|
234 |
||
235 |
def clone(self, offset=None): |
|
236 |
""" |
|
237 |
Return a new SFTPTransport with root at self.base + offset.
|
|
238 |
We share the same SFTP session between such transports, because it's
|
|
239 |
fairly expensive to set them up.
|
|
240 |
"""
|
|
241 |
if offset is None: |
|
242 |
return SFTPTransport(self.base, self) |
|
243 |
else: |
|
244 |
return SFTPTransport(self.abspath(offset), self) |
|
245 |
||
|
1524.1.1
by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir |
246 |
def _remote_path(self, relpath): |
247 |
"""Return the path to be passed along the sftp protocol for relpath. |
|
248 |
|
|
249 |
relpath is a urlencoded string.
|
|
|
1910.15.4
by Andrew Bennetts
Make SFTPTransport._remote_path do the right thing with absolute paths (and thus make it pass tests.) |
250 |
|
251 |
:return: a path prefixed with / for regular abspath-based urls, or a
|
|
252 |
path that does not begin with / for urls which begin with /~/.
|
|
|
1524.1.1
by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir |
253 |
"""
|
|
1986.1.10
by Robert Collins
Merge from bzr.dev, fixing found bugs handling 'has('/')' in MemoryTransport and SFTP transports. |
254 |
# how does this work?
|
255 |
# it processes relpath with respect to
|
|
256 |
# our state:
|
|
257 |
# firstly we create a path to evaluate:
|
|
258 |
# if relpath is an abspath or homedir path, its the entire thing
|
|
259 |
# otherwise we join our base with relpath
|
|
260 |
# then we eliminate all empty segments (double //'s) outside the first
|
|
261 |
# two elements of the list. This avoids problems with trailing
|
|
262 |
# slashes, or other abnormalities.
|
|
263 |
# finally we evaluate the entire path in a single pass
|
|
264 |
# '.'s are stripped,
|
|
265 |
# '..' result in popping the left most already
|
|
266 |
# processed path (which can never be empty because of the check for
|
|
267 |
# abspath and homedir meaning that its not, or that we've used our
|
|
268 |
# path. If the pop would pop the root, we ignore it.
|
|
269 |
||
270 |
# Specific case examinations:
|
|
271 |
# remove the special casefor ~: if the current root is ~/ popping of it
|
|
272 |
# = / thus our seed for a ~ based path is ['', '~']
|
|
273 |
# and if we end up with [''] then we had basically ('', '..') (which is
|
|
274 |
# '/..' so we append '' if the length is one, and assert that the first
|
|
275 |
# element is still ''. Lastly, if we end with ['', '~'] as a prefix for
|
|
276 |
# the output, we've got a homedir path, so we strip that prefix before
|
|
277 |
# '/' joining the resulting list.
|
|
278 |
#
|
|
279 |
# case one: '/' -> ['', ''] cannot shrink
|
|
280 |
# case two: '/' + '../foo' -> ['', 'foo'] (take '', '', '..', 'foo')
|
|
281 |
# and pop the second '' for the '..', append 'foo'
|
|
282 |
# case three: '/~/' -> ['', '~', '']
|
|
283 |
# case four: '/~/' + '../foo' -> ['', '~', '', '..', 'foo'],
|
|
284 |
# and we want to get '/foo' - the empty path in the middle
|
|
285 |
# needs to be stripped, then normal path manipulation will
|
|
286 |
# work.
|
|
287 |
# case five: '/..' ['', '..'], we want ['', '']
|
|
288 |
# stripping '' outside the first two is ok
|
|
289 |
# ignore .. if its too high up
|
|
290 |
#
|
|
291 |
# lastly this code is possibly reusable by FTP, but not reusable by
|
|
292 |
# local paths: ~ is resolvable correctly, nor by HTTP or the smart
|
|
293 |
# server: ~ is resolved remotely.
|
|
294 |
#
|
|
295 |
# however, a version of this that acts on self.base is possible to be
|
|
296 |
# written which manipulates the URL in canonical form, and would be
|
|
297 |
# reusable for all transports, if a flag for allowing ~/ at all was
|
|
298 |
# provided.
|
|
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
299 |
assert isinstance(relpath, basestring) |
|
1986.1.10
by Robert Collins
Merge from bzr.dev, fixing found bugs handling 'has('/')' in MemoryTransport and SFTP transports. |
300 |
relpath = urlutils.unescape(relpath) |
301 |
||
302 |
# case 1)
|
|
|
1910.15.2
by Andrew Bennetts
Fix SFTPTransport to pass the new abspath tests. |
303 |
if relpath.startswith('/'): |
|
1986.1.10
by Robert Collins
Merge from bzr.dev, fixing found bugs handling 'has('/')' in MemoryTransport and SFTP transports. |
304 |
# abspath - normal split is fine.
|
305 |
current_path = relpath.split('/') |
|
306 |
elif relpath.startswith('~/'): |
|
307 |
# root is homedir based: normal split and prefix '' to remote the
|
|
308 |
# special case
|
|
309 |
current_path = [''].extend(relpath.split('/')) |
|
310 |
else: |
|
311 |
# root is from the current directory:
|
|
312 |
if self._path.startswith('/'): |
|
313 |
# abspath, take the regular split
|
|
314 |
current_path = [] |
|
315 |
else: |
|
316 |
# homedir based, add the '', '~' not present in self._path
|
|
317 |
current_path = ['', '~'] |
|
318 |
# add our current dir
|
|
319 |
current_path.extend(self._path.split('/')) |
|
320 |
# add the users relpath
|
|
321 |
current_path.extend(relpath.split('/')) |
|
322 |
# strip '' segments that are not in the first one - the leading /.
|
|
323 |
to_process = current_path[:1] |
|
324 |
for segment in current_path[1:]: |
|
325 |
if segment != '': |
|
326 |
to_process.append(segment) |
|
327 |
||
328 |
# process '.' and '..' segments into output_path.
|
|
329 |
output_path = [] |
|
330 |
for segment in to_process: |
|
331 |
if segment == '..': |
|
332 |
# directory pop. Remove a directory
|
|
333 |
# as long as we are not at the root
|
|
334 |
if len(output_path) > 1: |
|
335 |
output_path.pop() |
|
336 |
# else: pass
|
|
337 |
# cannot pop beyond the root, so do nothing
|
|
338 |
elif segment == '.': |
|
339 |
continue # strip the '.' from the output. |
|
340 |
else: |
|
341 |
# this will append '' to output_path for the root elements,
|
|
342 |
# which is appropriate: its why we strip '' in the first pass.
|
|
343 |
output_path.append(segment) |
|
344 |
||
345 |
# check output special cases:
|
|
346 |
if output_path == ['']: |
|
347 |
# [''] -> ['', '']
|
|
348 |
output_path = ['', ''] |
|
349 |
elif output_path[:2] == ['', '~']: |
|
350 |
# ['', '~', ...] -> ...
|
|
351 |
output_path = output_path[2:] |
|
352 |
path = '/'.join(output_path) |
|
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
353 |
return path |
354 |
||
355 |
def relpath(self, abspath): |
|
|
1910.16.2
by Andrew Bennetts
Reduce transport code duplication by creating a '_combine_paths' method to Transport. |
356 |
scheme, username, password, host, port, path = self._split_url(abspath) |
|
1185.49.23
by John Arbash Meinel
bugreport from Matthieu Moy: relpath was failing, but throwing an unhelpful exception. |
357 |
error = [] |
358 |
if (username != self._username): |
|
359 |
error.append('username mismatch') |
|
360 |
if (host != self._host): |
|
361 |
error.append('host mismatch') |
|
362 |
if (port != self._port): |
|
363 |
error.append('port mismatch') |
|
364 |
if (not path.startswith(self._path)): |
|
365 |
error.append('path mismatch') |
|
366 |
if error: |
|
|
1185.31.44
by John Arbash Meinel
Cleaned up Exceptions for all transports. |
367 |
extra = ': ' + ', '.join(error) |
368 |
raise PathNotChild(abspath, self.base, extra=extra) |
|
|
1185.48.8
by James Henstridge
More URL handling fixes |
369 |
pl = len(self._path) |
|
1530.1.3
by Robert Collins
transport implementations now tested consistently. |
370 |
return path[pl:].strip('/') |
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
371 |
|
372 |
def has(self, relpath): |
|
373 |
""" |
|
374 |
Does the target location exist?
|
|
375 |
"""
|
|
376 |
try: |
|
|
1524.1.1
by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir |
377 |
self._sftp.stat(self._remote_path(relpath)) |
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
378 |
return True |
379 |
except IOError: |
|
380 |
return False |
|
381 |
||
|
1540.3.2
by Martin Pool
Remove obsolete (and no-op) `decode` parameter to `Transport.get`. |
382 |
def get(self, relpath): |
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
383 |
""" |
384 |
Get the file at the given relative path.
|
|
385 |
||
386 |
:param relpath: The relative path to the file
|
|
387 |
"""
|
|
388 |
try: |
|
|
1524.1.1
by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir |
389 |
path = self._remote_path(relpath) |
|
1185.31.51
by John Arbash Meinel
Setting binary flags for sftp. |
390 |
f = self._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. |
391 |
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 |
392 |
f.prefetch() |
393 |
return f |
|
|
1185.50.13
by John Arbash Meinel
Expanded the Transport test suite. Including delete, copy, move, etc. Updated SftpTransport to conform. |
394 |
except (IOError, paramiko.SSHException), e: |
395 |
self._translate_io_exception(e, path, ': error retrieving') |
|
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
396 |
|
|
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. |
397 |
def readv(self, relpath, offsets): |
398 |
"""See Transport.readv()""" |
|
399 |
# We overload the default readv() because we want to use a file
|
|
400 |
# that does not have prefetch enabled.
|
|
|
1864.5.15
by John Arbash Meinel
Cleanup and document the new sftp readv implementation |
401 |
# 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. |
402 |
if not offsets: |
403 |
return
|
|
404 |
||
405 |
try: |
|
406 |
path = self._remote_path(relpath) |
|
407 |
fp = self._sftp.file(path, mode='rb') |
|
|
1864.5.15
by John Arbash Meinel
Cleanup and document the new sftp readv implementation |
408 |
readv = getattr(fp, 'readv', None) |
|
1864.5.18
by John Arbash Meinel
Remove benchmarking stipple. |
409 |
if readv: |
|
2001.3.2
by John Arbash Meinel
Force all transports to raise ShortReadvError if they can |
410 |
return self._sftp_readv(fp, offsets, relpath) |
|
1864.5.16
by John Arbash Meinel
instrument to enable/disable readv support for testing |
411 |
mutter('seek and read %s offsets', len(offsets)) |
|
2001.3.2
by John Arbash Meinel
Force all transports to raise ShortReadvError if they can |
412 |
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. |
413 |
except (IOError, paramiko.SSHException), e: |
414 |
self._translate_io_exception(e, path, ': error retrieving') |
|
415 |
||
|
2001.3.2
by John Arbash Meinel
Force all transports to raise ShortReadvError if they can |
416 |
def _sftp_readv(self, fp, offsets, relpath='<unknown>'): |
|
1864.5.15
by John Arbash Meinel
Cleanup and document the new sftp readv implementation |
417 |
"""Use the readv() member of fp to do async readv. |
|
1864.5.13
by John Arbash Meinel
Try using paramiko.readv() |
418 |
|
419 |
And then read them using paramiko.readv(). paramiko.readv()
|
|
420 |
does not support ranges > 64K, so it caps the request size, and
|
|
421 |
just reads until it gets all the stuff it wants
|
|
422 |
"""
|
|
|
1864.5.15
by John Arbash Meinel
Cleanup and document the new sftp readv implementation |
423 |
offsets = list(offsets) |
|
1864.5.13
by John Arbash Meinel
Try using paramiko.readv() |
424 |
sorted_offsets = sorted(offsets) |
425 |
||
|
1864.5.15
by John Arbash Meinel
Cleanup and document the new sftp readv implementation |
426 |
# The algorithm works as follows:
|
427 |
# 1) Coalesce nearby reads into a single chunk
|
|
428 |
# This generates a list of combined regions, the total size
|
|
429 |
# and the size of the sub regions. This coalescing step is limited
|
|
430 |
# in the number of nearby chunks to combine, and is allowed to
|
|
431 |
# skip small breaks in the requests. Limiting it makes sure that
|
|
432 |
# we can start yielding some data earlier, and skipping means we
|
|
433 |
# make fewer requests. (Beneficial even when using async)
|
|
434 |
# 2) Break up this combined regions into chunks that are smaller
|
|
435 |
# than 64KiB. Technically the limit is 65536, but we are a
|
|
436 |
# little bit conservative. This is because sftp has a maximum
|
|
437 |
# return chunk size of 64KiB (max size of an unsigned short)
|
|
438 |
# 3) Issue a readv() to paramiko to create an async request for
|
|
439 |
# all of this data
|
|
440 |
# 4) Read in the data as it comes back, until we've read one
|
|
441 |
# continuous section as determined in step 1
|
|
442 |
# 5) Break up the full sections into hunks for the original requested
|
|
443 |
# offsets. And put them in a cache
|
|
444 |
# 6) Check if the next request is in the cache, and if it is, remove
|
|
445 |
# it from the cache, and yield its data. Continue until no more
|
|
446 |
# entries are in the cache.
|
|
447 |
# 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 |
448 |
#
|
449 |
# TODO: jam 20060725 This could be optimized one step further, by
|
|
450 |
# attempting to yield whatever data we have read, even before
|
|
|
1864.5.20
by John Arbash Meinel
Some small cleanups. |
451 |
# the first coallesced section has been fully processed.
|
|
1864.5.15
by John Arbash Meinel
Cleanup and document the new sftp readv implementation |
452 |
|
|
1864.5.17
by John Arbash Meinel
A little cleanup, and restrict to 32K to conform better to sftp spec |
453 |
# When coalescing for use with readv(), we don't really need to
|
454 |
# use any fudge factor, because the requests are made asynchronously
|
|
|
1864.5.13
by John Arbash Meinel
Try using paramiko.readv() |
455 |
coalesced = list(self._coalesce_offsets(sorted_offsets, |
456 |
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 |
457 |
fudge_factor=0, |
|
1864.5.13
by John Arbash Meinel
Try using paramiko.readv() |
458 |
))
|
459 |
requests = [] |
|
460 |
for c_offset in coalesced: |
|
461 |
start = c_offset.start |
|
|
1864.5.17
by John Arbash Meinel
A little cleanup, and restrict to 32K to conform better to sftp spec |
462 |
size = c_offset.length |
|
1864.5.13
by John Arbash Meinel
Try using paramiko.readv() |
463 |
|
464 |
# 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 |
465 |
while size > 0: |
|
1864.5.20
by John Arbash Meinel
Some small cleanups. |
466 |
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 |
467 |
requests.append((start, next_size)) |
468 |
size -= next_size |
|
469 |
start += next_size |
|
|
1864.5.13
by John Arbash Meinel
Try using paramiko.readv() |
470 |
|
|
1864.5.16
by John Arbash Meinel
instrument to enable/disable readv support for testing |
471 |
mutter('SFTP.readv() %s offsets => %s coalesced => %s requests', |
472 |
len(offsets), len(coalesced), len(requests)) |
|
473 |
||
|
1864.5.15
by John Arbash Meinel
Cleanup and document the new sftp readv implementation |
474 |
# Queue the current read until we have read the full coalesced section
|
|
1864.5.13
by John Arbash Meinel
Try using paramiko.readv() |
475 |
cur_data = [] |
476 |
cur_data_len = 0 |
|
477 |
cur_coalesced_stack = iter(coalesced) |
|
478 |
cur_coalesced = cur_coalesced_stack.next() |
|
479 |
||
|
1864.5.15
by John Arbash Meinel
Cleanup and document the new sftp readv implementation |
480 |
# Cache the results, but only until they have been fulfilled
|
481 |
data_map = {} |
|
482 |
# turn the list of offsets into a stack
|
|
483 |
offset_stack = iter(offsets) |
|
484 |
cur_offset_and_size = offset_stack.next() |
|
485 |
||
|
1864.5.13
by John Arbash Meinel
Try using paramiko.readv() |
486 |
for data in fp.readv(requests): |
487 |
cur_data += data |
|
488 |
cur_data_len += len(data) |
|
489 |
||
490 |
if cur_data_len < cur_coalesced.length: |
|
491 |
continue
|
|
492 |
assert cur_data_len == cur_coalesced.length, \ |
|
493 |
"Somehow we read too much: %s != %s" % (cur_data_len, |
|
494 |
cur_coalesced.length) |
|
|
1864.5.20
by John Arbash Meinel
Some small cleanups. |
495 |
all_data = ''.join(cur_data) |
|
1864.5.13
by John Arbash Meinel
Try using paramiko.readv() |
496 |
cur_data = [] |
497 |
cur_data_len = 0 |
|
498 |
||
499 |
for suboffset, subsize in cur_coalesced.ranges: |
|
500 |
key = (cur_coalesced.start+suboffset, subsize) |
|
|
1864.5.20
by John Arbash Meinel
Some small cleanups. |
501 |
data_map[key] = all_data[suboffset:suboffset+subsize] |
|
1864.5.13
by John Arbash Meinel
Try using paramiko.readv() |
502 |
|
503 |
# Now that we've read some data, see if we can yield anything back
|
|
504 |
while cur_offset_and_size in data_map: |
|
505 |
this_data = data_map.pop(cur_offset_and_size) |
|
506 |
yield cur_offset_and_size[0], this_data |
|
507 |
cur_offset_and_size = offset_stack.next() |
|
508 |
||
|
2001.3.2
by John Arbash Meinel
Force all transports to raise ShortReadvError if they can |
509 |
# We read a coalesced entry, so mark it as done
|
510 |
cur_coalesced = None |
|
|
1864.5.13
by John Arbash Meinel
Try using paramiko.readv() |
511 |
# Now that we've read all of the data for this coalesced section
|
512 |
# on to the next
|
|
513 |
cur_coalesced = cur_coalesced_stack.next() |
|
|
1864.5.12
by John Arbash Meinel
Using a simple sftp_file.readv() request if possible. |
514 |
|
|
2001.3.2
by John Arbash Meinel
Force all transports to raise ShortReadvError if they can |
515 |
if cur_coalesced is not None: |
516 |
raise errors.ShortReadvError(relpath, cur_coalesced.start, |
|
|
2001.3.3
by John Arbash Meinel
review feedback: add the actual count written to ShortReadvError |
517 |
cur_coalesced.length, len(data)) |
|
2001.3.2
by John Arbash Meinel
Force all transports to raise ShortReadvError if they can |
518 |
|
|
1955.3.6
by John Arbash Meinel
Lots of deprecation warnings, but no errors |
519 |
def put_file(self, relpath, f, mode=None): |
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
520 |
""" |
|
1955.3.6
by John Arbash Meinel
Lots of deprecation warnings, but no errors |
521 |
Copy the file-like object into the location.
|
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
522 |
|
523 |
:param relpath: Location to put the contents, relative to base.
|
|
|
1955.3.6
by John Arbash Meinel
Lots of deprecation warnings, but no errors |
524 |
: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. |
525 |
:param mode: The final mode for the file
|
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
526 |
"""
|
|
1524.1.1
by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir |
527 |
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. |
528 |
self._put(final_path, f, mode=mode) |
529 |
||
530 |
def _put(self, abspath, f, mode=None): |
|
531 |
"""Helper function so both put() and copy_abspaths can reuse the code""" |
|
532 |
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 |
533 |
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. |
534 |
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. |
535 |
closed = False |
|
1185.41.6
by Robey Pointer
modified version of john's patch to add atomic put and locking to the sftp transport |
536 |
try: |
|
1185.49.1
by John Arbash Meinel
Updating SftpTransport.put() so that it is atomic |
537 |
try: |
|
1185.58.2
by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work. |
538 |
fout.set_pipelined(True) |
|
1185.49.1
by John Arbash Meinel
Updating SftpTransport.put() so that it is atomic |
539 |
self._pump(f, fout) |
|
1185.31.47
by John Arbash Meinel
Added a fancy footwork rename to osutils, made SftpTransport use it. |
540 |
except (IOError, paramiko.SSHException), e: |
541 |
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 |
542 |
# XXX: This doesn't truly help like we would like it to.
|
543 |
# The problem is that openssh strips sticky bits. So while we
|
|
544 |
# can properly set group write permission, we lose the group
|
|
545 |
# sticky bit. So it is probably best to stop chmodding, and
|
|
546 |
# just tell users that they need to set the umask correctly.
|
|
547 |
# The attr.st_mode = mode, in _sftp_open_exclusive
|
|
548 |
# will handle when the user wants the final mode to be more
|
|
549 |
# restrictive. And then we avoid a round trip. Unless
|
|
550 |
# paramiko decides to expose an async chmod()
|
|
551 |
||
552 |
# This is designed to chmod() right before we close.
|
|
553 |
# Because we set_pipelined() earlier, theoretically we might
|
|
554 |
# 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. |
555 |
if mode is not None: |
556 |
self._sftp.chmod(tmp_abspath, mode) |
|
|
1185.31.47
by John Arbash Meinel
Added a fancy footwork rename to osutils, made SftpTransport use it. |
557 |
fout.close() |
558 |
closed = True |
|
|
1553.5.13
by Martin Pool
New Transport.rename that mustn't overwrite |
559 |
self._rename_and_overwrite(tmp_abspath, abspath) |
|
1185.49.1
by John Arbash Meinel
Updating SftpTransport.put() so that it is atomic |
560 |
except Exception, e: |
561 |
# If we fail, try to clean up the temporary file
|
|
562 |
# before we throw the exception
|
|
563 |
# 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. |
564 |
# Write out the traceback, because otherwise
|
565 |
# 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. |
566 |
import traceback |
567 |
mutter(traceback.format_exc()) |
|
|
1185.49.1
by John Arbash Meinel
Updating SftpTransport.put() so that it is atomic |
568 |
try: |
|
1185.31.47
by John Arbash Meinel
Added a fancy footwork rename to osutils, made SftpTransport use it. |
569 |
if not closed: |
570 |
fout.close() |
|
|
1185.49.3
by John Arbash Meinel
Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path |
571 |
self._sftp.remove(tmp_abspath) |
|
1185.49.1
by John Arbash Meinel
Updating SftpTransport.put() so that it is atomic |
572 |
except: |
|
1532
by Robert Collins
Merge in John Meinels integration branch. |
573 |
# raise the saved except
|
574 |
raise e |
|
575 |
# raise the original with its traceback if we can.
|
|
576 |
raise
|
|
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
577 |
|
|
1955.3.27
by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions |
578 |
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 |
579 |
create_parent_dir=False, |
580 |
dir_mode=None): |
|
|
1946.1.6
by John Arbash Meinel
Basic implementation of non_atomic_put for sftp |
581 |
abspath = self._remote_path(relpath) |
|
1946.1.8
by John Arbash Meinel
Update non_atomic_put to have a create_parent_dir flag |
582 |
|
583 |
# TODO: jam 20060816 paramiko doesn't publicly expose a way to
|
|
584 |
# set the file mode at create time. If it does, use it.
|
|
585 |
# But for now, we just chmod later anyway.
|
|
|
1946.1.6
by John Arbash Meinel
Basic implementation of non_atomic_put for sftp |
586 |
|
|
1946.1.8
by John Arbash Meinel
Update non_atomic_put to have a create_parent_dir flag |
587 |
def _open_and_write_file(): |
588 |
"""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. |
589 |
fout = None |
|
1946.1.8
by John Arbash Meinel
Update non_atomic_put to have a create_parent_dir flag |
590 |
try: |
|
1946.1.10
by John Arbash Meinel
make sure to always close the file object. |
591 |
try: |
592 |
fout = self._sftp.file(abspath, mode='wb') |
|
593 |
fout.set_pipelined(True) |
|
|
1955.3.21
by John Arbash Meinel
Update the LocalTransport and SftpTransport to implement non_atomic_* |
594 |
writer(fout) |
|
1946.1.10
by John Arbash Meinel
make sure to always close the file object. |
595 |
except (paramiko.SSHException, IOError), e: |
|
1955.3.21
by John Arbash Meinel
Update the LocalTransport and SftpTransport to implement non_atomic_* |
596 |
self._translate_io_exception(e, abspath, |
597 |
': unable to open') |
|
|
1946.1.8
by John Arbash Meinel
Update non_atomic_put to have a create_parent_dir flag |
598 |
|
|
1946.1.10
by John Arbash Meinel
make sure to always close the file object. |
599 |
# This is designed to chmod() right before we close.
|
600 |
# Because we set_pipelined() earlier, theoretically we might
|
|
601 |
# avoid the round trip for fout.close()
|
|
602 |
if mode is not None: |
|
603 |
self._sftp.chmod(abspath, mode) |
|
604 |
finally: |
|
605 |
if fout is not None: |
|
606 |
fout.close() |
|
|
1946.1.8
by John Arbash Meinel
Update non_atomic_put to have a create_parent_dir flag |
607 |
|
608 |
if not create_parent_dir: |
|
609 |
_open_and_write_file() |
|
610 |
return
|
|
611 |
||
612 |
# Try error handling to create the parent directory if we need to
|
|
613 |
try: |
|
614 |
_open_and_write_file() |
|
615 |
except NoSuchFile: |
|
616 |
# Try to create the parent directory, and then go back to
|
|
617 |
# writing the file
|
|
618 |
parent_dir = os.path.dirname(abspath) |
|
|
1946.2.15
by John Arbash Meinel
Fix the sftp mkdir mode code |
619 |
self._mkdir(parent_dir, dir_mode) |
|
1946.1.8
by John Arbash Meinel
Update non_atomic_put to have a create_parent_dir flag |
620 |
_open_and_write_file() |
|
1946.1.6
by John Arbash Meinel
Basic implementation of non_atomic_put for sftp |
621 |
|
|
1955.3.27
by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions |
622 |
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 |
623 |
create_parent_dir=False, |
624 |
dir_mode=None): |
|
|
1955.3.21
by John Arbash Meinel
Update the LocalTransport and SftpTransport to implement non_atomic_* |
625 |
"""Copy the file-like object into the target location. |
626 |
||
627 |
This function is not strictly safe to use. It is only meant to
|
|
628 |
be used when you already know that the target does not exist.
|
|
629 |
It is not safe, because it will open and truncate the remote
|
|
630 |
file. So there may be a time when the file has invalid contents.
|
|
631 |
||
632 |
:param relpath: The remote location to put the contents.
|
|
633 |
:param f: File-like object.
|
|
634 |
:param mode: Possible access permissions for new file.
|
|
635 |
None means do not set remote permissions.
|
|
636 |
:param create_parent_dir: If we cannot create the target file because
|
|
637 |
the parent directory does not exist, go ahead and
|
|
638 |
create it, and then try again.
|
|
639 |
"""
|
|
640 |
def writer(fout): |
|
641 |
self._pump(f, fout) |
|
|
1955.3.27
by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions |
642 |
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 |
643 |
create_parent_dir=create_parent_dir, |
644 |
dir_mode=dir_mode) |
|
|
1955.3.21
by John Arbash Meinel
Update the LocalTransport and SftpTransport to implement non_atomic_* |
645 |
|
|
1955.3.27
by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions |
646 |
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 |
647 |
create_parent_dir=False, |
648 |
dir_mode=None): |
|
|
1955.3.21
by John Arbash Meinel
Update the LocalTransport and SftpTransport to implement non_atomic_* |
649 |
def writer(fout): |
650 |
fout.write(bytes) |
|
|
1955.3.27
by John Arbash Meinel
rename non_atomic_put_* to put_*non_atomic, and re-order the functions |
651 |
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 |
652 |
create_parent_dir=create_parent_dir, |
653 |
dir_mode=dir_mode) |
|
|
1955.3.21
by John Arbash Meinel
Update the LocalTransport and SftpTransport to implement non_atomic_* |
654 |
|
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
655 |
def iter_files_recursive(self): |
656 |
"""Walk the relative paths of all files in this transport.""" |
|
657 |
queue = list(self.list_dir('.')) |
|
658 |
while queue: |
|
|
1959.2.1
by John Arbash Meinel
David Allouche: Make transports return escaped paths |
659 |
relpath = queue.pop(0) |
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
660 |
st = self.stat(relpath) |
661 |
if stat.S_ISDIR(st.st_mode): |
|
662 |
for i, basename in enumerate(self.list_dir(relpath)): |
|
663 |
queue.insert(i, relpath+'/'+basename) |
|
664 |
else: |
|
665 |
yield relpath |
|
666 |
||
|
1988.1.1
by John Arbash Meinel
Restore mode bit tests for sftp, and track down bugs |
667 |
def _mkdir(self, abspath, mode=None): |
668 |
if mode is None: |
|
669 |
local_mode = 0777 |
|
670 |
else: |
|
671 |
local_mode = mode |
|
672 |
try: |
|
673 |
self._sftp.mkdir(abspath, local_mode) |
|
674 |
if mode is not None: |
|
675 |
self._sftp.chmod(abspath, mode=mode) |
|
676 |
except (paramiko.SSHException, IOError), e: |
|
677 |
self._translate_io_exception(e, abspath, ': unable to mkdir', |
|
678 |
failure_exc=FileExists) |
|
679 |
||
|
1185.58.2
by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work. |
680 |
def mkdir(self, relpath, mode=None): |
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
681 |
"""Create a directory at the given path.""" |
|
1988.1.1
by John Arbash Meinel
Restore mode bit tests for sftp, and track down bugs |
682 |
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. |
683 |
|
|
1662.1.12
by Martin Pool
Translate unknown sftp errors to PathError, no NoSuchFile |
684 |
def _translate_io_exception(self, e, path, more_info='', |
685 |
failure_exc=PathError): |
|
|
1185.50.13
by John Arbash Meinel
Expanded the Transport test suite. Including delete, copy, move, etc. Updated SftpTransport to conform. |
686 |
"""Translate a paramiko or IOError into a friendlier exception. |
687 |
||
688 |
:param e: The original exception
|
|
689 |
:param path: The path in question when the error is raised
|
|
690 |
:param more_info: Extra information that can be included,
|
|
691 |
such as what was going on
|
|
692 |
:param failure_exc: Paramiko has the super fun ability to raise completely
|
|
693 |
opaque errors that just set "e.args = ('Failure',)" with
|
|
694 |
no more information.
|
|
|
1662.1.12
by Martin Pool
Translate unknown sftp errors to PathError, no NoSuchFile |
695 |
If this parameter is set, it defines the exception
|
696 |
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. |
697 |
"""
|
|
1489
by Robert Collins
Make the paramiko tests pass. Nice huh. |
698 |
# 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. |
699 |
self._translate_error(e, path, raise_generic=False) |
|
1963.2.6
by Robey Pointer
pychecker is on crack; go back to using 'is None'. |
700 |
if getattr(e, 'args', None) is not None: |
|
1185.31.44
by John Arbash Meinel
Cleaned up Exceptions for all transports. |
701 |
if (e.args == ('No such file or directory',) or |
702 |
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. |
703 |
raise NoSuchFile(path, str(e) + more_info) |
|
1185.31.44
by John Arbash Meinel
Cleaned up Exceptions for all transports. |
704 |
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. |
705 |
raise FileExists(path, str(e) + more_info) |
|
1185.31.44
by John Arbash Meinel
Cleaned up Exceptions for all transports. |
706 |
# strange but true, for the paramiko server.
|
707 |
if (e.args == ('Failure',)): |
|
|
1185.50.13
by John Arbash Meinel
Expanded the Transport test suite. Including delete, copy, move, etc. Updated SftpTransport to conform. |
708 |
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. |
709 |
mutter('Raising exception with args %s', e.args) |
|
1963.2.6
by Robey Pointer
pychecker is on crack; go back to using 'is None'. |
710 |
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. |
711 |
mutter('Raising exception with errno %s', e.errno) |
|
1185.31.44
by John Arbash Meinel
Cleaned up Exceptions for all transports. |
712 |
raise e |
|
1489
by Robert Collins
Make the paramiko tests pass. Nice huh. |
713 |
|
|
1955.3.15
by John Arbash Meinel
Deprecate 'Transport.append' in favor of Transport.append_file or Transport.append_bytes |
714 |
def append_file(self, relpath, f, mode=None): |
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
715 |
""" |
716 |
Append the text in the file-like object into the final
|
|
717 |
location.
|
|
718 |
"""
|
|
719 |
try: |
|
|
1524.1.1
by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir |
720 |
path = self._remote_path(relpath) |
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
721 |
fout = self._sftp.file(path, 'ab') |
|
1666.1.6
by Robert Collins
Make knit the default format. |
722 |
if mode is not None: |
723 |
self._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. |
724 |
result = fout.tell() |
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
725 |
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. |
726 |
return result |
|
1185.50.13
by John Arbash Meinel
Expanded the Transport test suite. Including delete, copy, move, etc. Updated SftpTransport to conform. |
727 |
except (IOError, paramiko.SSHException), e: |
728 |
self._translate_io_exception(e, relpath, ': unable to append') |
|
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
729 |
|
|
1553.5.13
by Martin Pool
New Transport.rename that mustn't overwrite |
730 |
def rename(self, rel_from, rel_to): |
731 |
"""Rename without special overwriting""" |
|
732 |
try: |
|
733 |
self._sftp.rename(self._remote_path(rel_from), |
|
734 |
self._remote_path(rel_to)) |
|
735 |
except (IOError, paramiko.SSHException), e: |
|
736 |
self._translate_io_exception(e, rel_from, |
|
737 |
': unable to rename to %r' % (rel_to)) |
|
738 |
||
739 |
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. |
740 |
"""Do a fancy rename on the remote server. |
741 |
|
|
742 |
Using the implementation provided by osutils.
|
|
743 |
"""
|
|
744 |
try: |
|
745 |
fancy_rename(abs_from, abs_to, |
|
746 |
rename_func=self._sftp.rename, |
|
747 |
unlink_func=self._sftp.remove) |
|
748 |
except (IOError, paramiko.SSHException), e: |
|
749 |
self._translate_io_exception(e, abs_from, ': unable to rename to %r' % (abs_to)) |
|
750 |
||
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
751 |
def move(self, rel_from, rel_to): |
752 |
"""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 |
753 |
path_from = self._remote_path(rel_from) |
754 |
path_to = self._remote_path(rel_to) |
|
|
1553.5.13
by Martin Pool
New Transport.rename that mustn't overwrite |
755 |
self._rename_and_overwrite(path_from, path_to) |
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
756 |
|
757 |
def delete(self, relpath): |
|
758 |
"""Delete the item at relpath""" |
|
|
1524.1.1
by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir |
759 |
path = self._remote_path(relpath) |
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
760 |
try: |
761 |
self._sftp.remove(path) |
|
|
1185.50.13
by John Arbash Meinel
Expanded the Transport test suite. Including delete, copy, move, etc. Updated SftpTransport to conform. |
762 |
except (IOError, paramiko.SSHException), e: |
763 |
self._translate_io_exception(e, path, ': unable to delete') |
|
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
764 |
|
765 |
def listable(self): |
|
766 |
"""Return True if this store supports listing.""" |
|
767 |
return True |
|
768 |
||
769 |
def list_dir(self, relpath): |
|
770 |
""" |
|
771 |
Return a list of all files at the given location.
|
|
772 |
"""
|
|
773 |
# does anything actually use this?
|
|
|
1959.2.1
by John Arbash Meinel
David Allouche: Make transports return escaped paths |
774 |
# -- Unknown
|
775 |
# This is at least used by copy_tree for remote upgrades.
|
|
776 |
# -- David Allouche 2006-08-11
|
|
|
1524.1.1
by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir |
777 |
path = self._remote_path(relpath) |
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
778 |
try: |
|
1959.2.1
by John Arbash Meinel
David Allouche: Make transports return escaped paths |
779 |
entries = self._sftp.listdir(path) |
|
1185.50.13
by John Arbash Meinel
Expanded the Transport test suite. Including delete, copy, move, etc. Updated SftpTransport to conform. |
780 |
except (IOError, paramiko.SSHException), e: |
781 |
self._translate_io_exception(e, path, ': failed to list_dir') |
|
|
1959.2.2
by John Arbash Meinel
Apply Andrew Bennetts list_dir fixes |
782 |
return [urlutils.escape(entry) for entry in entries] |
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
783 |
|
|
1534.4.15
by Robert Collins
Remove shutil dependency in upgrade - create a delete_tree method for transports. |
784 |
def rmdir(self, relpath): |
785 |
"""See Transport.rmdir.""" |
|
786 |
path = self._remote_path(relpath) |
|
787 |
try: |
|
788 |
return self._sftp.rmdir(path) |
|
789 |
except (IOError, paramiko.SSHException), e: |
|
790 |
self._translate_io_exception(e, path, ': failed to rmdir') |
|
791 |
||
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
792 |
def stat(self, relpath): |
793 |
"""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 |
794 |
path = self._remote_path(relpath) |
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
795 |
try: |
796 |
return self._sftp.stat(path) |
|
|
1185.50.13
by John Arbash Meinel
Expanded the Transport test suite. Including delete, copy, move, etc. Updated SftpTransport to conform. |
797 |
except (IOError, paramiko.SSHException), e: |
798 |
self._translate_io_exception(e, path, ': unable to stat') |
|
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
799 |
|
800 |
def lock_read(self, relpath): |
|
801 |
""" |
|
802 |
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 |
803 |
:return: A lock object, which has an unlock() member function
|
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
804 |
"""
|
805 |
# FIXME: there should be something clever i can do here...
|
|
806 |
class BogusLock(object): |
|
807 |
def __init__(self, path): |
|
808 |
self.path = path |
|
809 |
def unlock(self): |
|
810 |
pass
|
|
811 |
return BogusLock(relpath) |
|
812 |
||
813 |
def lock_write(self, relpath): |
|
814 |
""" |
|
815 |
Lock the given file for exclusive (write) access.
|
|
816 |
WARNING: many transports do not support this, so trying avoid using it
|
|
817 |
||
|
1185.49.3
by John Arbash Meinel
Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path |
818 |
:return: A lock object, which has an unlock() member function
|
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
819 |
"""
|
|
1185.49.2
by John Arbash Meinel
Adding a open_exclusive function since paramiko supports it, but doesn't expose it |
820 |
# This is a little bit bogus, but basically, we create a file
|
821 |
# which should not already exist, and if it does, we assume
|
|
822 |
# that there is a lock, and if it doesn't, the we assume
|
|
823 |
# 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 |
824 |
return SFTPLock(relpath, self) |
|
1185.16.87
by mbp at sourcefrog
- fix line endings in sftp transport |
825 |
|
826 |
def _sftp_connect(self): |
|
|
1185.49.14
by John Arbash Meinel
[merge] bzr.dev |
827 |
"""Connect to the remote sftp server. |
828 |
After this, self._sftp should have a valid connection (or
|
|
|
1185.31.44
by John Arbash Meinel
Cleaned up Exceptions for all transports. |
829 |
we raise an TransportError 'could not connect').
|
|
1185.49.14
by John Arbash Meinel
[merge] bzr.dev |
830 |
|
831 |
TODO: Raise a more reasonable ConnectionFailed exception
|
|
832 |
"""
|
|
|
1951.1.3
by Andrew Bennetts
Move paramiko connection code out of SFTPTransport. |
833 |
self._sftp = _sftp_connect(self._host, self._port, self._username, |
834 |
self._password) |
|
|
1185.49.2
by John Arbash Meinel
Adding a open_exclusive function since paramiko supports it, but doesn't expose it |
835 |
|
|
1185.58.2
by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work. |
836 |
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 |
837 |
"""Open a remote path exclusively. |
838 |
||
839 |
SFTP supports O_EXCL (SFTP_FLAG_EXCL), which fails if
|
|
840 |
the file already exists. However it does not expose this
|
|
841 |
at the higher level of SFTPClient.open(), so we have to
|
|
842 |
sneak away with it.
|
|
843 |
||
844 |
WARNING: This breaks the SFTPClient abstraction, so it
|
|
845 |
could easily break against an updated version of paramiko.
|
|
846 |
||
|
1185.58.2
by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work. |
847 |
:param abspath: The remote absolute path where the file should be opened
|
848 |
: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 |
849 |
"""
|
|
1946.1.8
by John Arbash Meinel
Update non_atomic_put to have a create_parent_dir flag |
850 |
# TODO: jam 20060816 Paramiko >= 1.6.2 (probably earlier) supports
|
851 |
# using the 'x' flag to indicate SFTP_FLAG_EXCL.
|
|
852 |
# However, there is no way to set the permission mode at open
|
|
853 |
# time using the sftp_client.file() functionality.
|
|
|
1185.58.2
by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work. |
854 |
path = self._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 |
855 |
# 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 |
856 |
attr = SFTPAttributes() |
|
1185.58.2
by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work. |
857 |
if mode is not None: |
858 |
attr.st_mode = mode |
|
859 |
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 |
860 |
| SFTP_FLAG_TRUNC | SFTP_FLAG_EXCL) |
861 |
try: |
|
|
1185.58.2
by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work. |
862 |
t, msg = self._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 |
863 |
if t != CMD_HANDLE: |
|
1185.31.44
by John Arbash Meinel
Cleaned up Exceptions for all transports. |
864 |
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 |
865 |
handle = msg.get_string() |
|
1185.31.51
by John Arbash Meinel
Setting binary flags for sftp. |
866 |
return SFTPFile(self._sftp, handle, 'wb', -1) |
|
1185.31.44
by John Arbash Meinel
Cleaned up Exceptions for all transports. |
867 |
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. |
868 |
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. |
869 |
failure_exc=FileExists) |
|
1185.49.2
by John Arbash Meinel
Adding a open_exclusive function since paramiko supports it, but doesn't expose it |
870 |
|
|
1988.1.1
by John Arbash Meinel
Restore mode bit tests for sftp, and track down bugs |
871 |
def _can_roundtrip_unix_modebits(self): |
872 |
if sys.platform == 'win32': |
|
873 |
# anyone else?
|
|
874 |
return False |
|
875 |
else: |
|
876 |
return True |
|
|
1530.1.1
by Robert Collins
Minimal infrastructure to test TransportTestProviderAdapter. |
877 |
|
|
1530.1.3
by Robert Collins
transport implementations now tested consistently. |
878 |
# ------------- server test implementation --------------
|
879 |
import threading |
|
880 |
||
881 |
from bzrlib.tests.stub_sftp import StubServer, StubSFTPServer |
|
882 |
||
883 |
STUB_SERVER_KEY = """ |
|
884 |
-----BEGIN RSA PRIVATE KEY-----
|
|
885 |
MIICWgIBAAKBgQDTj1bqB4WmayWNPB+8jVSYpZYk80Ujvj680pOTh2bORBjbIAyz
|
|
886 |
oWGW+GUjzKxTiiPvVmxFgx5wdsFvF03v34lEVVhMpouqPAYQ15N37K/ir5XY+9m/
|
|
887 |
d8ufMCkjeXsQkKqFbAlQcnWMCRnOoPHS3I4vi6hmnDDeeYTSRvfLbW0fhwIBIwKB
|
|
888 |
gBIiOqZYaoqbeD9OS9z2K9KR2atlTxGxOJPXiP4ESqP3NVScWNwyZ3NXHpyrJLa0
|
|
889 |
EbVtzsQhLn6rF+TzXnOlcipFvjsem3iYzCpuChfGQ6SovTcOjHV9z+hnpXvQ/fon
|
|
890 |
soVRZY65wKnF7IAoUwTmJS9opqgrN6kRgCd3DASAMd1bAkEA96SBVWFt/fJBNJ9H
|
|
891 |
tYnBKZGw0VeHOYmVYbvMSstssn8un+pQpUm9vlG/bp7Oxd/m+b9KWEh2xPfv6zqU
|
|
892 |
avNwHwJBANqzGZa/EpzF4J8pGti7oIAPUIDGMtfIcmqNXVMckrmzQ2vTfqtkEZsA
|
|
893 |
4rE1IERRyiJQx6EJsz21wJmGV9WJQ5kCQQDwkS0uXqVdFzgHO6S++tjmjYcxwr3g
|
|
894 |
H0CoFYSgbddOT6miqRskOQF3DZVkJT3kyuBgU2zKygz52ukQZMqxCb1fAkASvuTv
|
|
895 |
qfpH87Qq5kQhNKdbbwbmd2NxlNabazPijWuphGTdW0VfJdWfklyS2Kr+iqrs/5wV
|
|
896 |
HhathJt636Eg7oIjAkA8ht3MQ+XSl9yIJIS8gVpbPxSw5OMfw0PjVE7tBdQruiSc
|
|
897 |
nvuQES5C9BMHjF39LZiGH1iLQy7FgdHyoP+eodI7
|
|
898 |
-----END RSA PRIVATE KEY-----
|
|
899 |
"""
|
|
|
1551.6.39
by Aaron Bentley
Apply Robey Pointer's listener patch |
900 |
|
901 |
||
902 |
class SocketListener(threading.Thread): |
|
|
1530.1.3
by Robert Collins
transport implementations now tested consistently. |
903 |
|
904 |
def __init__(self, callback): |
|
905 |
threading.Thread.__init__(self) |
|
906 |
self._callback = callback |
|
907 |
self._socket = socket.socket() |
|
908 |
self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) |
|
909 |
self._socket.bind(('localhost', 0)) |
|
910 |
self._socket.listen(1) |
|
911 |
self.port = self._socket.getsockname()[1] |
|
|
1551.6.39
by Aaron Bentley
Apply Robey Pointer's listener patch |
912 |
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 |
913 |
|
|
1530.1.3
by Robert Collins
transport implementations now tested consistently. |
914 |
def stop(self): |
|
1551.6.39
by Aaron Bentley
Apply Robey Pointer's listener patch |
915 |
# called from outside this thread
|
916 |
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 |
917 |
# use a timeout here, because if the test fails, the server thread may
|
918 |
# never notice the stop_event.
|
|
919 |
self.join(5.0) |
|
|
1551.6.39
by Aaron Bentley
Apply Robey Pointer's listener patch |
920 |
self._socket.close() |
921 |
||
922 |
def run(self): |
|
923 |
while True: |
|
|
1551.6.40
by Aaron Bentley
Wrapped long lines in Robey's patch |
924 |
readable, writable_unused, exception_unused = \ |
925 |
select.select([self._socket], [], [], 0.1) |
|
|
1551.6.39
by Aaron Bentley
Apply Robey Pointer's listener patch |
926 |
if self._stop_event.isSet(): |
927 |
return
|
|
928 |
if len(readable) == 0: |
|
929 |
continue
|
|
930 |
try: |
|
931 |
s, addr_unused = self._socket.accept() |
|
932 |
# because the loopback socket is inline, and transports are
|
|
933 |
# never explicitly closed, best to launch a new thread.
|
|
934 |
threading.Thread(target=self._callback, args=(s,)).start() |
|
935 |
except socket.error, x: |
|
936 |
sys.excepthook(*sys.exc_info()) |
|
|
1551.6.40
by Aaron Bentley
Wrapped long lines in Robey's patch |
937 |
warning('Socket error during accept() within unit test server' |
938 |
' thread: %r' % x) |
|
|
1551.6.39
by Aaron Bentley
Apply Robey Pointer's listener patch |
939 |
except Exception, x: |
|
1551.6.40
by Aaron Bentley
Wrapped long lines in Robey's patch |
940 |
# probably a failed test; unit test thread will log the
|
941 |
# failure/error
|
|
|
1551.6.39
by Aaron Bentley
Apply Robey Pointer's listener patch |
942 |
sys.excepthook(*sys.exc_info()) |
|
1551.6.40
by Aaron Bentley
Wrapped long lines in Robey's patch |
943 |
warning('Exception from within unit test server thread: %r' % |
944 |
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 |
945 |
|
946 |
||
|
1871.1.3
by Robert Collins
proof of concept slowsocket wrapper. |
947 |
class SocketDelay(object): |
948 |
"""A socket decorator to make TCP appear slower. |
|
949 |
||
|
1874.1.2
by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to |
950 |
This changes recv, send, and sendall to add a fixed latency to each python
|
951 |
call if a new roundtrip is detected. That is, when a recv is called and the
|
|
952 |
flag new_roundtrip is set, latency is charged. Every send and send_all
|
|
953 |
sets this flag.
|
|
954 |
||
955 |
In addition every send, sendall and recv sleeps a bit per character send to
|
|
956 |
simulate bandwidth.
|
|
957 |
||
958 |
Not all methods are implemented, this is deliberate as this class is not a
|
|
959 |
replacement for the builtin sockets layer. fileno is not implemented to
|
|
960 |
prevent the proxy being bypassed.
|
|
|
1871.1.3
by Robert Collins
proof of concept slowsocket wrapper. |
961 |
"""
|
962 |
||
|
1874.1.2
by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to |
963 |
simulated_time = 0 |
|
1874.1.9
by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert. |
964 |
_proxied_arguments = dict.fromkeys([ |
965 |
"close", "getpeername", "getsockname", "getsockopt", "gettimeout", |
|
966 |
"setblocking", "setsockopt", "settimeout", "shutdown"]) |
|
|
1874.1.2
by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to |
967 |
|
|
1874.1.5
by holger krekel
(cfbolz, hpk) Refactored bandwidth parameter. Fixed indentation bug in 'send'. |
968 |
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. |
969 |
really_sleep=True): |
|
1874.1.5
by holger krekel
(cfbolz, hpk) Refactored bandwidth parameter. Fixed indentation bug in 'send'. |
970 |
""" |
971 |
:param bandwith: simulated bandwith (MegaBit)
|
|
|
1874.1.9
by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert. |
972 |
:param really_sleep: If set to false, the SocketDelay will just
|
973 |
increase a counter, instead of calling time.sleep. This is useful for
|
|
974 |
unittesting the SocketDelay.
|
|
|
1874.1.5
by holger krekel
(cfbolz, hpk) Refactored bandwidth parameter. Fixed indentation bug in 'send'. |
975 |
"""
|
|
1871.1.3
by Robert Collins
proof of concept slowsocket wrapper. |
976 |
self.sock = sock |
977 |
self.latency = latency |
|
|
1874.1.2
by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to |
978 |
self.really_sleep = really_sleep |
|
1874.1.5
by holger krekel
(cfbolz, hpk) Refactored bandwidth parameter. Fixed indentation bug in 'send'. |
979 |
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 |
980 |
self.new_roundtrip = False |
981 |
||
982 |
def sleep(self, s): |
|
983 |
if self.really_sleep: |
|
984 |
time.sleep(s) |
|
|
1874.1.9
by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert. |
985 |
else: |
986 |
SocketDelay.simulated_time += s |
|
|
1871.1.3
by Robert Collins
proof of concept slowsocket wrapper. |
987 |
|
|
1874.1.9
by Carl Friedrich Bolz
Try to fix all the issues outline by john and Robert. |
988 |
def __getattr__(self, attr): |
989 |
if attr in SocketDelay._proxied_arguments: |
|
990 |
return getattr(self.sock, attr) |
|
991 |
raise AttributeError("'SocketDelay' object has no attribute %r" % |
|
992 |
attr) |
|
|
1871.1.3
by Robert Collins
proof of concept slowsocket wrapper. |
993 |
|
994 |
def dup(self): |
|
|
1874.1.5
by holger krekel
(cfbolz, hpk) Refactored bandwidth parameter. Fixed indentation bug in 'send'. |
995 |
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 |
996 |
self._sleep) |
|
1871.1.3
by Robert Collins
proof of concept slowsocket wrapper. |
997 |
|
998 |
def recv(self, *args): |
|
999 |
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 |
1000 |
if data and self.new_roundtrip: |
1001 |
self.new_roundtrip = False |
|
1002 |
self.sleep(self.latency) |
|
|
1874.1.5
by holger krekel
(cfbolz, hpk) Refactored bandwidth parameter. Fixed indentation bug in 'send'. |
1003 |
self.sleep(len(data) * self.time_per_byte) |
|
1871.1.3
by Robert Collins
proof of concept slowsocket wrapper. |
1004 |
return data |
1005 |
||
|
1874.1.2
by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to |
1006 |
def sendall(self, data, flags=0): |
1007 |
if not self.new_roundtrip: |
|
1008 |
self.new_roundtrip = True |
|
1009 |
self.sleep(self.latency) |
|
|
1874.1.5
by holger krekel
(cfbolz, hpk) Refactored bandwidth parameter. Fixed indentation bug in 'send'. |
1010 |
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 |
1011 |
return self.sock.sendall(data, flags) |
|
1871.1.3
by Robert Collins
proof of concept slowsocket wrapper. |
1012 |
|
|
1874.1.2
by Carl Friedrich Bolz
Refined the SocketDelay to charge latency only once per round-trip and to |
1013 |
def send(self, data, flags=0): |
1014 |
if not self.new_roundtrip: |
|
1015 |
self.new_roundtrip = True |
|
1016 |
self.sleep(self.latency) |
|
1017 |
bytes_sent = self.sock.send(data, flags) |
|
|
1874.1.5
by holger krekel
(cfbolz, hpk) Refactored bandwidth parameter. Fixed indentation bug in 'send'. |
1018 |
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 |
1019 |
return bytes_sent |
|
1871.1.3
by Robert Collins
proof of concept slowsocket wrapper. |
1020 |
|
1021 |
||
|
1530.1.3
by Robert Collins
transport implementations now tested consistently. |
1022 |
class SFTPServer(Server): |
1023 |
"""Common code for SFTP server facilities.""" |
|
1024 |
||
|
2018.1.1
by Andrew Bennetts
Make bzr+ssh:// actually work (at least with absolute paths). |
1025 |
def __init__(self, server_interface=StubServer): |
|
1530.1.3
by Robert Collins
transport implementations now tested consistently. |
1026 |
self._original_vendor = None |
1027 |
self._homedir = None |
|
|
1530.1.8
by Robert Collins
More NEWS, move sibling sftp tests into new framework, nuke legacy local transport tests. |
1028 |
self._server_homedir = None |
|
1530.1.3
by Robert Collins
transport implementations now tested consistently. |
1029 |
self._listener = None |
1030 |
self._root = None |
|
|
1951.1.8
by Andrew Bennetts
Make _get_ssh_vendor return the vendor object, rather than just a string. |
1031 |
self._vendor = ssh.ParamikoVendor() |
|
2018.1.1
by Andrew Bennetts
Make bzr+ssh:// actually work (at least with absolute paths). |
1032 |
self._server_interface = server_interface |
|
1530.1.6
by Robert Collins
Trim duplicate sftp tests. |
1033 |
# sftp server logs
|
1034 |
self.logs = [] |
|
|
1871.1.3
by Robert Collins
proof of concept slowsocket wrapper. |
1035 |
self.add_latency = 0 |
|
1530.1.3
by Robert Collins
transport implementations now tested consistently. |
1036 |
|
|
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 |
1037 |
def _get_sftp_url(self, path): |
1038 |
"""Calculate an sftp url to this server for path.""" |
|
1039 |
return 'sftp://foo:bar@localhost:%d/%s' % (self._listener.port, path) |
|
1040 |
||
|
1530.1.6
by Robert Collins
Trim duplicate sftp tests. |
1041 |
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 |
1042 |
"""StubServer uses this to log when a new server is created.""" |
|
1530.1.6
by Robert Collins
Trim duplicate sftp tests. |
1043 |
self.logs.append(message) |
|
1530.1.3
by Robert Collins
transport implementations now tested consistently. |
1044 |
|
|
1871.1.3
by Robert Collins
proof of concept slowsocket wrapper. |
1045 |
def _run_server_entry(self, sock): |
1046 |
"""Entry point for all implementations of _run_server. |
|
1047 |
|
|
1048 |
If self.add_latency is > 0.000001 then sock is given a latency adding
|
|
1049 |
decorator.
|
|
1050 |
"""
|
|
1051 |
if self.add_latency > 0.000001: |
|
1052 |
sock = SocketDelay(sock, self.add_latency) |
|
1053 |
return self._run_server(sock) |
|
1054 |
||
|
1551.6.39
by Aaron Bentley
Apply Robey Pointer's listener patch |
1055 |
def _run_server(self, s): |
|
1530.1.3
by Robert Collins
transport implementations now tested consistently. |
1056 |
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 |
1057 |
key_file = pathjoin(self._homedir, 'test_rsa.key') |
|
1551.6.39
by Aaron Bentley
Apply Robey Pointer's listener patch |
1058 |
f = open(key_file, 'w') |
1059 |
f.write(STUB_SERVER_KEY) |
|
1060 |
f.close() |
|
|
1530.1.3
by Robert Collins
transport implementations now tested consistently. |
1061 |
host_key = paramiko.RSAKey.from_private_key_file(key_file) |
1062 |
ssh_server.add_server_key(host_key) |
|
|
2018.1.1
by Andrew Bennetts
Make bzr+ssh:// actually work (at least with absolute paths). |
1063 |
server = self._server_interface(self) |
|
1530.1.3
by Robert Collins
transport implementations now tested consistently. |
1064 |
ssh_server.set_subsystem_handler('sftp', paramiko.SFTPServer, |
1065 |
StubSFTPServer, root=self._root, |
|
|
1530.1.8
by Robert Collins
More NEWS, move sibling sftp tests into new framework, nuke legacy local transport tests. |
1066 |
home=self._server_homedir) |
|
1530.1.3
by Robert Collins
transport implementations now tested consistently. |
1067 |
event = threading.Event() |
1068 |
ssh_server.start_server(event, server) |
|
1069 |
event.wait(5.0) |
|
|
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 |
1070 |
|
|
1530.1.3
by Robert Collins
transport implementations now tested consistently. |
1071 |
def setUp(self): |
|
1951.1.10
by Andrew Bennetts
Move register_ssh_vendor, _ssh_vendor and _get_ssh_vendor into ssh.py |
1072 |
self._original_vendor = ssh._ssh_vendor |
1073 |
ssh._ssh_vendor = self._vendor |
|
|
1711.6.3
by John Arbash Meinel
Fix regression on unicode tests for SFTP under Linux |
1074 |
if sys.platform == 'win32': |
1075 |
# Win32 needs to use the UNICODE api
|
|
1076 |
self._homedir = getcwd() |
|
1077 |
else: |
|
1078 |
# But Linux SFTP servers should just deal in bytestreams
|
|
1079 |
self._homedir = os.getcwd() |
|
|
1530.1.8
by Robert Collins
More NEWS, move sibling sftp tests into new framework, nuke legacy local transport tests. |
1080 |
if self._server_homedir is None: |
1081 |
self._server_homedir = self._homedir |
|
|
1530.1.3
by Robert Collins
transport implementations now tested consistently. |
1082 |
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 |
1083 |
if sys.platform == 'win32': |
1084 |
self._root = '' |
|
|
1871.1.3
by Robert Collins
proof of concept slowsocket wrapper. |
1085 |
self._listener = SocketListener(self._run_server_entry) |
|
1530.1.3
by Robert Collins
transport implementations now tested consistently. |
1086 |
self._listener.setDaemon(True) |
1087 |
self._listener.start() |
|
1088 |
||
1089 |
def tearDown(self): |
|
1090 |
"""See bzrlib.transport.Server.tearDown.""" |
|
1091 |
self._listener.stop() |
|
|
1951.1.10
by Andrew Bennetts
Move register_ssh_vendor, _ssh_vendor and _get_ssh_vendor into ssh.py |
1092 |
ssh._ssh_vendor = self._original_vendor |
|
1530.1.3
by Robert Collins
transport implementations now tested consistently. |
1093 |
|
|
1711.2.42
by John Arbash Meinel
enable bogus_url support for SFTP tests |
1094 |
def get_bogus_url(self): |
1095 |
"""See bzrlib.transport.Server.get_bogus_url.""" |
|
|
1185.49.35
by John Arbash Meinel
Update tests to use a truly unused port |
1096 |
# this is chosen to try to prevent trouble with proxies, wierd dns, etc
|
1097 |
# we bind a random socket, so that we get a guaranteed unused port
|
|
1098 |
# we just never listen on that port
|
|
1099 |
s = socket.socket() |
|
1100 |
s.bind(('localhost', 0)) |
|
1101 |
return 'sftp://%s:%s/' % s.getsockname() |
|
|
1711.2.42
by John Arbash Meinel
enable bogus_url support for SFTP tests |
1102 |
|
1103 |
||
|
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. |
1104 |
class SFTPFullAbsoluteServer(SFTPServer): |
1105 |
"""A test server for sftp transports, using absolute urls and ssh.""" |
|
1106 |
||
1107 |
def get_url(self): |
|
1108 |
"""See bzrlib.transport.Server.get_url.""" |
|
|
1685.1.45
by John Arbash Meinel
Moved url functions into bzrlib.urlutils |
1109 |
return self._get_sftp_url(urlutils.escape(self._homedir[1:])) |
|
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. |
1110 |
|
1111 |
||
|
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 |
1112 |
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. |
1113 |
"""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 |
1114 |
|
1115 |
def __init__(self): |
|
1116 |
super(SFTPServerWithoutSSH, self).__init__() |
|
|
1951.1.8
by Andrew Bennetts
Make _get_ssh_vendor return the vendor object, rather than just a string. |
1117 |
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 |
1118 |
|
|
1551.6.39
by Aaron Bentley
Apply Robey Pointer's listener patch |
1119 |
def _run_server(self, sock): |
|
1951.1.10
by Andrew Bennetts
Move register_ssh_vendor, _ssh_vendor and _get_ssh_vendor into ssh.py |
1120 |
# Re-import these as locals, so that they're still accessible during
|
1121 |
# interpreter shutdown (when all module globals get set to None, leading
|
|
1122 |
# 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 |
1123 |
class FakeChannel(object): |
1124 |
def get_transport(self): |
|
1125 |
return self |
|
1126 |
def get_log_channel(self): |
|
1127 |
return 'paramiko' |
|
1128 |
def get_name(self): |
|
1129 |
return '1' |
|
1130 |
def get_hexdump(self): |
|
1131 |
return False |
|
|
1711.2.1
by John Arbash Meinel
[patch] Marien Zwart: paramiko-1.6 compatibility fix |
1132 |
def close(self): |
1133 |
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 |
1134 |
|
1135 |
server = paramiko.SFTPServer(FakeChannel(), 'sftp', StubServer(self), StubSFTPServer, |
|
1136 |
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. |
1137 |
try: |
1138 |
server.start_subsystem('sftp', None, sock) |
|
1139 |
except socket.error, e: |
|
1140 |
if (len(e.args) > 0) and (e.args[0] == errno.EPIPE): |
|
1141 |
# it's okay for the client to disconnect abruptly
|
|
1142 |
# (bug in paramiko 1.6: it should absorb this exception)
|
|
1143 |
pass
|
|
1144 |
else: |
|
1145 |
raise
|
|
1146 |
except Exception, e: |
|
1147 |
import sys; sys.stderr.write('\nEXCEPTION %r\n\n' % e.__class__) |
|
|
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 |
1148 |
server.finish_subsystem() |
1149 |
||
1150 |
||
1151 |
class SFTPAbsoluteServer(SFTPServerWithoutSSH): |
|
|
1530.1.1
by Robert Collins
Minimal infrastructure to test TransportTestProviderAdapter. |
1152 |
"""A test server for sftp transports, using absolute urls.""" |
1153 |
||
|
1530.1.3
by Robert Collins
transport implementations now tested consistently. |
1154 |
def get_url(self): |
1155 |
"""See bzrlib.transport.Server.get_url.""" |
|
|
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 |
1156 |
if sys.platform == 'win32': |
1157 |
return self._get_sftp_url(urlutils.escape(self._homedir)) |
|
1158 |
else: |
|
1159 |
return self._get_sftp_url(urlutils.escape(self._homedir[1:])) |
|
|
1530.1.3
by Robert Collins
transport implementations now tested consistently. |
1160 |
|
1161 |
||
|
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 |
1162 |
class SFTPHomeDirServer(SFTPServerWithoutSSH): |
|
1530.1.1
by Robert Collins
Minimal infrastructure to test TransportTestProviderAdapter. |
1163 |
"""A test server for sftp transports, using homedir relative urls.""" |
|
1530.1.3
by Robert Collins
transport implementations now tested consistently. |
1164 |
|
1165 |
def get_url(self): |
|
1166 |
"""See bzrlib.transport.Server.get_url.""" |
|
|
1534.1.8
by Robert Collins
Update SFTP Urls as per mailing list thread. |
1167 |
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. |
1168 |
|
1169 |
||
1170 |
class SFTPSiblingAbsoluteServer(SFTPAbsoluteServer): |
|
1171 |
"""A test servere for sftp transports, using absolute urls to non-home.""" |
|
1172 |
||
1173 |
def setUp(self): |
|
1174 |
self._server_homedir = '/dev/noone/runs/tests/here' |
|
1175 |
super(SFTPSiblingAbsoluteServer, self).setUp() |
|
|
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. |
1176 |
|
1177 |
||
|
1951.1.3
by Andrew Bennetts
Move paramiko connection code out of SFTPTransport. |
1178 |
def _sftp_connect(host, port, username, password): |
1179 |
"""Connect to the remote sftp server. |
|
1180 |
||
1181 |
:raises: a TransportError 'could not connect'.
|
|
1182 |
||
|
1951.1.7
by Andrew Bennetts
Move more generic SSH code from sftp.py into ssh.py, and start unifying the connection establishing logic. |
1183 |
:returns: an paramiko.sftp_client.SFTPClient
|
|
1951.1.3
by Andrew Bennetts
Move paramiko connection code out of SFTPTransport. |
1184 |
|
1185 |
TODO: Raise a more reasonable ConnectionFailed exception
|
|
1186 |
"""
|
|
1187 |
idx = (host, port, username) |
|
1188 |
try: |
|
|
1951.1.9
by Andrew Bennetts
Add docstrings and tweak method names in ssh.py |
1189 |
return _connected_hosts[idx] |
|
1951.1.3
by Andrew Bennetts
Move paramiko connection code out of SFTPTransport. |
1190 |
except KeyError: |
1191 |
pass
|
|
1192 |
||
|
1951.1.4
by Andrew Bennetts
Start moving SSH connection code into bzrlib/transport/ssh.py |
1193 |
sftp = _sftp_connect_uncached(host, port, username, password) |
|
1951.1.9
by Andrew Bennetts
Add docstrings and tweak method names in ssh.py |
1194 |
_connected_hosts[idx] = sftp |
|
1951.1.4
by Andrew Bennetts
Start moving SSH connection code into bzrlib/transport/ssh.py |
1195 |
return sftp |
1196 |
||
1197 |
def _sftp_connect_uncached(host, port, username, password): |
|
|
1951.1.10
by Andrew Bennetts
Move register_ssh_vendor, _ssh_vendor and _get_ssh_vendor into ssh.py |
1198 |
vendor = ssh._get_ssh_vendor() |
|
1951.1.8
by Andrew Bennetts
Make _get_ssh_vendor return the vendor object, rather than just a string. |
1199 |
sftp = vendor.connect_sftp(username, password, host, port) |
|
1951.1.7
by Andrew Bennetts
Move more generic SSH code from sftp.py into ssh.py, and start unifying the connection establishing logic. |
1200 |
return sftp |
|
1951.1.3
by Andrew Bennetts
Move paramiko connection code out of SFTPTransport. |
1201 |
|
1202 |
||
|
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. |
1203 |
def get_test_permutations(): |
1204 |
"""Return the permutations to be used in testing.""" |
|
1205 |
return [(SFTPTransport, SFTPAbsoluteServer), |
|
1206 |
(SFTPTransport, SFTPHomeDirServer), |
|
1207 |
(SFTPTransport, SFTPSiblingAbsoluteServer), |
|
1208 |
]
|