sftp: make move an atomic operation

This commit is contained in:
Mr. Outis
2019-11-01 13:17:22 -06:00
parent ab1ead881b
commit 283f848822
2 changed files with 15 additions and 8 deletions
+9 -8
View File
@@ -185,17 +185,18 @@ class SSHConnection:
self.sftp.get(src, dest, callback=pbar.update_to)
def move(self, src, dst):
"""Use `SFTP RENAME` operation when possible, otherwise,
fallback to copy and remove, since the former one doesn't
work across drives.
"""Atomically move src to dst.
Moving is performed in two stages to make the whole operation atomic in
case src and dst are on different filesystems and actual physical
copying of data is happening.
"""
self.makedirs(posixpath.dirname(dst))
try:
self.sftp.rename(src, dst)
except OSError:
self.copy(src, dst)
self.remove(src)
tmp = tmp_fname(dst)
self.copy(src, tmp)
self.sftp.rename(tmp, dst)
self.remove(src)
def upload(self, src, dest, no_progress_bar=False, progress_title=None):
self.makedirs(posixpath.dirname(dest))
+6
View File
@@ -111,3 +111,9 @@ def test_hardlink(repo_dir, ssh):
def test_copy(repo_dir, ssh):
ssh.copy("foo", "link")
assert filecmp.cmp("foo", "link")
def test_move(repo_dir, ssh):
ssh.move("foo", "copy")
assert os.path.exists("copy")
assert not os.path.exists("foo")