196
196
def _abspath(self, relpath):
197
197
assert isinstance(relpath, basestring)
198
198
relpath = urlutils.unescape(relpath)
199
relpath_parts = relpath.split('/')
200
if len(relpath_parts) > 1:
201
if relpath_parts[0] == '':
202
raise ValueError("path %r within branch %r seems to be absolute"
203
% (relpath, self._path))
204
basepath = self._path.split('/')
199
if relpath.startswith('/'):
202
basepath = self._path.split('/')
205
203
if len(basepath) > 0 and basepath[-1] == '':
206
204
basepath = basepath[:-1]
207
for p in relpath_parts:
205
for p in relpath.split('/'):
209
207
if len(basepath) == 0:
210
208
# In most filesystems, a request for the parent
294
292
self._FTP_instance = None
295
293
return self.get(relpath, decode, retries+1)
297
def put(self, relpath, fp, mode=None, retries=0):
295
def put_file(self, relpath, fp, mode=None, retries=0):
298
296
"""Copy the file-like or string object into the location.
300
298
:param relpath: Location to put the contents, relative to base.
307
305
abspath = self._abspath(relpath)
308
306
tmp_abspath = '%s.tmp.%.9f.%d.%d' % (abspath, time.time(),
309
307
os.getpid(), random.randint(0,0x7FFFFFFF))
310
if not hasattr(fp, 'read'):
308
if getattr(fp, 'read', None) is None:
311
309
fp = StringIO(fp)
313
311
mutter("FTP put: %s", abspath)
334
332
warning("FTP temporary error: %s. Retrying.", str(e))
335
333
self._FTP_instance = None
336
self.put(relpath, fp, mode, retries+1)
334
self.put_file(relpath, fp, mode, retries+1)
338
336
if retries > _number_of_retries:
339
337
raise errors.TransportError("FTP control connection closed during PUT %s."
342
340
warning("FTP control connection closed. Trying to reopen.")
343
341
time.sleep(_sleep_between_retries)
344
342
self._FTP_instance = None
345
self.put(relpath, fp, mode, retries+1)
343
self.put_file(relpath, fp, mode, retries+1)
347
345
def mkdir(self, relpath, mode=None):
348
346
"""Create a directory at the given path."""
365
363
except ftplib.error_perm, e:
366
364
self._translate_perm_error(e, abspath, unknown_exc=errors.PathError)
368
def append(self, relpath, f, mode=None):
366
def append_file(self, relpath, f, mode=None):
369
367
"""Append the text in the file-like object into the final
466
464
def list_dir(self, relpath):
467
465
"""See Transport.list_dir."""
466
basepath = self._abspath(relpath)
467
mutter("FTP nlst: %s", basepath)
469
mutter("FTP nlst: %s", self._abspath(relpath))
471
basepath = self._abspath(relpath)
472
470
paths = f.nlst(basepath)
473
# If FTP.nlst returns paths prefixed by relpath, strip 'em
474
if paths and paths[0].startswith(basepath):
475
paths = [path[len(basepath)+1:] for path in paths]
476
# Remove . and .. if present, and return
477
return [path for path in paths if path not in (".", "..")]
478
471
except ftplib.error_perm, e:
479
472
self._translate_perm_error(e, relpath, extra='error with list_dir')
473
# If FTP.nlst returns paths prefixed by relpath, strip 'em
474
if paths and paths[0].startswith(basepath):
475
entries = [path[len(basepath)+1:] for path in paths]
478
# Remove . and .. if present
479
return [urlutils.escape(entry) for entry in entries
480
if entry not in ('.', '..')]
481
482
def iter_files_recursive(self):
482
483
"""See Transport.iter_files_recursive.
485
486
mutter("FTP iter_files_recursive")
486
487
queue = list(self.list_dir("."))
488
relpath = urllib.quote(queue.pop(0))
489
relpath = queue.pop(0)
489
490
st = self.stat(relpath)
490
491
if stat.S_ISDIR(st.st_mode):
491
492
for i, basename in enumerate(self.list_dir(relpath)):