Commit b9949a62 authored by bescoto's avatar bescoto

Fixes for --compare, --compare-at-time switches


git-svn-id: http://svn.savannah.nongnu.org/svn/rdiff-backup@513 2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109
parent f6505e4b
......@@ -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).
......
# 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):
......
# 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:
......
# 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):
......
......@@ -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"""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment