147
147
def _urldecode_abspath(self, abspath):
148
148
abspath = super(SFTPUrlHandling, self)._urldecode_abspath(abspath)
149
if abspath.startswith('/~/'):
150
abspath = abspath[3:]
151
elif abspath == '/~':
155
def _combine_paths_respecting_home_dir(self, relpath):
149
156
# the initial slash should be removed from the path, and treated
150
157
# as a homedir relative path (the path begins with a double slash
151
158
# if it is absolute).
153
160
# RBC 20060118 we are not using this as its too user hostile. instead
154
161
# we are following lftp and using /~/foo to mean '~/foo'.
156
# handle homedir paths
157
if abspath.startswith('/~/'):
158
abspath = abspath[3:]
159
elif abspath == '/~':
163
if not self._path.startswith('/'):
164
abspath = self._combine_paths('/~/' + self._path, relpath)
165
if abspath.startswith('/~/'):
166
abspath = abspath[3:]
167
elif abspath == '/~':
170
abspath = self._combine_paths(self._path, relpath)
174
def abspath(self, relpath):
175
"""Return the full url to the given relative path respecting home dir"""
176
relative = urlutils.unescape(relpath).encode('utf-8')
177
path = self._combine_paths_respecting_home_dir(relative)
178
return self._unsplit_url(self._scheme, self._user, self._password,
179
self._host, self._port,
180
self._urlencode_abspath(path))
163
183
def _remote_path(self, relpath):
164
184
"""Return the path to be passed along the sftp protocol for relpath.
166
186
:param relpath: is a urlencoded string.
168
188
relative = urlutils.unescape(relpath).encode('utf-8')
169
if not self._path.startswith('/'):
170
# handle homedir paths
171
remote_path = self._combine_paths('/~/' + self._path, relative)
172
if remote_path.startswith('/~/'):
173
remote_path = remote_path[3:]
174
elif remote_path == '/~':
177
remote_path = self._combine_paths(self._path, relative)
189
remote_path = self._combine_paths_respecting_home_dir(relative)
178
190
return remote_path
180
192
class SFTPTransport(SFTPUrlHandling):
198
210
# up the request itself, rather than us having to worry about it
199
211
_max_request_size = 32768
201
def __init__(self, base, clone_from=None):
213
def __init__(self, base, from_transport=None):
202
214
assert base.startswith('sftp://')
203
super(SFTPTransport, self).__init__(base)
204
if clone_from is None:
215
super(SFTPTransport, self).__init__(base, from_transport)
216
if from_transport is None:
205
217
self._sftp_connect()
207
219
# use the same ssh connection, etc
208
self._sftp = clone_from._sftp
220
self._sftp = from_transport._sftp
209
221
# super saves 'self.base'
211
223
def should_cache(self):