diff options
author | ben <ben@2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109> | 2002-04-30 02:02:56 +0000 |
---|---|---|
committer | ben <ben@2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109> | 2002-04-30 02:02:56 +0000 |
commit | d49f6dccf43983b317d31aa49b7e9a54aa28bf01 (patch) | |
tree | 1986d43b549551e12b60b6c03251061eae7bf433 /rdiff-backup/rdiff_backup/restore.py | |
parent | ef22311017db214255b24f93de2a43d75f9d45cc (diff) | |
download | rdiff-backup-d49f6dccf43983b317d31aa49b7e9a54aa28bf01.tar.gz |
Changed for 0.7.3 release
git-svn-id: http://svn.savannah.nongnu.org/svn/rdiff-backup/trunk@48 2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109
Diffstat (limited to 'rdiff-backup/rdiff_backup/restore.py')
-rw-r--r-- | rdiff-backup/rdiff_backup/restore.py | 137 |
1 files changed, 100 insertions, 37 deletions
diff --git a/rdiff-backup/rdiff_backup/restore.py b/rdiff-backup/rdiff_backup/restore.py index 0e0d62e..6e51b81 100644 --- a/rdiff-backup/rdiff_backup/restore.py +++ b/rdiff-backup/rdiff_backup/restore.py @@ -20,7 +20,6 @@ class Restore: and rptarget is the rpath that will be written with the restored file. """ - inclist = Restore.sortincseq(rest_time, inclist) if not inclist and not (rpbase and rpbase.lstat()): return # no increments were applicable Log("Restoring %s with increments %s to %s" % @@ -58,7 +57,7 @@ class Restore: i = i+1 incpairs = incpairs[:i+1] - # Return increments in reversed order + # Return increments in reversed order (latest first) incpairs.reverse() return map(lambda pair: pair[1], incpairs) @@ -106,44 +105,106 @@ class Restore: """ assert isinstance(target_base, DSRPath) - collated = RORPIter.CollateIterators( - DestructiveStepping.Iterate_from(mirror_base, None), - Restore.yield_inc_tuples(baseinc_tup)) + baseinc_tup = IndexedTuple(baseinc_tup.index, (baseinc_tup[0], + Restore.sortincseq(rest_time, baseinc_tup[1]))) + + collated = Restore.yield_collated_tuples((), mirror_base, + baseinc_tup, target_base, rest_time) mirror_finalizer = DestructiveStepping.Finalizer() target_finalizer = DestructiveStepping.Finalizer() - for mirror, inc_tup in collated: - if not inc_tup: - inclist = [] - target = target_base.new_index(mirror.index) - else: - inclist = inc_tup[1] - target = target_base.new_index(inc_tup.index) + for mirror, inc_tup, target in collated: + inclist = inc_tup and inc_tup[1] or [] DestructiveStepping.initialize(target, None) Restore.RestoreFile(rest_time, mirror, mirror_rel_index, inclist, target) target_finalizer(target) if mirror: mirror_finalizer(mirror) target_finalizer.getresult() - mirror_finalizer.getresult() + mirror_finalizer.getresult() + + def yield_collated_tuples(index, mirrorrp, inc_tup, target, rest_time): + """Iterate collated tuples starting with given args - def yield_inc_tuples(inc_tuple): - """Iterate increment tuples starting with inc_tuple + A collated tuple is an IndexedTuple (mirrorrp, inc_tuple, target). + inc_tuple is itself an IndexedTuple. target is an rpath where + the created file should go. - An increment tuple is an IndexedTuple (pair). The first will - be the rpath of a directory, and the second is a list of all - the increments associated with that directory. If there are - increments that do not correspond to a directory, the first - element will be None. All the rpaths involved correspond to - files in the increment directory. + In this case the "mirror" directory is treated as the source, + and we are actually copying stuff onto what Select considers + the source directory. """ - oldindex, rpath = inc_tuple.index, inc_tuple[0] - yield inc_tuple - if not rpath or not rpath.isdir(): return + select_result = Globals.select_mirror.Select(target) + if select_result == 0: return + + inc_base = inc_tup and inc_tup[0] + if mirrorrp and (not Globals.select_source.Select(mirrorrp) or + DestructiveStepping.initialize(mirrorrp, None)): + mirrorrp = None + collated_tuple = IndexedTuple(index, (mirrorrp, inc_tup, target)) + if mirrorrp and mirrorrp.isdir() or inc_base and inc_base.isdir(): + depth_tuples = Restore.yield_collated_tuples_dir(index, mirrorrp, + inc_tup, target, rest_time) + else: depth_tuples = None + + if select_result == 1: + yield collated_tuple + if depth_tuples: + for tup in depth_tuples: yield tup + elif select_result == 2: + if depth_tuples: + try: first = depth_tuples.next() + except StopIteration: return # no tuples found inside, skip + yield collated_tuple + yield first + for tup in depth_tuples: yield tup + + def yield_collated_tuples_dir(index, mirrorrp, inc_tup, target, rest_time): + """Yield collated tuples from inside given args""" + if not Restore.check_dir_exists(mirrorrp, inc_tup): return + if mirrorrp and mirrorrp.isdir(): + dirlist = mirrorrp.listdir() + dirlist.sort() + mirror_list = map(lambda x: IndexedTuple(x, (mirrorrp.append(x),)), + dirlist) + else: mirror_list = [] + inc_list = Restore.get_inc_tuples(inc_tup, rest_time) + + for indexed_tup in RORPIter.CollateIterators(iter(mirror_list), + iter(inc_list)): + filename = indexed_tup.index + new_inc_tup = indexed_tup[1] + new_mirrorrp = indexed_tup[0] and indexed_tup[0][0] + for new_col_tup in Restore.yield_collated_tuples( + index + (filename,), new_mirrorrp, new_inc_tup, + target.append(filename), rest_time): yield new_col_tup + + def check_dir_exists(mirrorrp, inc_tuple): + """Return true if target should be a directory""" + if inc_tuple and inc_tuple[1]: + # Incs say dir if last (earliest) one is a dir increment + return inc_tuple[1][-1].getinctype() == "dir" + elif mirrorrp: return mirrorrp.isdir() # if no incs, copy mirror + else: return None + + def get_inc_tuples(inc_tuple, rest_time): + """Return list of inc tuples in given rpath of increment directory + + An increment tuple is an IndexedTuple (pair). The second + element in the pair is a list of increments with the same + base. The first element is the rpath of the corresponding + base. Usually this base is a directory, otherwise it is + ignored. If there are increments whose corresponding base + doesn't exist, the first element will be None. All the rpaths + involved correspond to files in the increment directory. + """ + if not inc_tuple: return [] + oldindex, incdir = inc_tuple.index, inc_tuple[0] + if not incdir.isdir(): return [] inc_list_dict = {} # Index tuple lists by index - dirlist = rpath.listdir() + dirlist = incdir.listdir() def affirm_dict_indexed(index): """Make sure the inc_list_dict has given index""" @@ -152,7 +213,7 @@ class Restore: def add_to_dict(filename): """Add filename to the inc tuple dictionary""" - rp = rpath.append(filename) + rp = incdir.append(filename) if rp.isincfile(): basename = rp.getincbase_str() affirm_dict_indexed(basename) @@ -161,20 +222,22 @@ class Restore: affirm_dict_indexed(filename) inc_list_dict[filename][0] = rp - def list2tuple(index): - """Return inc_tuple version of dictionary entry by index""" - inclist = inc_list_dict[index] - if not inclist[1]: return None # no increments, so ignore - return IndexedTuple(oldindex + (index,), inclist) + def index2tuple(index): + """Return inc_tuple version of dictionary entry by index + + Also runs sortincseq to sort the increments and remove + irrelevant ones. This is done here so we can avoid + descending into .missing directories. + + """ + incbase, inclist = inc_list_dict[index] + inclist = Restore.sortincseq(rest_time, inclist) + if not inclist: return None # no relevant increments, so ignore + return IndexedTuple(index, (incbase, inclist)) for filename in dirlist: add_to_dict(filename) keys = inc_list_dict.keys() keys.sort() - for index in keys: - new_inc_tuple = list2tuple(index) - if not new_inc_tuple: continue - elif new_inc_tuple[0]: # corresponds to directory - for i in Restore.yield_inc_tuples(new_inc_tuple): yield i - else: yield new_inc_tuple + return filter(lambda x: x, map(index2tuple, keys)) MakeStatic(Restore) |