diff options
-rw-r--r-- | rdiff-backup/CHANGELOG | 4 | ||||
-rw-r--r-- | rdiff-backup/rdiff_backup/Main.py | 13 | ||||
-rw-r--r-- | rdiff-backup/rdiff_backup/restore.py | 18 | ||||
-rw-r--r-- | rdiff-backup/rdiff_backup/rpath.py | 21 | ||||
-rw-r--r-- | rdiff-backup/testing/finaltest.py | 46 |
5 files changed, 71 insertions, 31 deletions
diff --git a/rdiff-backup/CHANGELOG b/rdiff-backup/CHANGELOG index 8871415..d468dc2 100644 --- a/rdiff-backup/CHANGELOG +++ b/rdiff-backup/CHANGELOG @@ -11,6 +11,10 @@ information. As John says: > * dual integer location Much thanks to John for adding this useful feature all by himself! +Added --compare and --compare-at-time switches for comparing a +directory with the backup information saved about it. Thanks to Erik +Forsberg, who noticed that this feature was missing. + Regressing and restoring should now take less memory when processing large directories (noticed by Luke Mewburn and others). diff --git a/rdiff-backup/rdiff_backup/Main.py b/rdiff-backup/rdiff_backup/Main.py index 1177296..b25f1ad 100644 --- a/rdiff-backup/rdiff_backup/Main.py +++ b/rdiff-backup/rdiff_backup/Main.py @@ -1,4 +1,4 @@ -# Copyright 2002, 2003 Ben Escoto +# Copyright 2002, 2003, 2004 Ben Escoto # # This file is part of rdiff-backup. # @@ -36,6 +36,7 @@ user_mapping_filename, group_mapping_filename = None, None # These are global because they are set while we are trying to figure # whether to restore or to backup restore_root, restore_index, restore_root_set = None, None, 0 +return_val = None # Set to cause exit code to be specified value def parse_cmdlineoptions(arglist): """Parse argument list and set global preferences""" @@ -188,7 +189,7 @@ def final_set_action(rps): def commandline_error(message): sys.stderr.write("Error: %s\n" % message) sys.stderr.write("See the rdiff-backup manual page for instructions\n") - sys.exit(1) + sys.exit(2) def misc_setup(rps): """Set default change ownership flag, umask, relay regexps""" @@ -253,6 +254,7 @@ def Main(arglist): misc_setup(rps) take_action(rps) cleanup() + if return_val is not None: sys.exit(return_val) def Backup(rpin, rpout): @@ -732,17 +734,18 @@ def Compare(src_rp, dest_rp, compare_time = None): Session time is read from restore_timestr if compare_time is None. """ + global return_val require_root_set(dest_rp) if not compare_time: - try: compare_time = Time.getstrtotime(restore_timestr) + try: compare_time = Time.genstrtotime(restore_timestr) except Time.TimeException, exc: Log.FatalError(str(exc)) restore_check_backup_dir(restore_root) mirror_rp = restore_root.new_index(restore_index) inc_rp = mirror_rp.append_path("increments", restore_index) backup_set_select(src_rp) # Sets source rorp iterator - restore.Compare(src_rp.conn.backup.SourceStruct.get_source_select(), - src_iter, mirror_rp, inc_rp, compare_time) + src_iter = src_rp.conn.backup.SourceStruct.get_source_select() + return_val = restore.Compare(src_iter, mirror_rp, inc_rp, compare_time) def CheckDest(dest_rp): diff --git a/rdiff-backup/rdiff_backup/restore.py b/rdiff-backup/rdiff_backup/restore.py index af097b1..1c1d1cc 100644 --- a/rdiff-backup/rdiff_backup/restore.py +++ b/rdiff-backup/rdiff_backup/restore.py @@ -1,4 +1,4 @@ -# Copyright 2002, 2003 Ben Escoto +# Copyright 2002, 2003, 2004 Ben Escoto # # This file is part of rdiff-backup. # @@ -106,18 +106,22 @@ def Compare(src_iter, mirror_rp, inc_rp, compare_time): mir_iter = MirrorStruct.get_mirror_rorp_iter(compare_time, 1) collated = rorpiter.Collate2Iters(src_iter, mir_iter) changed_files_found = 0 - for src_rorp, mir_rorp in collated: - if src_rorp == mir_rorp: continue - changed_files_found = 1 + for src_rorp, mir_rorp in collated: if not mir_rorp: change = "new" elif not src_rorp: change = "deleted" + elif src_rorp == mir_rorp: continue else: change = "changed" + changed_files_found = 1 path_desc = (src_rorp and src_rorp.get_indexpath() or mir_rorp.get_indexpath()) - Log("%-7s %s" % (change, path_desc), 3) - if not changed_file_found: - Log("No changes found. Directory matches archive data.", 3) + log.Log("%-7s %s" % (change, path_desc), 2) + if change == "changed": # Log more description of difference + assert not src_rorp.equal_verbose_auto(mir_rorp, 3) + + if not changed_files_found: + log.Log("No changes found. Directory matches archive data.", 2) MirrorStruct.close_rf_cache() + return changed_files_found class MirrorStruct: diff --git a/rdiff-backup/rdiff_backup/rpath.py b/rdiff-backup/rdiff_backup/rpath.py index ef38402..e1228e9 100644 --- a/rdiff-backup/rdiff_backup/rpath.py +++ b/rdiff-backup/rdiff_backup/rpath.py @@ -1,4 +1,4 @@ -# Copyright 2002, 2003 Ben Escoto +# Copyright 2002, 2003, 2004 Ben Escoto # # This file is part of rdiff-backup. # @@ -352,10 +352,11 @@ class RORPath: def equal_verbose(self, other, check_index = 1, compare_inodes = 0, compare_ownership = 0, - compare_acls = 0, compare_eas = 0): + compare_acls = 0, compare_eas = 0, verbosity = 2): """Like __eq__, but log more information. Useful when testing""" if check_index and self.index != other.index: - log.Log("Index %s != index %s" % (self.index, other.index), 2) + log.Log("Index %s != index %s" % (self.index, other.index), + verbosity) return None for key in self.data.keys(): # compare dicts key by key @@ -374,12 +375,22 @@ class RORPath: elif (not other.data.has_key(key) or self.data[key] != other.data[key]): if not other.data.has_key(key): - log.Log("Second is missing key %s" % (key,), 2) + log.Log("Second is missing key %s" % (key,), verbosity) else: log.Log("Value of %s differs: %s vs %s" % - (key, self.data[key], other.data[key]), 2) + (key, self.data[key], other.data[key]), + verbosity) return None return 1 + def equal_verbose_auto(self, other, verbosity = 2): + """Like equal_verbose, but set parameters like __eq__ does""" + compare_inodes = ((self.getnumlinks() != 1) and + Globals.compare_inode and Globals.preserve_hardlinks) + return self.equal_verbose(other, + compare_inodes = compare_inodes, + compare_eas = Globals.eas_active, + compare_acls = Globals.acls_active) + def __ne__(self, other): return not self.__eq__(other) def __str__(self): diff --git a/rdiff-backup/testing/finaltest.py b/rdiff-backup/testing/finaltest.py index 26ff171..ffe175c 100644 --- a/rdiff-backup/testing/finaltest.py +++ b/rdiff-backup/testing/finaltest.py @@ -64,20 +64,18 @@ class PathSetter(unittest.TestCase): def exec_rb(self, time, *args): """Run rdiff-backup on given arguments""" - arglist = [] - if time: arglist.extend(["--current-time", str(time)]) - arglist.append(self.src_prefix + args[0]) - if len(args) > 1: - arglist.append(self.dest_prefix + args[1]) - assert len(args) == 2 - - argstring = ' '.join(map(lambda s: "'%s'" % (s,), arglist)) - cmdstr = self.rb_schema + argstring - print "executing " + cmdstr - assert not os.system(cmdstr) + self.exec_rb_extra_args(time, '', *args) def exec_rb_extra_args(self, time, extra_args, *args): - """Run rdiff-backup on given arguments""" + self.exec_rb_extra_args_retval(time, extra_args, 0, *args) + + def exec_rb_extra_args_retval(self, time, extra_args, ret_val, *args): + """Like exec_rb_extra_args, but require return val to be ret_val + + Because of some problems I have with os.system, return val is + only accurate to 0 or non-zero. + + """ arglist = [] if time: arglist.extend(["--current-time", str(time)]) arglist.append(self.src_prefix + args[0]) @@ -85,9 +83,13 @@ class PathSetter(unittest.TestCase): arglist.append(self.dest_prefix + args[1]) assert len(args) == 2 - cmdstr = "%s %s %s" % (self.rb_schema, extra_args, ' '.join(arglist)) + arg_string = ' '.join(map(lambda s: "'%s'" % (s,), arglist)) + cmdstr = "%s %s %s" % (self.rb_schema, extra_args, arg_string) print "executing " + cmdstr - assert not os.system(cmdstr) + actual_val = os.system(cmdstr) + assert ((actual_val == 0 and ret_val == 0) or + (actual_val > 0 and ret_val > 0)), \ + "Bad return val %s" % (actual_val,) def exec_rb_restore(self, time, *args): """Restore using rdiff-backup's new syntax and given time""" @@ -417,6 +419,22 @@ class FinalMisc(PathSetter): for inc in self.get_all_increments(rbdir): assert inc.getinctime() >= 30000 + def testCompare(self): + """Test --compare and --compare-older-than modes""" + Myrm("testfiles/output") + self.set_connections(None, None, None, None) + self.exec_rb(10000, 'testfiles/increment1', 'testfiles/output') + self.exec_rb(20000, 'testfiles/increment2', 'testfiles/output') + + self.exec_rb_extra_args_retval(20000, '--compare', 0, + 'testfiles/increment2', 'testfiles/output') + self.exec_rb_extra_args_retval(20000, '--compare', 1, + 'testfiles/increment1', 'testfiles/output') + self.exec_rb_extra_args_retval(20000, '--compare-at-time 10000', 1, + 'testfiles/increment2', 'testfiles/output') + self.exec_rb_extra_args_retval(20000, '--compare-at-time 10000', 0, + 'testfiles/increment1', 'testfiles/output') + class FinalSelection(PathSetter): """Test selection options""" |