summaryrefslogtreecommitdiff
path: root/rdiff-backup/rdiff_backup/selection.py
diff options
context:
space:
mode:
Diffstat (limited to 'rdiff-backup/rdiff_backup/selection.py')
-rw-r--r--rdiff-backup/rdiff_backup/selection.py96
1 files changed, 95 insertions, 1 deletions
diff --git a/rdiff-backup/rdiff_backup/selection.py b/rdiff-backup/rdiff_backup/selection.py
index 0fcc657..29b12e8 100644
--- a/rdiff-backup/rdiff_backup/selection.py
+++ b/rdiff-backup/rdiff_backup/selection.py
@@ -26,7 +26,7 @@ documentation on what this code does can be found on the man page.
from __future__ import generators
import re
-import FilenameMapping, robust, rpath, Globals, log
+import FilenameMapping, robust, rpath, Globals, log, rorpiter
class SelectError(Exception):
@@ -195,6 +195,18 @@ class Select:
for rp in rec_func(new_rp, rec_func, sel_func):
yield rp
+ def FilterIter(self, rorp_iter):
+ """Filter rorp_iter using Select below, removing excluded rorps"""
+ def getrpiter(rorp_iter):
+ """Return rp iter by adding indicies of rorp_iter to self.rpath"""
+ for rorp in rorp_iter:
+ yield rpath.RPath(self.rpath.conn, self.rpath.base,
+ rorp.index, rorp.data)
+
+ ITR = rorpiter.IterTreeReducer(FilterIterITRB, [self])
+ for rp in rp_iter: ITR(rp.index, rp)
+ ITR.Finish()
+
def Select(self, rp):
"""Run through the selection functions and return dominant val 0/1/2"""
for sf in self.selection_functions:
@@ -606,4 +618,86 @@ probably isn't what you meant.""" %
return res
+class FilterIter:
+ """Filter rorp_iter using a Select object, removing excluded rorps"""
+ def __init__(self, select, rorp_iter):
+ """Constructor
+
+ Input is the Select object to use and the iter of rorps to be
+ filtered. The rorps will be converted to rps using the Select
+ base.
+
+ """
+ self.rorp_iter = rorp_iter
+ self.base_rp = select.rpath
+ self.stored_rorps = []
+ self.ITR = rorpiter.IterTreeReducer(FilterIterITRB,
+ [select.Select, self.stored_rorps])
+ self.itr_finished = 0
+
+ def __iter__(self): return self
+
+ def next(self):
+ """Return next object, or StopIteration"""
+ while not self.stored_rorps:
+ try: next_rorp = self.rorp_iter.next()
+ except StopIteration:
+ if self.itr_finished: raise
+ else:
+ self.ITR.Finish()
+ self.itr_finished = 1
+ else:
+ next_rp = rpath.RPath(self.base_rp.conn, self.base_rp.base,
+ next_rorp.index, next_rorp.data)
+ self.ITR(next_rorp.index, next_rp, next_rorp)
+ return self.stored_rorps.pop(0)
+
+class FilterIterITRB(rorpiter.ITRBranch):
+ """ITRBranch used in above FilterIter class
+
+ The reason this is necessary is because for directories sometimes
+ we don't know whether a rorp is excluded until we see what is in
+ the directory.
+
+ """
+ def __init__(self, select, rorp_cache):
+ """Initialize FilterIterITRB. Called by IterTreeReducer.
+
+ select should be the relevant Select object used to test the
+ rps. rorp_cache is the list rps should be appended to if they
+ aren't excluded.
+
+ """
+ self.select, self.rorp_cache = select, rorp_cache
+ self.branch_excluded = None
+ self.base_queue = None # holds branch base while examining contents
+
+ def can_fast_process(self, index, next_rp, next_rorp):
+ return not next_rp.isdir()
+
+ def fast_process(self, index, next_rp, next_rorp):
+ """For ordinary files, just append if select is positive"""
+ if self.branch_excluded: return
+ s = self.select(next_rp)
+ if s == 1:
+ if self.base_queue:
+ self.rorp_cache.append(self.base_queue)
+ self.base_queue = None
+ self.rorp_cache.append(next_rorp)
+ else: assert s == 0, "Unexpected select value %s" % (s,)
+
+ def start_process(self, index, next_rp, next_rorp):
+ s = self.select(next_rp)
+ if s == 0: self.branch_excluded = 1
+ elif s == 1: self.rorp_cache.append(next_rorp)
+ else:
+ assert s == 2, s
+ self.base_queue = next_rorp
+
+
+
+
+
+
+