summaryrefslogtreecommitdiff
path: root/rdiff-backup/rdiff_backup/restore.py
diff options
context:
space:
mode:
authorbescoto <bescoto@2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109>2002-12-23 06:53:18 +0000
committerbescoto <bescoto@2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109>2002-12-23 06:53:18 +0000
commit9a0da726e2172321cdc1dcd21441f4ffc41e7931 (patch)
tree7f25f848386ca501b7f08c08c21af16f0d71330c /rdiff-backup/rdiff_backup/restore.py
parente95a61773adb2f98499cf13ff543f4249ee38226 (diff)
downloadrdiff-backup-9a0da726e2172321cdc1dcd21441f4ffc41e7931.tar.gz
Major refactoring - avoid use of 'from XX import *' in favor of more
normal 'import XXX' syntax. The previous way was an artifact from earlier versions where the whole program fit in one file. git-svn-id: http://svn.savannah.nongnu.org/svn/rdiff-backup/trunk@252 2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109
Diffstat (limited to 'rdiff-backup/rdiff_backup/restore.py')
-rw-r--r--rdiff-backup/rdiff_backup/restore.py438
1 files changed, 216 insertions, 222 deletions
diff --git a/rdiff-backup/rdiff_backup/restore.py b/rdiff-backup/rdiff_backup/restore.py
index 9ca279e..40720a4 100644
--- a/rdiff-backup/rdiff_backup/restore.py
+++ b/rdiff-backup/rdiff_backup/restore.py
@@ -20,238 +20,237 @@
"""Read increment files and restore to original"""
from __future__ import generators
-import tempfile
-from static import *
+import tempfile, os
+from log import Log
+import Globals, Time, Rdiff, Hardlink, FilenameMapping, SetConnections, \
+ rorpiter, selection, destructive_stepping, rpath, lazy
class RestoreError(Exception): pass
-class Restore:
- def Restore(inc_rpath, mirror, target, rest_time):
- """Recursively restore inc_rpath and mirror to target at rest_time
+def Restore(inc_rpath, mirror, target, rest_time):
+ """Recursively restore inc_rpath and mirror to target at rest_time
- Like restore_recusive below, but with a more friendly
- interface (it converts to DSRPaths if necessary, finds the inc
- files with the appropriate base, and makes rid).
+ Like restore_recusive below, but with a more friendly
+ interface (it converts to DSRPaths if necessary, finds the inc
+ files with the appropriate base, and makes rid).
- rest_time is the time in seconds to restore to;
+ rest_time is the time in seconds to restore to;
- inc_rpath should not be the name of an increment file, but the
- increment file shorn of its suffixes and thus should have the
- same index as mirror.
+ inc_rpath should not be the name of an increment file, but the
+ increment file shorn of its suffixes and thus should have the
+ same index as mirror.
- """
- if not isinstance(target, DSRPath): target = DSRPath(None, target)
-
- mirror_time = Restore.get_mirror_time()
- rest_time = Restore.get_rest_time(rest_time, mirror_time)
- inc_list = Restore.get_inclist(inc_rpath)
- rid = RestoreIncrementData(inc_rpath.index, inc_rpath, inc_list)
- rid.sortincseq(rest_time, mirror_time)
- Restore.check_hardlinks(rest_time)
- Restore.restore_recursive(inc_rpath.index, mirror, rid, target,
- rest_time, mirror_time)
-
- def get_mirror_time():
- """Return the time (in seconds) of latest mirror"""
- current_mirror_incs = \
- Restore.get_inclist(Globals.rbdir.append("current_mirror"))
- if not current_mirror_incs:
- Log.FatalError("Could not get time of current mirror")
- elif len(current_mirror_incs) > 1:
- Log("Warning, two different dates for current mirror found", 2)
- return Time.stringtotime(current_mirror_incs[0].getinctime())
-
- def get_rest_time(old_rest_time, mirror_time):
- """If old_rest_time is between two increments, return older time
-
- There is a slightly tricky reason for doing this: The rest of
- the code just ignores increments that are older than
- rest_time. But sometimes we want to consider the very next
- increment older than rest time, because rest_time will be
- between two increments, and what was actually on the mirror
- side will correspond to the older one.
-
- So here we assume all rdiff-backup events were recorded in
- "increments" increments, and if its in-between we pick the
- older one here.
+ """
+ if not isinstance(target, destructive_stepping.DSRPath):
+ target = destructive_stepping.DSRPath(None, target)
+
+ mirror_time = get_mirror_time()
+ rest_time = get_rest_time(rest_time, mirror_time)
+ inc_list = get_inclist(inc_rpath)
+ rid = RestoreIncrementData(inc_rpath.index, inc_rpath, inc_list)
+ rid.sortincseq(rest_time, mirror_time)
+ check_hardlinks(rest_time)
+ restore_recursive(inc_rpath.index, mirror, rid, target,
+ rest_time, mirror_time)
+
+def get_mirror_time():
+ """Return the time (in seconds) of latest mirror"""
+ current_mirror_incs = get_inclist(Globals.rbdir.append("current_mirror"))
+ if not current_mirror_incs:
+ Log.FatalError("Could not get time of current mirror")
+ elif len(current_mirror_incs) > 1:
+ Log("Warning, two different dates for current mirror found", 2)
+ return Time.stringtotime(current_mirror_incs[0].getinctime())
+
+def get_rest_time(old_rest_time, mirror_time):
+ """If old_rest_time is between two increments, return older time
+
+ There is a slightly tricky reason for doing this: The rest of
+ the code just ignores increments that are older than
+ rest_time. But sometimes we want to consider the very next
+ increment older than rest time, because rest_time will be
+ between two increments, and what was actually on the mirror
+ side will correspond to the older one.
+
+ So here we assume all rdiff-backup events were recorded in
+ "increments" increments, and if its in-between we pick the
+ older one here.
- """
- base_incs = Restore.get_inclist(Globals.rbdir.append("increments"))
- if not base_incs: return old_rest_time
- inctimes = [Time.stringtotime(inc.getinctime()) for inc in base_incs]
- inctimes.append(mirror_time)
- older_times = filter(lambda time: time <= old_rest_time, inctimes)
- if older_times: return max(older_times)
- else: # restore time older than oldest increment, just return that
- return min(inctimes)
-
- def get_inclist(inc_rpath):
- """Returns increments with given base"""
- dirname, basename = inc_rpath.dirsplit()
- parent_dir = RPath(inc_rpath.conn, dirname, ())
- if not parent_dir.isdir(): return [] # inc directory not created yet
- index = inc_rpath.index
-
- if index:
- get_inc_ext = lambda filename: \
- RPath(inc_rpath.conn, inc_rpath.base,
- inc_rpath.index[:-1] + (filename,))
- else: get_inc_ext = lambda filename: \
- RPath(inc_rpath.conn, os.path.join(dirname, filename))
-
- inc_list = []
- for filename in parent_dir.listdir():
- inc = get_inc_ext(filename)
- if inc.isincfile() and inc.getincbase_str() == basename:
- inc_list.append(inc)
- return inc_list
-
- def check_hardlinks(rest_time):
- """Check for hard links and enable hard link support if found"""
- if (Globals.preserve_hardlinks != 0 and
- Hardlink.retrieve_final(rest_time)):
- Log("Hard link information found, attempting to preserve "
- "hard links.", 5)
- SetConnections.UpdateGlobal('preserve_hardlinks', 1)
- else: SetConnections.UpdateGlobal('preserve_hardlinks', None)
-
- def restore_recursive(index, mirror, rid, target, time, mirror_time):
- """Recursive restore function.
-
- rid is a RestoreIncrementData object whose inclist is already
- sortedincseq'd, and target is the dsrp to restore to.
-
- Note that target may have a different index than mirror and
- rid, because we may be restoring a file whose index is, say
- ('foo','bar') to a target whose path does not contain
- "foo/bar".
+ """
+ base_incs = get_inclist(Globals.rbdir.append("increments"))
+ if not base_incs: return old_rest_time
+ inctimes = [Time.stringtotime(inc.getinctime()) for inc in base_incs]
+ inctimes.append(mirror_time)
+ older_times = filter(lambda time: time <= old_rest_time, inctimes)
+ if older_times: return max(older_times)
+ else: # restore time older than oldest increment, just return that
+ return min(inctimes)
+
+def get_inclist(inc_rpath):
+ """Returns increments with given base"""
+ dirname, basename = inc_rpath.dirsplit()
+ parent_dir = rpath.RPath(inc_rpath.conn, dirname, ())
+ if not parent_dir.isdir(): return [] # inc directory not created yet
+ index = inc_rpath.index
+
+ if index:
+ get_inc_ext = lambda filename: \
+ rpath.RPath(inc_rpath.conn, inc_rpath.base,
+ inc_rpath.index[:-1] + (filename,))
+ else: get_inc_ext = lambda filename: \
+ rpath.RPath(inc_rpath.conn, os.path.join(dirname, filename))
+
+ inc_list = []
+ for filename in parent_dir.listdir():
+ inc = get_inc_ext(filename)
+ if inc.isincfile() and inc.getincbase_str() == basename:
+ inc_list.append(inc)
+ return inc_list
+
+def check_hardlinks(rest_time):
+ """Check for hard links and enable hard link support if found"""
+ if (Globals.preserve_hardlinks != 0 and
+ Hardlink.retrieve_final(rest_time)):
+ Log("Hard link information found, attempting to preserve "
+ "hard links.", 5)
+ SetConnections.UpdateGlobal('preserve_hardlinks', 1)
+ else: SetConnections.UpdateGlobal('preserve_hardlinks', None)
+
+def restore_recursive(index, mirror, rid, target, time, mirror_time):
+ """Recursive restore function.
+
+ rid is a RestoreIncrementData object whose inclist is already
+ sortedincseq'd, and target is the dsrp to restore to.
+
+ Note that target may have a different index than mirror and
+ rid, because we may be restoring a file whose index is, say
+ ('foo','bar') to a target whose path does not contain
+ "foo/bar".
- """
- assert isinstance(target, DSRPath)
- assert mirror.index == rid.index
+ """
+ assert isinstance(target, destructive_stepping.DSRPath)
+ assert mirror.index == rid.index
- target_finalizer = IterTreeReducer(DestructiveSteppingFinalizer, ())
- for rcd in Restore.yield_rcds(rid.index, mirror, rid,
- target, time, mirror_time):
- rcd.RestoreFile()
- #if rcd.mirror: mirror_finalizer(rcd.index, rcd.mirror)
- target_finalizer(rcd.target.index, rcd.target)
- target_finalizer.Finish()
+ target_finalizer = rorpiter.IterTreeReducer(
+ rorpiter.DestructiveSteppingFinalizer, ())
+ for rcd in yield_rcds(rid.index, mirror, rid, target, time, mirror_time):
+ rcd.RestoreFile()
+ #if rcd.mirror: mirror_finalizer(rcd.index, rcd.mirror)
+ target_finalizer(rcd.target.index, rcd.target)
+ target_finalizer.Finish()
- def yield_rcds(index, mirrorrp, rid, target, rest_time, mirror_time):
- """Iterate RestoreCombinedData objects starting with given args
+def yield_rcds(index, mirrorrp, rid, target, rest_time, mirror_time):
+ """Iterate RestoreCombinedData objects starting with given args
- rid is a RestoreCombinedData object. target is an rpath where
- the created file should go.
+ rid is a RestoreCombinedData object. target is an rpath where
+ the created file should go.
- In this case the "mirror" directory is treated as the source,
- and we are actually copying stuff onto what Select considers
- the source 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.
- """
- select_result = Globals.select_mirror.Select(target)
- if select_result == 0: return
+ """
+ select_result = Globals.select_mirror.Select(target)
+ if select_result == 0: return
+
+ if mirrorrp and not Globals.select_source.Select(mirrorrp):
+ mirrorrp = None
+ rcd = RestoreCombinedData(rid, mirrorrp, target)
+
+ if mirrorrp and mirrorrp.isdir() or \
+ rid and rid.inc_rpath and rid.inc_rpath.isdir():
+ sub_rcds = yield_sub_rcds(index, mirrorrp, rid,
+ target, rest_time, mirror_time)
+ else: sub_rcds = None
+
+ if select_result == 1:
+ yield rcd
+ if sub_rcds:
+ for sub_rcd in sub_rcds: yield sub_rcd
+ elif select_result == 2:
+ if sub_rcds:
+ try: first = sub_rcds.next()
+ except StopIteration: return # no tuples found inside, skip
+ yield rcd
+ yield first
+ for sub_rcd in sub_rcds: yield sub_rcd
+
+def yield_sub_rcds(index, mirrorrp, rid, target, rest_time, mirror_time):
+ """Yield collated tuples from inside given args"""
+ if not check_dir_exists(mirrorrp, rid): return
+ mirror_iter = yield_mirrorrps(mirrorrp)
+ rid_iter = yield_rids(rid, rest_time, mirror_time)
+
+ for indexed_tup in rorpiter.CollateIterators(mirror_iter, rid_iter):
+ index = indexed_tup.index
+ new_mirrorrp, new_rid = indexed_tup
+ for rcd in yield_rcds(index, new_mirrorrp, new_rid,
+ target.append(index[-1]), rest_time, mirror_time):
+ yield rcd
- if mirrorrp and not Globals.select_source.Select(mirrorrp):
- mirrorrp = None
- rcd = RestoreCombinedData(rid, mirrorrp, target)
+def check_dir_exists(mirrorrp, rid):
+ """Return true if target should be a directory"""
+ if rid and rid.inc_list:
+ # Incs say dir if last (earliest) one is a dir increment
+ return rid.inc_list[-1].getinctype() == "dir"
+ elif mirrorrp: return mirrorrp.isdir() # if no incs, copy mirror
+ else: return None
+
+def yield_mirrorrps(mirrorrp):
+ """Yield mirrorrps underneath given mirrorrp"""
+ if mirrorrp and mirrorrp.isdir():
+ if Globals.quoting_enabled:
+ for rp in selection.get_quoted_dir_children(mirrorrp):
+ yield rp
+ else:
+ dirlist = mirrorrp.listdir()
+ dirlist.sort()
+ for filename in dirlist: yield mirrorrp.append(filename)
- if mirrorrp and mirrorrp.isdir() or \
- rid and rid.inc_rpath and rid.inc_rpath.isdir():
- sub_rcds = Restore.yield_sub_rcds(index, mirrorrp, rid,
- target, rest_time, mirror_time)
- else: sub_rcds = None
+def yield_rids(rid, rest_time, mirror_time):
+ """Yield RestoreIncrementData objects within given rid dir
- if select_result == 1:
- yield rcd
- if sub_rcds:
- for sub_rcd in sub_rcds: yield sub_rcd
- elif select_result == 2:
- if sub_rcds:
- try: first = sub_rcds.next()
- except StopIteration: return # no tuples found inside, skip
- yield rcd
- yield first
- for sub_rcd in sub_rcds: yield sub_rcd
-
- def yield_sub_rcds(index, mirrorrp, rid, target, rest_time, mirror_time):
- """Yield collated tuples from inside given args"""
- if not Restore.check_dir_exists(mirrorrp, rid): return
- mirror_iter = Restore.yield_mirrorrps(mirrorrp)
- rid_iter = Restore.yield_rids(rid, rest_time, mirror_time)
-
- for indexed_tup in RORPIter.CollateIterators(mirror_iter, rid_iter):
- index = indexed_tup.index
- new_mirrorrp, new_rid = indexed_tup
- for rcd in Restore.yield_rcds(index, new_mirrorrp,
- new_rid, target.append(index[-1]), rest_time, mirror_time):
- yield rcd
-
- def check_dir_exists(mirrorrp, rid):
- """Return true if target should be a directory"""
- if rid and rid.inc_list:
- # Incs say dir if last (earliest) one is a dir increment
- return rid.inc_list[-1].getinctype() == "dir"
- elif mirrorrp: return mirrorrp.isdir() # if no incs, copy mirror
- else: return None
-
- def yield_mirrorrps(mirrorrp):
- """Yield mirrorrps underneath given mirrorrp"""
- if mirrorrp and mirrorrp.isdir():
- if Globals.quoting_enabled:
- for rp in FilenameMapping.get_quoted_dir_children(mirrorrp):
- yield rp
- else:
- dirlist = mirrorrp.listdir()
- dirlist.sort()
- for filename in dirlist: yield mirrorrp.append(filename)
-
- def yield_rids(rid, rest_time, mirror_time):
- """Yield RestoreIncrementData objects within given rid dir
-
- If the rid doesn't correspond to a directory, don't yield any
- elements. 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 the rid doesn't correspond to a directory, don't yield any
+ elements. 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 rid or not rid.inc_rpath or not rid.inc_rpath.isdir(): return
- rid_dict = {} # dictionary of basenames:rids
- dirlist = rid.inc_rpath.listdir()
- if Globals.quoting_enabled:
- dirlist = [FilenameMapping.unquote(fn) for fn in dirlist]
-
- def affirm_dict_indexed(basename):
- """Make sure the rid dictionary has given basename as key"""
- if not rid_dict.has_key(basename):
- rid_dict[basename] = RestoreIncrementData(
- rid.index + (basename,), None, []) # init with empty rid
-
- def add_to_dict(filename):
- """Add filename to the inc tuple dictionary"""
- rp = rid.inc_rpath.append(filename)
- if Globals.quoting_enabled: rp.quote_path()
- if rp.isincfile() and rp.getinctype() != 'data':
- basename = rp.getincbase_str()
- affirm_dict_indexed(basename)
- rid_dict[basename].inc_list.append(rp)
- elif rp.isdir():
- affirm_dict_indexed(filename)
- rid_dict[filename].inc_rpath = rp
-
- for filename in dirlist: add_to_dict(filename)
- keys = rid_dict.keys()
- keys.sort()
-
- # sortincseq now to avoid descending .missing directories later
- for key in keys:
- rid = rid_dict[key]
- if rid.inc_rpath or rid.inc_list:
- rid.sortincseq(rest_time, mirror_time)
- yield rid
-
-MakeStatic(Restore)
+ """
+ if not rid or not rid.inc_rpath or not rid.inc_rpath.isdir(): return
+ rid_dict = {} # dictionary of basenames:rids
+ dirlist = rid.inc_rpath.listdir()
+ if Globals.quoting_enabled:
+ dirlist = [FilenameMapping.unquote(fn) for fn in dirlist]
+
+ def affirm_dict_indexed(basename):
+ """Make sure the rid dictionary has given basename as key"""
+ if not rid_dict.has_key(basename):
+ rid_dict[basename] = RestoreIncrementData(
+ rid.index + (basename,), None, []) # init with empty rid
+
+ def add_to_dict(filename):
+ """Add filename to the inc tuple dictionary"""
+ rp = rid.inc_rpath.append(filename)
+ if Globals.quoting_enabled: rp.quote_path()
+ if rp.isincfile() and rp.getinctype() != 'data':
+ basename = rp.getincbase_str()
+ affirm_dict_indexed(basename)
+ rid_dict[basename].inc_list.append(rp)
+ elif rp.isdir():
+ affirm_dict_indexed(filename)
+ rid_dict[filename].inc_rpath = rp
+
+ for filename in dirlist: add_to_dict(filename)
+ keys = rid_dict.keys()
+ keys.sort()
+
+ # sortincseq now to avoid descending .missing directories later
+ for key in keys:
+ rid = rid_dict[key]
+ if rid.inc_rpath or rid.inc_list:
+ rid.sortincseq(rest_time, mirror_time)
+ yield rid
class RestoreIncrementData:
@@ -339,7 +338,7 @@ class RestoreCombinedData:
if not self.inc_list or self.inc_list[0].getinctype() == "diff":
assert self.mirror and self.mirror.lstat(), \
"No base to go with incs for %s" % self.target.path
- RPath.copy_with_attribs(self.mirror, self.target)
+ rpath.copy_with_attribs(self.mirror, self.target)
for inc in self.inc_list: self.applyinc(inc, self.target)
def log(self):
@@ -353,7 +352,7 @@ class RestoreCombinedData:
"""Hard link target and return true if hard linking appropriate"""
if (Globals.preserve_hardlinks and
Hardlink.restore_link(self.index, self.target)):
- RPath.copy_attribs(self.inc_list and self.inc_list[-1] or
+ rpath.copy_attribs(self.inc_list and self.inc_list[-1] or
self.mirror, self.target)
return 1
return None
@@ -377,13 +376,8 @@ class RestoreCombinedData:
elif inctype == "snapshot":
if inc.isinccompressed():
target.write_from_fileobj(inc.open("rb", compress = 1))
- else: RPath.copy(inc, target)
+ else: rpath.copy(inc, target)
else: raise RestoreError("Unknown inctype %s" % inctype)
- RPath.copy_attribs(inc, target)
+ rpath.copy_attribs(inc, target)
-from log import *
-from destructive_stepping import *
-from rpath import *
-from rorpiter import *
-import Globals, Time, Rdiff, Hardlink, FilenameMapping, SetConnections