Commit 7cfed788 authored by bescoto's avatar bescoto

Removed most destructive stepping operations


git-svn-id: http://svn.savannah.nongnu.org/svn/rdiff-backup@251 2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109
parent cf84368c
...@@ -7,6 +7,11 @@ Fixed bug with the --{include|exclude}-globbing-filelist options ...@@ -7,6 +7,11 @@ Fixed bug with the --{include|exclude}-globbing-filelist options
Added --list-changed-since option to list the files changed since the Added --list-changed-since option to list the files changed since the
given date. given date.
Removed --mirror-only and --change-source-perms options.
Removed all "resume" related functionality, like
--checkpoint-interval.
New in v0.11.0 (2002/10/05) New in v0.11.0 (2002/10/05)
--------------------------- ---------------------------
......
...@@ -55,10 +55,6 @@ change_ownership = None ...@@ -55,10 +55,6 @@ change_ownership = None
# permissions). # permissions).
change_mirror_perms = (process_uid != 0) change_mirror_perms = (process_uid != 0)
# If true, temporarily change permissions of unreadable files in
# the source directory to make sure we can read all files.
change_source_perms = None
# If true, try to reset the atimes of the source partition. # If true, try to reset the atimes of the source partition.
preserve_atime = None preserve_atime = None
...@@ -103,24 +99,9 @@ client_conn = None ...@@ -103,24 +99,9 @@ client_conn = None
# list. # list.
changed_settings = [] changed_settings = []
# rdiff-backup will try to checkpoint its state every
# checkpoint_interval seconds. Then when resuming, at most this
# amount of time is lost.
checkpoint_interval = 20
# The RPath of the rdiff-backup-data directory. # The RPath of the rdiff-backup-data directory.
rbdir = None rbdir = None
# Indicates if a resume or a lack of resume is forced. This
# should be None for the default. 0 means don't resume, and 1
# means resume.
resume = None
# If there has been an aborted backup fewer than this many seconds
# ago, attempt to resume it where it left off instead of starting
# a new one.
resume_window = 7200
# This string is used when recognizing and creating time strings. # This string is used when recognizing and creating time strings.
# If the time_separator is ":", then W3 datetime strings like # If the time_separator is ":", then W3 datetime strings like
# 2001-12-07T04:22:01-07:00 are produced. It can be set to "_" to # 2001-12-07T04:22:01-07:00 are produced. It can be set to "_" to
...@@ -265,7 +246,7 @@ def postset_regexp_local(name, re_string, flags): ...@@ -265,7 +246,7 @@ def postset_regexp_local(name, re_string, flags):
if flags: globals()[name] = re.compile(re_string, flags) if flags: globals()[name] = re.compile(re_string, flags)
else: globals()[name] = re.compile(re_string) else: globals()[name] = re.compile(re_string)
def set_select(dsrpath, tuplelist, quote_mode, *filelists): def set_select(source, rpath, tuplelist, quote_mode, *filelists):
"""Initialize select object using tuplelist """Initialize select object using tuplelist
Note that each list in filelists must each be passed as Note that each list in filelists must each be passed as
...@@ -275,12 +256,10 @@ def set_select(dsrpath, tuplelist, quote_mode, *filelists): ...@@ -275,12 +256,10 @@ def set_select(dsrpath, tuplelist, quote_mode, *filelists):
""" """
global select_source, select_mirror global select_source, select_mirror
if dsrpath.source: sel = Select(rpath, quote_mode)
select_source = Select(dsrpath, quote_mode) sel.ParseArgs(tuplelist, filelists)
select_source.ParseArgs(tuplelist, filelists) if source: select_source = sel
else: else: select_mirror = sel
select_mirror = Select(dsrpath, quote_mode)
select_mirror.ParseArgs(tuplelist, filelists)
from rpath import * # kludge to avoid circularity - not needed in this module from rpath import * # kludge to avoid circularity - not needed in this module
......
...@@ -25,7 +25,6 @@ from log import * ...@@ -25,7 +25,6 @@ from log import *
from lazy import * from lazy import *
from connection import * from connection import *
from rpath import * from rpath import *
from destructive_stepping import *
from robust import * from robust import *
from restore import * from restore import *
from highlevel import * from highlevel import *
...@@ -49,21 +48,20 @@ def parse_cmdlineoptions(arglist): ...@@ -49,21 +48,20 @@ def parse_cmdlineoptions(arglist):
except IOError: Log.FatalError("Error opening file %s" % filename) except IOError: Log.FatalError("Error opening file %s" % filename)
try: optlist, args = getopt.getopt(arglist, "blr:sv:V", try: optlist, args = getopt.getopt(arglist, "blr:sv:V",
["backup-mode", "calculate-average", "change-source-perms", ["backup-mode", "calculate-average", "chars-to-quote=",
"chars-to-quote=", "checkpoint-interval=", "current-time=", "current-time=", "exclude=", "exclude-device-files",
"exclude=", "exclude-device-files", "exclude-filelist=", "exclude-filelist=", "exclude-filelist-stdin",
"exclude-filelist-stdin", "exclude-globbing-filelist=", "exclude-globbing-filelist=", "exclude-mirror=",
"exclude-mirror=", "exclude-other-filesystems", "exclude-other-filesystems", "exclude-regexp=",
"exclude-regexp=", "exclude-special-files", "force", "exclude-special-files", "force", "include=",
"include=", "include-filelist=", "include-filelist-stdin", "include-filelist=", "include-filelist-stdin",
"include-globbing-filelist=", "include-regexp=", "include-globbing-filelist=", "include-regexp=",
"list-changed-since=", "list-increments", "no-compression", "list-changed-since=", "list-increments", "no-compression",
"no-compression-regexp=", "no-hard-links", "no-resume", "no-compression-regexp=", "no-hard-links", "null-separator",
"null-separator", "parsable-output", "print-statistics", "parsable-output", "print-statistics", "quoting-char=",
"quoting-char=", "remote-cmd=", "remote-schema=", "remote-cmd=", "remote-schema=", "remove-older-than=",
"remove-older-than=", "restore-as-of=", "restrict=", "restore-as-of=", "restrict=", "restrict-read-only=",
"restrict-read-only=", "restrict-update-only=", "resume", "restrict-update-only=", "server", "sleep-ratio=",
"resume-window=", "server", "sleep-ratio=",
"ssh-no-compression", "terminal-verbosity=", "test-server", "ssh-no-compression", "terminal-verbosity=", "test-server",
"verbosity=", "version", "windows-mode", "verbosity=", "version", "windows-mode",
"windows-time-format"]) "windows-time-format"])
...@@ -73,13 +71,9 @@ def parse_cmdlineoptions(arglist): ...@@ -73,13 +71,9 @@ def parse_cmdlineoptions(arglist):
for opt, arg in optlist: for opt, arg in optlist:
if opt == "-b" or opt == "--backup-mode": action = "backup" if opt == "-b" or opt == "--backup-mode": action = "backup"
elif opt == "--calculate-average": action = "calculate-average" elif opt == "--calculate-average": action = "calculate-average"
elif opt == "--change-source-perms":
Globals.set('change_source_perms', 1)
elif opt == "--chars-to-quote": elif opt == "--chars-to-quote":
Globals.set('chars_to_quote', arg) Globals.set('chars_to_quote', arg)
Globals.set('quoting_enabled', 1) Globals.set('quoting_enabled', 1)
elif opt == "--checkpoint-interval":
Globals.set_integer('checkpoint_interval', arg)
elif opt == "--current-time": elif opt == "--current-time":
Globals.set_integer('current_time', arg) Globals.set_integer('current_time', arg)
elif opt == "--exclude": select_opts.append((opt, arg)) elif opt == "--exclude": select_opts.append((opt, arg))
...@@ -118,7 +112,6 @@ def parse_cmdlineoptions(arglist): ...@@ -118,7 +112,6 @@ def parse_cmdlineoptions(arglist):
elif opt == "--no-compression-regexp": elif opt == "--no-compression-regexp":
Globals.set("no_compression_regexp_string", arg) Globals.set("no_compression_regexp_string", arg)
elif opt == "--no-hard-links": Globals.set('preserve_hardlinks', 0) elif opt == "--no-hard-links": Globals.set('preserve_hardlinks', 0)
elif opt == '--no-resume': Globals.resume = 0
elif opt == "--null-separator": Globals.set("null_separator", 1) elif opt == "--null-separator": Globals.set("null_separator", 1)
elif opt == "--parsable-output": Globals.set('parsable_output', 1) elif opt == "--parsable-output": Globals.set('parsable_output', 1)
elif opt == "--print-statistics": elif opt == "--print-statistics":
...@@ -140,9 +133,6 @@ def parse_cmdlineoptions(arglist): ...@@ -140,9 +133,6 @@ def parse_cmdlineoptions(arglist):
elif opt == "--restrict-update-only": elif opt == "--restrict-update-only":
Globals.security_level = "update-only" Globals.security_level = "update-only"
Globals.restrict_path = arg Globals.restrict_path = arg
elif opt == '--resume': Globals.resume = 1
elif opt == '--resume-window':
Globals.set_integer('resume_window', arg)
elif opt == "-s" or opt == "--server": elif opt == "-s" or opt == "--server":
action = "server" action = "server"
Globals.server = 1 Globals.server = 1
...@@ -263,9 +253,8 @@ def Backup(rpin, rpout): ...@@ -263,9 +253,8 @@ def Backup(rpin, rpout):
def backup_init_select(rpin, rpout): def backup_init_select(rpin, rpout):
"""Create Select objects on source and dest connections""" """Create Select objects on source and dest connections"""
rpin.conn.Globals.set_select(DSRPath(1, rpin), select_opts, rpin.conn.Globals.set_select(1, rpin, select_opts, None, *select_files)
None, *select_files) rpout.conn.Globals.set_select(0, rpout, select_mirror_opts, 1)
rpout.conn.Globals.set_select(DSRPath(None, rpout), select_mirror_opts, 1)
def backup_init_dirs(rpin, rpout): def backup_init_dirs(rpin, rpout):
"""Make sure rpin and rpout are valid, init data dir and logging""" """Make sure rpin and rpout are valid, init data dir and logging"""
...@@ -424,8 +413,8 @@ def restore_init_select(rpin, rpout): ...@@ -424,8 +413,8 @@ def restore_init_select(rpin, rpout):
the restore operation isn't. the restore operation isn't.
""" """
Globals.set_select(DSRPath(1, rpin), select_mirror_opts, None) Globals.set_select(1, rpin, select_mirror_opts, None)
Globals.set_select(DSRPath(None, rpout), select_opts, None, *select_files) Globals.set_select(0, rpout, select_opts, None, *select_files)
def restore_get_root(rpin): def restore_get_root(rpin):
"""Return (mirror root, index) and set the data dir """Return (mirror root, index) and set the data dir
......
...@@ -197,11 +197,6 @@ def BackupInitConnections(reading_conn, writing_conn): ...@@ -197,11 +197,6 @@ def BackupInitConnections(reading_conn, writing_conn):
writing_conn.Globals.set("isbackup_writer", 1) writing_conn.Globals.set("isbackup_writer", 1)
UpdateGlobal("backup_reader", reading_conn) UpdateGlobal("backup_reader", reading_conn)
UpdateGlobal("backup_writer", writing_conn) UpdateGlobal("backup_writer", writing_conn)
if (Globals.change_source_perms and
reading_conn.Globals.get("process_uid") == 0):
Log("Warning: --change_source_perms should usually not be used when\n"
"the reading connection is running as root, because root can\n"
"read all files regardless of their permissions.", 2)
def CloseConnections(): def CloseConnections():
"""Close all connections. Run by client""" """Close all connections. Run by client"""
......
...@@ -547,7 +547,6 @@ from connection import * ...@@ -547,7 +547,6 @@ from connection import *
from rpath import * from rpath import *
from robust import * from robust import *
from rorpiter import * from rorpiter import *
from destructive_stepping import *
from selection import * from selection import *
from statistics import * from statistics import *
from increment import * from increment import *
......
...@@ -87,27 +87,23 @@ class HLSourceStruct: ...@@ -87,27 +87,23 @@ class HLSourceStruct:
"""Return diffs and finalize any dsrp changes remaining """Return diffs and finalize any dsrp changes remaining
Return a rorpiterator with files included of signatures of Return a rorpiterator with files included of signatures of
dissimilar files. This is the last operation run on the local dissimilar files.
filestream, so finalize dsrp writes.
""" """
collated = RORPIter.CollateIterators(cls.initial_dsiter2, sigiter) collated = RORPIter.CollateIterators(cls.initial_dsiter2, sigiter)
finalizer = IterTreeReducer(DestructiveSteppingFinalizer, []) def error_handler(exc, dest_sig, rp):
def error_handler(exc, dest_sig, dsrp):
Log("Error %s producing a diff of %s" % Log("Error %s producing a diff of %s" %
(exc, dsrp and dsrp.path), 2) (exc, rp and rp.path), 2)
return None return None
def diffs(): def diffs():
for dsrp, dest_sig in collated: for rp, dest_sig in collated:
if dest_sig: if dest_sig:
if dest_sig.isplaceholder(): yield dest_sig if dest_sig.isplaceholder(): yield dest_sig
else: else:
diff = Robust.check_common_error( diff = Robust.check_common_error(
error_handler, RORPIter.diffonce, [dest_sig, dsrp]) error_handler, RORPIter.diffonce, [dest_sig, rp])
if diff: yield diff if diff: yield diff
if dsrp: finalizer(dsrp.index, dsrp)
finalizer.Finish()
return diffs() return diffs()
MakeClass(HLSourceStruct) MakeClass(HLSourceStruct)
...@@ -117,7 +113,7 @@ class HLDestinationStruct: ...@@ -117,7 +113,7 @@ class HLDestinationStruct:
"""Hold info used by HL on the destination side""" """Hold info used by HL on the destination side"""
_session_info = None # set to si if resuming _session_info = None # set to si if resuming
def split_initial_dsiter(cls): def split_initial_dsiter(cls):
"""Set initial_dsiters (iteration of all dsrps from rpath)""" """Set initial_dsiters (iteration of all rps from rpath)"""
result, cls.initial_dsiter2 = \ result, cls.initial_dsiter2 = \
Iter.multiplex(Globals.select_mirror.set_iter(), 2) Iter.multiplex(Globals.select_mirror.set_iter(), 2)
return result return result
...@@ -192,10 +188,10 @@ class HLDestinationStruct: ...@@ -192,10 +188,10 @@ class HLDestinationStruct:
return RORPIter.Signatures(dissimilars) return RORPIter.Signatures(dissimilars)
def get_dsrp(cls, dest_rpath, index): def get_dsrp(cls, dest_rpath, index):
"""Return initialized dsrp based on dest_rpath with given index""" """Return initialized rpath based on dest_rpath with given index"""
dsrp = DSRPath(None, dest_rpath.conn, dest_rpath.base, index) rp = RPath(dest_rpath.conn, dest_rpath.base, index)
if Globals.quoting_enabled: dsrp.quote_path() if Globals.quoting_enabled: rp.quote_path()
return dsrp return rp
def get_finalizer(cls): def get_finalizer(cls):
"""Return finalizer, starting from session info if necessary""" """Return finalizer, starting from session info if necessary"""
...@@ -226,8 +222,8 @@ class HLDestinationStruct: ...@@ -226,8 +222,8 @@ class HLDestinationStruct:
def patch_and_finalize(cls, dest_rpath, diffs): def patch_and_finalize(cls, dest_rpath, diffs):
"""Apply diffs and finalize""" """Apply diffs and finalize"""
collated = RORPIter.CollateIterators(diffs, cls.initial_dsiter2) collated = RORPIter.CollateIterators(diffs, cls.initial_dsiter2)
finalizer = cls.get_finalizer() #finalizer = cls.get_finalizer()
diff_rorp, dsrp = None, None diff_rorp, rp = None, None
def patch(diff_rorp, dsrp): def patch(diff_rorp, dsrp):
if not dsrp: dsrp = cls.get_dsrp(dest_rpath, diff_rorp.index) if not dsrp: dsrp = cls.get_dsrp(dest_rpath, diff_rorp.index)
...@@ -244,13 +240,14 @@ class HLDestinationStruct: ...@@ -244,13 +240,14 @@ class HLDestinationStruct:
diff_rorp, dsrp = indexed_tuple diff_rorp, dsrp = indexed_tuple
dsrp = Robust.check_common_error(error_handler, patch, dsrp = Robust.check_common_error(error_handler, patch,
[diff_rorp, dsrp]) [diff_rorp, dsrp])
finalizer(dsrp.index, dsrp) #finalizer(dsrp.index, dsrp)
finalizer.Finish() #finalizer.Finish()
def patch_w_datadir_writes(cls, dest_rpath, diffs, inc_rpath): def patch_w_datadir_writes(cls, dest_rpath, diffs, inc_rpath):
"""Apply diffs and finalize, with checkpointing and statistics""" """Apply diffs and finalize, with checkpointing and statistics"""
collated = RORPIter.CollateIterators(diffs, cls.initial_dsiter2) collated = RORPIter.CollateIterators(diffs, cls.initial_dsiter2)
finalizer, ITR = cls.get_finalizer(), cls.get_MirrorITR(inc_rpath) #finalizer, ITR = cls.get_finalizer(), cls.get_MirrorITR(inc_rpath)
finalizer, ITR = None, cls.get_MirrorITR(inc_rpath)
MiscStats.open_dir_stats_file() MiscStats.open_dir_stats_file()
dsrp, finished_dsrp = None, None dsrp, finished_dsrp = None, None
...@@ -261,10 +258,10 @@ class HLDestinationStruct: ...@@ -261,10 +258,10 @@ class HLDestinationStruct:
if not dsrp: dsrp = cls.get_dsrp(dest_rpath, diff_rorp.index) if not dsrp: dsrp = cls.get_dsrp(dest_rpath, diff_rorp.index)
if diff_rorp and diff_rorp.isplaceholder(): diff_rorp = None if diff_rorp and diff_rorp.isplaceholder(): diff_rorp = None
ITR(dsrp.index, diff_rorp, dsrp) ITR(dsrp.index, diff_rorp, dsrp)
finalizer(dsrp.index, dsrp) #finalizer(dsrp.index, dsrp)
finished_dsrp = dsrp finished_dsrp = dsrp
ITR.Finish() ITR.Finish()
finalizer.Finish() #finalizer.Finish()
except: cls.handle_last_error(finished_dsrp, finalizer, ITR) except: cls.handle_last_error(finished_dsrp, finalizer, ITR)
if Globals.preserve_hardlinks: Hardlink.final_writedata() if Globals.preserve_hardlinks: Hardlink.final_writedata()
...@@ -274,7 +271,8 @@ class HLDestinationStruct: ...@@ -274,7 +271,8 @@ class HLDestinationStruct:
def patch_increment_and_finalize(cls, dest_rpath, diffs, inc_rpath): def patch_increment_and_finalize(cls, dest_rpath, diffs, inc_rpath):
"""Apply diffs, write increment if necessary, and finalize""" """Apply diffs, write increment if necessary, and finalize"""
collated = RORPIter.CollateIterators(diffs, cls.initial_dsiter2) collated = RORPIter.CollateIterators(diffs, cls.initial_dsiter2)
finalizer, ITR = cls.get_finalizer(), cls.get_ITR(inc_rpath) #finalizer, ITR = cls.get_finalizer(), cls.get_ITR(inc_rpath)
finalizer, ITR = None, cls.get_ITR(inc_rpath)
MiscStats.open_dir_stats_file() MiscStats.open_dir_stats_file()
dsrp, finished_dsrp = None, None dsrp, finished_dsrp = None, None
...@@ -286,10 +284,10 @@ class HLDestinationStruct: ...@@ -286,10 +284,10 @@ class HLDestinationStruct:
if not dsrp: dsrp = cls.get_dsrp(dest_rpath, index) if not dsrp: dsrp = cls.get_dsrp(dest_rpath, index)
if diff_rorp and diff_rorp.isplaceholder(): diff_rorp = None if diff_rorp and diff_rorp.isplaceholder(): diff_rorp = None
ITR(index, diff_rorp, dsrp) ITR(index, diff_rorp, dsrp)
finalizer(index, dsrp) #finalizer(index, dsrp)
finished_dsrp = dsrp finished_dsrp = dsrp
ITR.Finish() ITR.Finish()
finalizer.Finish() #finalizer.Finish()
except: cls.handle_last_error(finished_dsrp, finalizer, ITR) except: cls.handle_last_error(finished_dsrp, finalizer, ITR)
if Globals.preserve_hardlinks: Hardlink.final_writedata() if Globals.preserve_hardlinks: Hardlink.final_writedata()
...@@ -311,6 +309,5 @@ from log import * ...@@ -311,6 +309,5 @@ from log import *
from rpath import * from rpath import *
from robust import * from robust import *
from increment import * from increment import *
from destructive_stepping import *
from rorpiter import * from rorpiter import *
import Globals, Hardlink, MiscStats, metadata import Globals, Hardlink, MiscStats, metadata
...@@ -145,8 +145,6 @@ class IncrementITRB(StatsITRB): ...@@ -145,8 +145,6 @@ class IncrementITRB(StatsITRB):
4. Directory -> Normal file: Wait until the end, so we can 4. Directory -> Normal file: Wait until the end, so we can
process all the files in the directory. process all the files in the directory.
Remember this object needs to be pickable.
""" """
# Iff true, mirror file was a directory # Iff true, mirror file was a directory
mirror_isdirectory = None mirror_isdirectory = None
...@@ -299,7 +297,14 @@ class MirrorITRB(StatsITRB): ...@@ -299,7 +297,14 @@ class MirrorITRB(StatsITRB):
def start_process(self, index, diff_rorp, mirror_dsrp): def start_process(self, index, diff_rorp, mirror_dsrp):
"""Initialize statistics and do actual writing to mirror""" """Initialize statistics and do actual writing to mirror"""
self.start_stats(mirror_dsrp) self.start_stats(mirror_dsrp)
if diff_rorp and not diff_rorp.isplaceholder(): if (diff_rorp and diff_rorp.isdir() or
not diff_rorp and mirror_dsrp.isdir()):
# mirror_dsrp will end up as directory, update attribs later
if not diff_rorp: diff_rorp = mirror_dsrp.get_rorpath()
if not mirror_dsrp.isdir():
mirror_dsrp.delete()
mirror_dsrp.mkdir()
elif diff_rorp and not diff_rorp.isplaceholder():
RORPIter.patchonce_action(None, mirror_dsrp, diff_rorp).execute() RORPIter.patchonce_action(None, mirror_dsrp, diff_rorp).execute()
self.incpref = self.inc_rpath.new_index(index) self.incpref = self.inc_rpath.new_index(index)
...@@ -309,6 +314,7 @@ class MirrorITRB(StatsITRB): ...@@ -309,6 +314,7 @@ class MirrorITRB(StatsITRB):
"""Update statistics when leaving""" """Update statistics when leaving"""
self.end_stats(self.diff_rorp, self.mirror_dsrp) self.end_stats(self.diff_rorp, self.mirror_dsrp)
if self.mirror_dsrp.isdir(): if self.mirror_dsrp.isdir():
RPathStatic.copy_attribs(self.diff_rorp, self.mirror_dsrp)
MiscStats.write_dir_stats_line(self, self.mirror_dsrp.index) MiscStats.write_dir_stats_line(self, self.mirror_dsrp.index)
def can_fast_process(self, index, diff_rorp, mirror_dsrp): def can_fast_process(self, index, diff_rorp, mirror_dsrp):
......
...@@ -41,7 +41,6 @@ class Restore: ...@@ -41,7 +41,6 @@ class Restore:
same index as mirror. same index as mirror.
""" """
if not isinstance(mirror, DSRPath): mirror = DSRPath(1, mirror)
if not isinstance(target, DSRPath): target = DSRPath(None, target) if not isinstance(target, DSRPath): target = DSRPath(None, target)
mirror_time = Restore.get_mirror_time() mirror_time = Restore.get_mirror_time()
...@@ -129,18 +128,16 @@ class Restore: ...@@ -129,18 +128,16 @@ class Restore:
"foo/bar". "foo/bar".
""" """
assert isinstance(mirror, DSRPath) and isinstance(target, DSRPath) assert isinstance(target, DSRPath)
assert mirror.index == rid.index assert mirror.index == rid.index
mirror_finalizer = IterTreeReducer(DestructiveSteppingFinalizer, ())
target_finalizer = IterTreeReducer(DestructiveSteppingFinalizer, ()) target_finalizer = IterTreeReducer(DestructiveSteppingFinalizer, ())
for rcd in Restore.yield_rcds(rid.index, mirror, rid, for rcd in Restore.yield_rcds(rid.index, mirror, rid,
target, time, mirror_time): target, time, mirror_time):
rcd.RestoreFile() rcd.RestoreFile()
if rcd.mirror: mirror_finalizer(rcd.index, rcd.mirror) #if rcd.mirror: mirror_finalizer(rcd.index, rcd.mirror)
target_finalizer(rcd.target.index, rcd.target) target_finalizer(rcd.target.index, rcd.target)
target_finalizer.Finish() target_finalizer.Finish()
mirror_finalizer.Finish()
def yield_rcds(index, mirrorrp, rid, target, rest_time, mirror_time): def yield_rcds(index, mirrorrp, rid, target, rest_time, mirror_time):
"""Iterate RestoreCombinedData objects starting with given args """Iterate RestoreCombinedData objects starting with given args
......
...@@ -288,6 +288,8 @@ class RORPath(RPathStatic): ...@@ -288,6 +288,8 @@ class RORPath(RPathStatic):
(not Globals.change_ownership or self.issym())): (not Globals.change_ownership or self.issym())):
# Don't compare gid/uid for symlinks or if not change_ownership # Don't compare gid/uid for symlinks or if not change_ownership
pass pass
elif key == 'mtime':
Log("%s differs only in mtime, skipping" % (self.path,), 2)
elif key == 'atime' and not Globals.preserve_atime: pass elif key == 'atime' and not Globals.preserve_atime: pass
elif key == 'devloc' or key == 'inode' or key == 'nlink': pass elif key == 'devloc' or key == 'inode' or key == 'nlink': pass
elif key == 'size' and not self.isreg(): pass elif key == 'size' and not self.isreg(): pass
...@@ -319,6 +321,10 @@ class RORPath(RPathStatic): ...@@ -319,6 +321,10 @@ class RORPath(RPathStatic):
"""Reproduce RORPath from __getstate__ output""" """Reproduce RORPath from __getstate__ output"""
self.index, self.data = rorp_state self.index, self.data = rorp_state
def get_rorpath(self):
"""Return new rorpath based on self"""
return RORPath(self.index, self.data.copy())
def make_placeholder(self): def make_placeholder(self):
"""Make rorp into a placeholder """Make rorp into a placeholder
...@@ -697,19 +703,15 @@ class RPath(RORPath): ...@@ -697,19 +703,15 @@ class RPath(RORPath):
return self.conn.Globals.get('process_gid') == self.data['gid'] return self.conn.Globals.get('process_gid') == self.data['gid']
def delete(self): def delete(self):
"""Delete file at self.path """Delete file at self.path. Recursively deletes directories."""
The destructive stepping allows this function to delete
directories even if they have files and we lack permissions.
"""
Log("Deleting %s" % self.path, 7) Log("Deleting %s" % self.path, 7)
self.setdata() self.setdata()
if not self.lstat(): return # must have been deleted in meantime if not self.lstat():
Log("Warning: %s does not exist---deleted in meantime?"
% (self.path,), 2)
elif self.isdir(): elif self.isdir():
itm = IterTreeReducer(RpathDeleter, []) itm = IterTreeReducer(RpathDeleter, [])
for dsrp in Select(DSRPath(None, self)).set_iter(): for rp in Select(self).set_iter(): itm(rp.index, rp)
itm(dsrp.index, dsrp)
itm.Finish() itm.Finish()
else: self.conn.os.unlink(self.path) else: self.conn.os.unlink(self.path)
self.setdata() self.setdata()
...@@ -891,18 +893,17 @@ class RPathFileHook: ...@@ -891,18 +893,17 @@ class RPathFileHook:
import FilenameMapping import FilenameMapping
from lazy import * from lazy import *
from selection import * from selection import *
from destructive_stepping import *
from highlevel import * from highlevel import *
class RpathDeleter(ITRBranch): class RpathDeleter(ITRBranch):
"""Delete a directory. Called by RPath.delete()""" """Delete a directory. Called by RPath.delete()"""
def start_process(self, index, dsrp): def start_process(self, index, rp):
self.dsrp = dsrp self.rp = rp
def end_process(self): def end_process(self):
if self.dsrp.isdir(): self.dsrp.rmdir() if self.rp.isdir(): self.rp.rmdir()
else: self.dsrp.delete() else: self.rp.delete()
def can_fast_process(self, index, dsrp): return not dsrp.isdir() def can_fast_process(self, index, rp): return not rp.isdir()
def fast_process(self, index, dsrp): dsrp.delete() def fast_process(self, index, rp): rp.delete()
...@@ -173,8 +173,7 @@ def CompareRecursive(src_rp, dest_rp, compare_hardlinks = 1, ...@@ -173,8 +173,7 @@ def CompareRecursive(src_rp, dest_rp, compare_hardlinks = 1,
Log("Comparing %s and %s, hardlinks %s" % (src_rp.path, dest_rp.path, Log("Comparing %s and %s, hardlinks %s" % (src_rp.path, dest_rp.path,
compare_hardlinks), 3) compare_hardlinks), 3)
src_select = Select(DSRPath(1, src_rp)) src_select, dest_select = Select(src_rp), Select(dest_rp)
dest_select = Select(DSRPath(None, dest_rp))
if ignore_tmp_files: if ignore_tmp_files:
# Ignoring temp files can be useful when we want to check the # Ignoring temp files can be useful when we want to check the
...@@ -201,13 +200,10 @@ def CompareRecursive(src_rp, dest_rp, compare_hardlinks = 1, ...@@ -201,13 +200,10 @@ def CompareRecursive(src_rp, dest_rp, compare_hardlinks = 1,
dest_select.add_selection_func(dest_select.glob_get_tuple_sf( dest_select.add_selection_func(dest_select.glob_get_tuple_sf(
('rdiff-backup-data',), 0)) ('rdiff-backup-data',), 0))
src_select.set_iter() dsiter1, dsiter2 = src_select.set_iter(), dest_select.set_iter()
dest_select.set_iter()
dsiter1, dsiter2 = src_select.iterate_with_finalizer(), \
dest_select.iterate_with_finalizer()
def hardlink_equal(src_rorp, dest_rorp): def hardlink_equal(src_rorp, dest_rorp):
if src_rorp != dest_rorp: return None if not src_rorp.equal_verbose(dest_rorp): return None
if Hardlink.rorp_eq(src_rorp, dest_rorp): return 1 if Hardlink.rorp_eq(src_rorp, dest_rorp): return 1
Log("%s: %s" % (src_rorp.index, Hardlink.get_indicies(src_rorp, 1)), 3) Log("%s: %s" % (src_rorp.index, Hardlink.get_indicies(src_rorp, 1)), 3)
Log("%s: %s" % (dest_rorp.index, Log("%s: %s" % (dest_rorp.index,
...@@ -229,7 +225,7 @@ def CompareRecursive(src_rp, dest_rp, compare_hardlinks = 1, ...@@ -229,7 +225,7 @@ def CompareRecursive(src_rp, dest_rp, compare_hardlinks = 1,
if dest_rorp.index[-1].endswith('.missing'): return 1 if dest_rorp.index[-1].endswith('.missing'): return 1
if compare_hardlinks: if compare_hardlinks:
if Hardlink.rorp_eq(src_rorp, dest_rorp): return 1 if Hardlink.rorp_eq(src_rorp, dest_rorp): return 1
elif src_rorp == dest_rorp: return 1 elif src_rorp.equal_verbose(dest_rorp): return 1
Log("%s: %s" % (src_rorp.index, Hardlink.get_indicies(src_rorp, 1)), 3) Log("%s: %s" % (src_rorp.index, Hardlink.get_indicies(src_rorp, 1)), 3)
Log("%s: %s" % (dest_rorp.index, Log("%s: %s" % (dest_rorp.index,
Hardlink.get_indicies(dest_rorp, None)), 3) Hardlink.get_indicies(dest_rorp, None)), 3)
......
...@@ -14,7 +14,7 @@ testfiles ...@@ -14,7 +14,7 @@ testfiles
Globals.set('change_source_perms', 1) Globals.set('change_source_perms', 1)
Globals.counter = 0 Globals.counter = 0
Log.setverbosity(3) Log.setverbosity(7)
class Local: class Local:
"""This is just a place to put increments relative to the local """This is just a place to put increments relative to the local
......
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