summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbescoto <bescoto@2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109>2003-11-24 00:21:50 +0000
committerbescoto <bescoto@2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109>2003-11-24 00:21:50 +0000
commit33ebc912eaf524abbb30952ab8a601502ed53674 (patch)
tree02d99e6318bca4d13c2614531a2b0f6f8f038456
parent8c16d0e2c767afb0d67fdf05a687197e4370f82f (diff)
downloadrdiff-backup-33ebc912eaf524abbb30952ab8a601502ed53674.tar.gz
Added restore selection file fix
git-svn-id: http://svn.savannah.nongnu.org/svn/rdiff-backup/branches/r0-12@500 2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109
-rw-r--r--rdiff-backup/CHANGELOG9
-rw-r--r--rdiff-backup/rdiff-backup.17
-rw-r--r--rdiff-backup/rdiff_backup/Main.py22
-rw-r--r--rdiff-backup/rdiff_backup/restore.py16
-rw-r--r--rdiff-backup/rdiff_backup/selection.py7
-rw-r--r--rdiff-backup/testing/finaltest.py57
6 files changed, 95 insertions, 23 deletions
diff --git a/rdiff-backup/CHANGELOG b/rdiff-backup/CHANGELOG
index f3faca6..34cfb9c 100644
--- a/rdiff-backup/CHANGELOG
+++ b/rdiff-backup/CHANGELOG
@@ -1,3 +1,12 @@
+New in v0.12.7 (??????????)
+---------------------------
+
+Altered file selection when restoring so excluded files will not be
+deleted from the target dir. The old behavior was technically
+intended and documented but not very convenient. Thanks to Oliver
+Kaltenecker for bug report.
+
+
New in v0.12.6 (2003/11/02)
---------------------------
diff --git a/rdiff-backup/rdiff-backup.1 b/rdiff-backup/rdiff-backup.1
index 0210424..0044d01 100644
--- a/rdiff-backup/rdiff-backup.1
+++ b/rdiff-backup/rdiff-backup.1
@@ -538,9 +538,10 @@ and
Each file selection condition either matches or doesn't match a given
file. A given file is excluded by the file selection system exactly
when the first matching file selection condition specifies that the
-file be excluded; otherwise the file is included. If a file is
-excluded, rdiff-backup acts as if that file does not exist in the
-source directory.
+file be excluded; otherwise the file is included. When backing up, if
+a file is excluded, rdiff-backup acts as if that file does not exist
+in the source directory. When restoring, an excluded file is
+considered to exist in neither the source nor target directories.
For instance,
.PP
diff --git a/rdiff-backup/rdiff_backup/Main.py b/rdiff-backup/rdiff_backup/Main.py
index 5eae9bf..ad0440c 100644
--- a/rdiff-backup/rdiff_backup/Main.py
+++ b/rdiff-backup/rdiff_backup/Main.py
@@ -20,7 +20,7 @@
"""Start (and end) here - read arguments, set global settings, etc."""
from __future__ import generators
-import getopt, sys, re, os
+import getopt, sys, re, os, cStringIO
from log import Log, LoggerError, ErrorLog
import Globals, Time, SetConnections, selection, robust, rpath, \
manage, backup, connection, restore, FilenameMapping, \
@@ -408,16 +408,26 @@ def restore_common(rpin, target, time):
Log("Restore ended", 4)
def restore_set_select(mirror_rp, target):
- """Set the selection iterator on mirror side from command line args
+ """Set the selection iterator on both side from command line args
- Here we set the selector on the mirror side, because that is where
- we will be filtering, but the pathnames are relative to the target
- directory.
+ We must set both sides because restore filtering is different from
+ select filtering. For instance, if a file is excluded it should
+ not be deleted from the target directory.
+
+ The StringIO stuff is because filelists need to be read and then
+ duplicated, because we need two copies of them now.
"""
+ def fp2string(fp):
+ buf = fp.read()
+ assert not fp.close()
+ return buf
+ select_data = map(fp2string, select_files)
if select_opts:
mirror_rp.conn.restore.MirrorStruct.set_mirror_select(
- target, select_opts, *select_files)
+ target, select_opts, *map(cStringIO.StringIO, select_data))
+ target.conn.restore.TargetStruct.set_target_select(
+ target, select_opts, *map(cStringIO.StringIO, select_data))
def restore_start_log(rpin, target, time):
"""Open restore log file, log initial message"""
diff --git a/rdiff-backup/rdiff_backup/restore.py b/rdiff-backup/rdiff_backup/restore.py
index 0e2e5c0..3ec3a77 100644
--- a/rdiff-backup/rdiff_backup/restore.py
+++ b/rdiff-backup/rdiff_backup/restore.py
@@ -25,11 +25,6 @@ import Globals, Time, Rdiff, Hardlink, rorpiter, selection, rpath, \
log, static, robust, metadata, statistics, TempFile
-# This should be set to selection.Select objects over the source and
-# mirror directories respectively.
-_select_source = None
-_select_mirror = None
-
# This will be set to the time of the current mirror
_mirror_time = None
# This will be set to the exact time to restore to (not restore_to_time)
@@ -251,9 +246,16 @@ static.MakeClass(MirrorStruct)
class TargetStruct:
"""Hold functions to be run on the target side when restoring"""
- def get_initial_iter(cls, target):
+ _select = None
+ def set_target_select(cls, target, select_opts, *filelists):
"""Return a selection object iterating the rorpaths in target"""
- return selection.Select(target).set_iter()
+ cls._select = selection.Select(target)
+ cls._select.ParseArgs(select_opts, filelists)
+ cls._select.set_iter()
+
+ def get_initial_iter(cls, target):
+ """Return selector previously set with set_initial_iter"""
+ return cls._select or selection.Select(target).set_iter()
def patch(cls, target, diff_iter):
"""Patch target with the diffs from the mirror side
diff --git a/rdiff-backup/rdiff_backup/selection.py b/rdiff-backup/rdiff_backup/selection.py
index b63db4a..30bc68f 100644
--- a/rdiff-backup/rdiff_backup/selection.py
+++ b/rdiff-backup/rdiff_backup/selection.py
@@ -694,10 +694,3 @@ class FilterIterITRB(rorpiter.ITRBranch):
assert s == 2, s
self.base_queue = next_rorp
-
-
-
-
-
-
-
diff --git a/rdiff-backup/testing/finaltest.py b/rdiff-backup/testing/finaltest.py
index 8285b36..9426e18 100644
--- a/rdiff-backup/testing/finaltest.py
+++ b/rdiff-backup/testing/finaltest.py
@@ -102,6 +102,20 @@ class PathSetter(unittest.TestCase):
print "Restoring via cmdline: " + cmdstr
assert not os.system(cmdstr)
+ def exec_rb_restore_extra_args(self, time, extra_args, *args):
+ """Like exec_rb_restore, but can provide extra arguments"""
+ arglist = []
+ arglist.append("--restore-as-of %s" % str(time))
+ arglist.append(extra_args)
+ arglist.append(self.src_prefix + args[0])
+ if len(args) > 1:
+ arglist.append(self.dest_prefix + args[1])
+ assert len(args) == 2
+
+ cmdstr = self.rb_schema + " ".join(arglist)
+ print "Restoring via cmdline: " + cmdstr
+ assert not os.system(cmdstr)
+
def delete_tmpdirs(self):
"""Remove any temp directories created by previous tests"""
assert not os.system(MiscDir + '/myrm testfiles/output* '
@@ -411,6 +425,49 @@ testfiles/increment2/changed_dir""")
self.assertRaises(OSError, os.lstat,
'testfiles/restoretarget1/executable2')
+ def testSelRestoreLocal(self):
+ """Test selection options when restoring locally"""
+ self.set_connections(None, None, None, None)
+ self.run_sel_restore_test()
+
+ def testSelRestoreRemote(self):
+ """Test selection options when both sides are remote"""
+ self.set_connections("test1/", "../", "test2/tmp/", "../../")
+ self.run_sel_restore_test("../../")
+
+ def run_sel_restore_test(self, prefix = ""):
+ """Test selection options with restore"""
+ self.make_restore_sel_dir()
+ existing_file = self.make_restore_existing_target()
+ file1_target = Local.rpout1.append("file1")
+ file2_target = Local.rpout1.append("file2")
+ excludes = ("--exclude %s --exclude %s --force" %
+ (prefix + file1_target.path, prefix + existing_file.path))
+ self.exec_rb_restore_extra_args("now", excludes,
+ Local.rpout.path, Local.rpout1.path)
+ for rp in (file1_target, file2_target, existing_file):
+ rp.setdata()
+ assert not file1_target.lstat(), file1_target.lstat()
+ assert file2_target.lstat()
+ assert existing_file.lstat() # excluded file shouldn't be deleted
+
+ def make_restore_sel_dir(self):
+ """Create rdiff-backup repository at Local.rpout"""
+ self.delete_tmpdirs()
+ Local.vft_in.mkdir()
+ rp1 = Local.vft_in.append("file1")
+ rp2 = Local.vft_in.append("file2")
+ rp1.touch()
+ rp2.touch()
+ self.exec_rb(None, Local.vft_in.path, Local.rpout.path)
+ Myrm(Local.vft_in.path)
+
+ def make_restore_existing_target(self):
+ """Create an existing file in the restore target directory"""
+ Local.rpout1.mkdir()
+ existing_file = Local.rpout1.append("existing_file")
+ existing_file.touch()
+ return existing_file
class FinalCorrupt(PathSetter):
"""Test messing with things a bit and making sure they still work"""