36
36
from bzrlib.config import config_dir, ensure_config_dir_exists
37
37
from bzrlib.trace import mutter, warning, error
38
38
from bzrlib.transport import Transport, register_transport
39
from bzrlib.osutils import pathjoin
39
from bzrlib.osutils import pathjoin, fancy_rename
356
356
tmp_abspath = self._abspath(tmp_relpath)
357
357
fout = self._sftp_open_exclusive(tmp_relpath)
361
362
self._pump(f, fout)
362
except (paramiko.SSHException, IOError), e:
363
self._translate_io_exception(e, relpath, ': unable to write')
363
except (IOError, paramiko.SSHException), e:
364
self._translate_io_exception(e, tmp_abspath)
367
self._rename(tmp_abspath, final_path)
364
368
except Exception, e:
365
369
# If we fail, try to clean up the temporary file
366
370
# before we throw the exception
367
371
# but don't let another exception mess things up
370
375
self._sftp.remove(tmp_abspath)
375
# sftp rename doesn't allow overwriting, so play tricks:
376
tmp_safety = 'bzr.tmp.%.9f.%d.%d' % (time.time(), os.getpid(), random.randint(0, 0x7FFFFFFF))
377
tmp_safety = self._abspath(tmp_safety)
379
self._sftp.rename(final_path, tmp_safety)
386
self._sftp.rename(tmp_abspath, final_path)
387
except (paramiko.SSHException, IOError), e:
388
self._translate_io_exception(e, relpath, ': unable to rename')
394
self._sftp.unlink(tmp_safety)
396
self._sftp.rename(tmp_safety, final_path)
398
380
def iter_files_recursive(self):
399
381
"""Walk the relative paths of all files in this transport."""
501
483
return self._iterate_over(relpaths, copy_entry, pb, 'copy_to', expand=False)
485
def _rename(self, abs_from, abs_to):
486
"""Do a fancy rename on the remote server.
488
Using the implementation provided by osutils.
491
fancy_rename(abs_from, abs_to,
492
rename_func=self._sftp.rename,
493
unlink_func=self._sftp.remove)
494
except (IOError, paramiko.SSHException), e:
495
self._translate_io_exception(e, abs_from, ': unable to rename to %r' % (abs_to))
503
497
def move(self, rel_from, rel_to):
504
498
"""Move the item at rel_from to the location at rel_to"""
505
499
path_from = self._abspath(rel_from)
506
500
path_to = self._abspath(rel_to)
508
self._sftp.rename(path_from, path_to)
509
except (IOError, paramiko.SSHException), x:
510
raise TransportError('Unable to move %r to %r' % (path_from, path_to), x)
501
self._rename(path_from, path_to)
512
503
def delete(self, relpath):
513
504
"""Delete the item at relpath"""