diff options
author | bescoto <bescoto@2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109> | 2003-08-24 03:39:56 +0000 |
---|---|---|
committer | bescoto <bescoto@2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109> | 2003-08-24 03:39:56 +0000 |
commit | 6a48fc6c34e3d2f8fcaf791a847aebb6854557e7 (patch) | |
tree | dfd7331259298750b49f7493ba52219acd647164 | |
parent | 94da66c4015094e2c5a71e945ef3562644543c0f (diff) | |
download | rdiff-backup-6a48fc6c34e3d2f8fcaf791a847aebb6854557e7.tar.gz |
When data gets deleted from dest, try not to exit as easily
git-svn-id: http://svn.savannah.nongnu.org/svn/rdiff-backup/trunk@401 2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109
-rw-r--r-- | rdiff-backup/CHANGELOG | 4 | ||||
-rw-r--r-- | rdiff-backup/rdiff_backup/Main.py | 4 | ||||
-rw-r--r-- | rdiff-backup/rdiff_backup/restore.py | 33 | ||||
-rw-r--r-- | rdiff-backup/testing/finaltest.py | 45 |
4 files changed, 78 insertions, 8 deletions
diff --git a/rdiff-backup/CHANGELOG b/rdiff-backup/CHANGELOG index 71c1e07..02c093c 100644 --- a/rdiff-backup/CHANGELOG +++ b/rdiff-backup/CHANGELOG @@ -8,6 +8,10 @@ Fixed bug backing up unreadable regular files when rdiff-backup is run by root on the source site and non-root on the destination side. (Reported by Troels Arvin and Arkadiusz Miskiewicz.) +If there is data missing from the destination dir (for instance if a +user mistakenly deletes it), only warn when restoring, instead of +exiting with error. + New in v0.13.1 (2003/08/08) --------------------------- diff --git a/rdiff-backup/rdiff_backup/Main.py b/rdiff-backup/rdiff_backup/Main.py index 638f137..f9cb252 100644 --- a/rdiff-backup/rdiff_backup/Main.py +++ b/rdiff-backup/rdiff_backup/Main.py @@ -571,7 +571,7 @@ def CalculateAverage(rps): def RemoveOlderThan(rootrp): """Remove all increment files older than a certain time""" - rom_check_dir(rootrp) + rot_check_dir(rootrp) try: time = Time.genstrtotime(remove_older_than_string) except Time.TimeException, exc: Log.FatalError(str(exc)) timep = Time.timetopretty(time) @@ -596,7 +596,7 @@ def RemoveOlderThan(rootrp): else: Log("Deleting increments at times:\n" + inc_pretty_time, 3) manage.delete_earlier_than(Globals.rbdir, time) -def rom_check_dir(rootrp): +def rot_check_dir(rootrp): """Check destination dir before RemoveOlderThan""" SetConnections.UpdateGlobal('rbdir', rootrp.append_path("rdiff-backup-data")) diff --git a/rdiff-backup/rdiff_backup/restore.py b/rdiff-backup/rdiff_backup/restore.py index 7094a3b..f4add16 100644 --- a/rdiff-backup/rdiff_backup/restore.py +++ b/rdiff-backup/rdiff_backup/restore.py @@ -289,28 +289,43 @@ class CachedRF: return "\n".join((s1, s2, s3)) def get_rf(self, index): - """Return RestoreFile of given index""" + """Return RestoreFile of given index, or None""" while 1: - if not self.rf_list: self.add_rfs(index) + if not self.rf_list: + if not self.add_rfs(index): return None rf = self.rf_list.pop(0) if rf.index < index: continue elif rf.index == index: return rf self.rf_list.insert(0, rf) - self.add_rfs(index) + if not self.add_rfs(index): return None def get_fp(self, index): """Return the file object (for reading) of given index""" + rf = self.get_rf(index) + if not rf: + log.Log("""Error: Unable to retrieve data for file %s! +The cause is probably data loss from the destination directory.""" % + (index and "/".join(index) or '.',), 2) + return cStringIO.StringIO('') return self.get_rf(index).get_restore_fp() def add_rfs(self, index): - """Given index, add the rfs in that same directory""" + """Given index, add the rfs in that same directory + + Returns false if no rfs are available, which usually indicates + an error. + + """ if not index: return self.root_rf parent_index = index[:-1] temp_rf = RestoreFile(self.root_rf.mirror_rp.new_index(parent_index), self.root_rf.inc_rp.new_index(parent_index), []) new_rfs = list(temp_rf.yield_sub_rfs()) - assert new_rfs, "No RFs added for index %s" % index + if not new_rfs: + log.Log("Warning: No RFs added for index %s" % (index,), 2) + return 0 self.rf_list[0:0] = new_rfs + return 1 class RestoreFile: @@ -434,7 +449,13 @@ rdiff-backup destination directory, or a bug in rdiff-backup""" % def yield_sub_rfs(self): """Return RestoreFiles under current RestoreFile (which is dir)""" - assert self.mirror_rp.isdir() or self.inc_rp.isdir() + if not self.mirror_rp.isdir() and not self.inc_rp.isdir(): + log.Log("""Warning: directory %s seems to be missing from backup! + +This is probably due to files being deleted manually from the +rdiff-backup destination directory. In general you shouldn't do this, +as data loss may result.\n""" % (self.mirror_rp.get_indexpath(),), 2) + return if self.mirror_rp.isdir(): mirror_iter = self.yield_mirrorrps(self.mirror_rp) else: mirror_iter = iter([]) diff --git a/rdiff-backup/testing/finaltest.py b/rdiff-backup/testing/finaltest.py index 593570f..4f1caf9 100644 --- a/rdiff-backup/testing/finaltest.py +++ b/rdiff-backup/testing/finaltest.py @@ -471,5 +471,50 @@ testfiles/increment2/changed_dir""") self.assertRaises(OSError, os.lstat, 'testfiles/restoretarget1/executable2') + +class FinalCorrupt(PathSetter): + """Test messing with things a bit and making sure they still work""" + def make_dir(self): + self.delete_tmpdirs() + rp1 = rpath.RPath(Globals.local_connection, 'testfiles/final_deleted1') + if rp1.lstat(): Myrm(rp1.path) + rp1.mkdir() + rp1_1 = rp1.append('regfile') + rp1_1.touch() + rp1_2 = rp1.append('dir') + rp1_2.mkdir() + rp1_2_1 = rp1_2.append('regfile2') + rp1_2_1.write_string('foo') + + rp2 = rpath.RPath(Globals.local_connection, 'testfiles/final_deleted2') + if rp2.lstat(): Myrm(rp2.path) + os.system('cp -a %s %s' % (rp1.path, rp2.path)) + rp2_2_1 = rp2.append('dir').append('regfile2') + assert rp2_2_1.lstat() + rp2_2_1.delete() + rp2_2_1.touch() + return rp1, rp1_2, rp2 + + def test_dest_delete(self): + """Test deleting a directory from the destination dir + + Obviously that directory can no longer be restored, but the + rest of the files should be OK. Just runs locally for now. + + """ + in_dir1, in_subdir, in_dir2 = self.make_dir() + self.set_connections(None, None, None, None) + self.exec_rb(10000, in_dir1.path, 'testfiles/output') + + out_subdir = rpath.RPath(Globals.local_connection, + 'testfiles/output/%s' % + (in_subdir.index[-1],)) + log.Log("Deleting %s" % (out_subdir.path,), 3) + out_subdir.delete() + self.exec_rb(20000, in_dir2.path, 'testfiles/output') + + self.exec_rb_restore(10000, 'testfiles/output', + 'testfiles/restoretarget1') + if __name__ == "__main__": unittest.main() |