]> arthur.barton.de Git - bup.git/commitdiff
Attempt to unlink or rmdir existing paths as appropriate during restore.
authorRob Browning <rlb@defaultvalue.org>
Sat, 23 Oct 2010 20:28:18 +0000 (15:28 -0500)
committerRob Browning <rlb@defaultvalue.org>
Sat, 23 Oct 2010 20:28:18 +0000 (15:28 -0500)
lib/bup/metadata.py
lib/bup/t/tmetadata.py

index a1188217b4082681a2f35ddc0a13098682b549de..c598701e70d3a0b07ba36afa42715399ed3a2bea 100644 (file)
@@ -237,6 +237,26 @@ class Metadata:
             self.ctime = _normalize_ts(self.ctime)
 
     def _create_via_common_rec(self, path, create_symlinks=True):
+        # If the path already exists and is a dir, try rmdir.
+        # If the path already exists and is anything else, try unlink.
+        st = None
+        try:
+            st = lstat(path)
+        except IOError, e:
+            if e.errno != errno.ENOENT:
+                raise
+        if st:
+            if stat.S_ISDIR(st.st_mode):
+                try:
+                    os.rmdir(path)
+                except OSError, e:
+                    if e.errno == errno.ENOTEMPTY:
+                        msg = 'refusing to overwrite non-empty dir' + path
+                        raise Exception(msg)
+                    raise
+            else:
+                os.unlink(path)
+
         if stat.S_ISREG(self.mode):
             os.mknod(path, 0600 | stat.S_IFREG)
         elif stat.S_ISDIR(self.mode):
index efcfcba99b341b5e280a79ab6d32b9031ac784f8..b09a87e6f9c38af63c1485a558190f902e118046 100644 (file)
@@ -1,5 +1,6 @@
 import grp
 import pwd
+import stat
 import subprocess
 import tempfile
 from bup import metadata
@@ -168,3 +169,38 @@ def test_restore_nonexistent_user_group():
         WVPASSEQ(os.stat(path).st_uid, os.getgid())
     finally:
         subprocess.call(['rm', '-rf', tmpdir])
+
+
+@wvtest
+def test_restore_over_existing_target():
+    tmpdir = tempfile.mkdtemp(prefix='bup-tmetadata-')
+    try:
+        path = tmpdir + '/foo'
+        os.mkdir(path)
+        dir_m = metadata.from_path(path, archive_path=path, save_symlinks=True)
+        os.rmdir(path)
+        open(path, 'w').close()
+        file_m = metadata.from_path(path, archive_path=path, save_symlinks=True)
+        # Restore dir over file.
+        WVPASSEQ(dir_m.create_path(path, create_symlinks=True), None)
+        WVPASS(stat.S_ISDIR(os.stat(path).st_mode))
+        # Restore dir over dir.
+        WVPASSEQ(dir_m.create_path(path, create_symlinks=True), None)
+        WVPASS(stat.S_ISDIR(os.stat(path).st_mode))
+        # Restore file over dir.
+        WVPASSEQ(file_m.create_path(path, create_symlinks=True), None)
+        WVPASS(stat.S_ISREG(os.stat(path).st_mode))
+        # Restore file over file.
+        WVPASSEQ(file_m.create_path(path, create_symlinks=True), None)
+        WVPASS(stat.S_ISREG(os.stat(path).st_mode))
+        # Restore file over non-empty dir.
+        os.remove(path)
+        os.mkdir(path)
+        open(path + '/bar', 'w').close()
+        WVEXCEPT(Exception, file_m.create_path, path, create_symlinks=True)
+        # Restore dir over non-empty dir.
+        os.remove(path + '/bar')
+        os.mkdir(path + '/bar')
+        WVEXCEPT(Exception, dir_m.create_path, path, create_symlinks=True)
+    finally:
+        subprocess.call(['rm', '-rf', tmpdir])