Commit e637a895 authored by ben's avatar ben

Added --null-separator, tweaked increment error handling


git-svn-id: http://svn.savannah.nongnu.org/svn/rdiff-backup@117 2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109
parent 5ff84f45
New in v0.8.0 (2002/06/06)
--------------------------
Fixed 'size' bug that occurred on some non-Linux systems. Thanks to
Robert Weber for the report.
Added --null-separator argument so filenames can safely include
newlines in an include/exclude filelist.
New in v0.7.6 (2002/05/31) New in v0.7.6 (2002/05/31)
-------------------------- --------------------------
......
...@@ -187,6 +187,13 @@ are present, this option can drastically decrease memory usage. ...@@ -187,6 +187,13 @@ are present, this option can drastically decrease memory usage.
Do not resume last aborted backup even if it falls within the resume Do not resume last aborted backup even if it falls within the resume
window. window.
.TP .TP
.B --null-separator
Use nulls (\\0) instead of newlines (\\n) as line separators, which
may help when dealing with filenames containing newlines. This
affects the expected format of the files specified by the
--{include|exclude}-filelist[-stdin] switches as well as the format of
the directory_statistics file.
.TP
.BI "-r, --restore-as-of " restore_time .BI "-r, --restore-as-of " restore_time
Restore the specified directory as it was as of Restore the specified directory as it was as of
.IR restore_time . .IR restore_time .
...@@ -651,8 +658,10 @@ and ...@@ -651,8 +658,10 @@ and
.B --exclude-filelist-stdin .B --exclude-filelist-stdin
options also introduce file selection conditions. They direct options also introduce file selection conditions. They direct
rdiff-backup to read in a file, each line of which is a file rdiff-backup to read in a file, each line of which is a file
specification, and to include or exclude the matching files. The specification, and to include or exclude the matching files. Lines
lines in a filelist are interpreted similarly to the way are separated by newlines or nulls, depending on whether the
--null-separator switch was given. Each line in a filelist is
interpreted similarly to the way
.I extended shell patterns .I extended shell patterns
are, with a few exceptions: are, with a few exceptions:
.TP .TP
...@@ -731,11 +740,6 @@ rdiff-backup uses the shell command ...@@ -731,11 +740,6 @@ rdiff-backup uses the shell command
to backup device files (e.g. /dev/ttyS0), so device files won't be to backup device files (e.g. /dev/ttyS0), so device files won't be
handled correctly on systems with non-standard mknod syntax. handled correctly on systems with non-standard mknod syntax.
.PP .PP
When an rdiff-backup session fails (for instance if a remote
connection is lost), rdiff-backup tries to save the session so it can
be resumed later. Apparently sometimes, depending on how the
rdiff-backup session fails, later sessions cannot be resumed properly.
.PP
Files whose names are close to the maximum length (e.g. 235 chars if Files whose names are close to the maximum length (e.g. 235 chars if
the maximum is 255) may be skipped because the filenames of related the maximum is 255) may be skipped because the filenames of related
increment files would be too long. increment files would be too long.
......
...@@ -219,6 +219,7 @@ class IncrementITR(ErrorITR, StatsITR): ...@@ -219,6 +219,7 @@ class IncrementITR(ErrorITR, StatsITR):
# Write updated mirror to temp file so we can compute # Write updated mirror to temp file so we can compute
# reverse diff locally # reverse diff locally
mirror_tf = TempFileManager.new(dsrp) mirror_tf = TempFileManager.new(dsrp)
old_dsrp_tf = TempFileManager.new(dsrp)
def init_thunk(): def init_thunk():
if diff_rorp.isflaglinked(): if diff_rorp.isflaglinked():
Hardlink.link_rp(diff_rorp, mirror_tf, dsrp) Hardlink.link_rp(diff_rorp, mirror_tf, dsrp)
...@@ -226,8 +227,16 @@ class IncrementITR(ErrorITR, StatsITR): ...@@ -226,8 +227,16 @@ class IncrementITR(ErrorITR, StatsITR):
mirror_tf).execute() mirror_tf).execute()
self.incrp = Inc.Increment_action(mirror_tf, dsrp, self.incrp = Inc.Increment_action(mirror_tf, dsrp,
incpref).execute() incpref).execute()
def final(init_val): mirror_tf.rename(dsrp) if dsrp.lstat(): RPathStatic.rename(dsrp, old_dsrp_tf)
def error(exc, ran_init, init_val): mirror_tf.delete() mirror_tf.rename(dsrp)
def final(init_val): old_dsrp_tf.delete()
def error(exc, ran_init, init_val):
if ran_init: old_dsrp_tf.delete() # everything is fine
else: # restore to previous state
if old_dsrp_tf.lstat(): old_dsrp_tf.rename(dsrp)
if self.incrp: self.incrp.delete()
RobustAction(init_thunk, final, error).execute() RobustAction(init_thunk, final, error).execute()
else: self.incrp = Robust.chain( else: self.incrp = Robust.chain(
Inc.Increment_action(diff_rorp, dsrp, incpref), Inc.Increment_action(diff_rorp, dsrp, incpref),
......
...@@ -54,7 +54,7 @@ class Iter: ...@@ -54,7 +54,7 @@ class Iter:
return None return None
try: i2 = iter2.next() try: i2 = iter2.next()
except StopIteration: return 1 except StopIteration: return 1
if verbose: print "End when i2 = %s" % i2 if verbose: print "End when i2 = %s" % (i2,)
return None return None
def Or(iter): def Or(iter):
......
...@@ -281,19 +281,25 @@ probably isn't what you meant.""" % ...@@ -281,19 +281,25 @@ probably isn't what you meant.""" %
def filelist_read(self, filelist_fp, include, filelist_name): def filelist_read(self, filelist_fp, include, filelist_name):
"""Read filelist from fp, return (tuplelist, something_excluded)""" """Read filelist from fp, return (tuplelist, something_excluded)"""
prefix_warnings = [0]
def incr_warnings(exc):
"""Warn if prefix is incorrect"""
prefix_warnings[0] += 1
if prefix_warnings[0] < 6:
Log("Warning: file specification '%s' in filelist %s\n"
"doesn't start with correct prefix %s. Ignoring." %
(exc, filelist_name, self.prefix), 2)
if prefix_warnings[0] == 5:
Log("Future prefix errors will not be logged.", 2)
something_excluded, tuple_list = None, [] something_excluded, tuple_list = None, []
prefix_warnings = 0 separator = Globals.null_separator and "\0" or "\n"
for line in filelist_fp: for line in filelist_fp.read().split(separator):
if not line.strip(): continue # skip blanks if not line: continue # skip blanks
try: tuple = self.filelist_parse_line(line, include) try: tuple = self.filelist_parse_line(line, include)
except FilePrefixError, exc: except FilePrefixError, exc:
prefix_warnings += 1 incr_warnings(exc)
if prefix_warnings < 6: continue
Log("Warning: file specification %s in filelist %s\n"
"doesn't start with correct prefix %s, ignoring." %
(exc, filelist_name, self.prefix), 2)
if prefix_warnings == 5:
Log("Future prefix errors will not be logged.", 2)
tuple_list.append(tuple) tuple_list.append(tuple)
if not tuple[1]: something_excluded = 1 if not tuple[1]: something_excluded = 1
if filelist_fp.close(): if filelist_fp.close():
......
...@@ -56,15 +56,17 @@ class StatsObj: ...@@ -56,15 +56,17 @@ class StatsObj:
"""Add 1 to value of attribute""" """Add 1 to value of attribute"""
self.__dict__[attr] = self.get_stat(attr) + 1 self.__dict__[attr] = self.get_stat(attr) + 1
def get_stats_line(self, index): def get_stats_line(self, index, use_repr = 1):
"""Return one line abbreviated version of full stats string""" """Return one line abbreviated version of full stats string"""
file_attrs = map(lambda attr: str(self.get_stat(attr)), file_attrs = map(lambda attr: str(self.get_stat(attr)),
self.stat_file_attrs) self.stat_file_attrs)
if not index: filename = "." if not index: filename = "."
else: else:
# use repr to quote newlines in relative filename, then filename = apply(os.path.join, index)
# take of leading and trailing quote. if use_repr:
filename = repr(apply(os.path.join, index))[1:-1] # use repr to quote newlines in relative filename, then
# take of leading and trailing quote.
filename = repr(filename)[1:-1]
return " ".join([filename,] + file_attrs) return " ".join([filename,] + file_attrs)
def set_stats_from_line(self, line): def set_stats_from_line(self, line):
...@@ -227,39 +229,45 @@ class StatsITR(IterTreeReducer, StatsObj): ...@@ -227,39 +229,45 @@ class StatsITR(IterTreeReducer, StatsObj):
""" """
if mirror_dsrp.lstat(): if mirror_dsrp.lstat():
self.mirror_base_exists = 1 self.mirror_base_exists = 1
self.mirror_base_size = mirror_dsrp.getsize() self.mirror_base_size = self.stats_getsize(mirror_dsrp)
else: self.mirror_base_exists = None else: self.mirror_base_exists = None
def stats_getsize(self, rp):
"""Return size of rp, with error checking"""
try: return rp.getsize()
except KeyError: return 0
def end_stats(self, diff_rorp, mirror_dsrp, inc_rp = None): def end_stats(self, diff_rorp, mirror_dsrp, inc_rp = None):
"""Set various statistics after mirror processed""" """Set various statistics after mirror processed"""
if mirror_dsrp.lstat(): if mirror_dsrp.lstat():
source_size = self.stats_getsize(mirror_dsrp)
self.SourceFiles += 1 self.SourceFiles += 1
self.SourceFileSize += mirror_dsrp.getsize() self.SourceFileSize += source_size
if self.mirror_base_exists: if self.mirror_base_exists:
self.MirrorFiles += 1 self.MirrorFiles += 1
self.MirrorFileSize += self.mirror_base_size self.MirrorFileSize += self.mirror_base_size
if diff_rorp: # otherwise no change if diff_rorp: # otherwise no change
self.ChangedFiles += 1 self.ChangedFiles += 1
self.ChangedSourceSize += mirror_dsrp.getsize() self.ChangedSourceSize += source_size
self.ChangedMirrorSize += self.mirror_base_size self.ChangedMirrorSize += self.mirror_base_size
if inc_rp: self.stats_incr_incfiles(inc_rp)
self.IncrementFiles += 1
self.IncrementFileSize += inc_rp.getsize()
else: # new file was created else: # new file was created
self.NewFiles += 1 self.NewFiles += 1
self.NewFileSize += mirror_dsrp.getsize() self.NewFileSize += source_size
if inc_rp: self.stats_incr_incfiles(inc_rp)
self.IncrementFiles += 1
self.IncrementFileSize += inc_rp.getsize()
else: else:
if self.mirror_base_exists: # file was deleted from mirror if self.mirror_base_exists: # file was deleted from mirror
self.MirrorFiles += 1 self.MirrorFiles += 1
self.MirrorFileSize += self.mirror_base_size self.MirrorFileSize += self.mirror_base_size
self.DeletedFiles += 1 self.DeletedFiles += 1
self.DeletedFileSize += self.mirror_base_size self.DeletedFileSize += self.mirror_base_size
if inc_rp: self.stats_incr_incfiles(inc_rp)
self.IncrementFiles += 1
self.IncrementFileSize += inc_rp.getsize() def stats_incr_incfiles(self, inc_rp):
"""Increment IncrementFile statistics"""
if inc_rp:
self.IncrementFiles += 1
self.IncrementFileSize += self.stats_getsize(inc_rp)
def add_file_stats(self, subinstance): def add_file_stats(self, subinstance):
"""Add all file statistics from subinstance to current totals""" """Add all file statistics from subinstance to current totals"""
...@@ -304,7 +312,9 @@ class Stats: ...@@ -304,7 +312,9 @@ class Stats:
def write_dir_stats_line(cls, statobj, index): def write_dir_stats_line(cls, statobj, index):
"""Write info from statobj about rpath to statistics file""" """Write info from statobj about rpath to statistics file"""
cls._dir_stats_fp.write(statobj.get_stats_line(index) +"\n") if Globals.null_separator:
cls._dir_stats_fp.write(statobj.get_stats_line(index, None) + "\0")
else: cls._dir_stats_fp.write(statobj.get_stats_line(index) + "\n")
def close_dir_stats_file(cls): def close_dir_stats_file(cls):
"""Close directory statistics file if its open""" """Close directory statistics file if its open"""
......
...@@ -147,6 +147,10 @@ class Globals: ...@@ -147,6 +147,10 @@ class Globals:
"jpg|gif|png|jp2|mp3|ogg|avi|wmv|mpeg|mpg|rm|mov)$" "jpg|gif|png|jp2|mp3|ogg|avi|wmv|mpeg|mpg|rm|mov)$"
no_compression_regexp = None no_compression_regexp = None
# If true, filelists and directory statistics will be split on
# nulls instead of newlines.
null_separator = None
# Determines whether or not ssh will be run with the -C switch # Determines whether or not ssh will be run with the -C switch
ssh_compression = 1 ssh_compression = 1
......
...@@ -219,6 +219,7 @@ class IncrementITR(ErrorITR, StatsITR): ...@@ -219,6 +219,7 @@ class IncrementITR(ErrorITR, StatsITR):
# Write updated mirror to temp file so we can compute # Write updated mirror to temp file so we can compute
# reverse diff locally # reverse diff locally
mirror_tf = TempFileManager.new(dsrp) mirror_tf = TempFileManager.new(dsrp)
old_dsrp_tf = TempFileManager.new(dsrp)
def init_thunk(): def init_thunk():
if diff_rorp.isflaglinked(): if diff_rorp.isflaglinked():
Hardlink.link_rp(diff_rorp, mirror_tf, dsrp) Hardlink.link_rp(diff_rorp, mirror_tf, dsrp)
...@@ -226,8 +227,16 @@ class IncrementITR(ErrorITR, StatsITR): ...@@ -226,8 +227,16 @@ class IncrementITR(ErrorITR, StatsITR):
mirror_tf).execute() mirror_tf).execute()
self.incrp = Inc.Increment_action(mirror_tf, dsrp, self.incrp = Inc.Increment_action(mirror_tf, dsrp,
incpref).execute() incpref).execute()
def final(init_val): mirror_tf.rename(dsrp) if dsrp.lstat(): RPathStatic.rename(dsrp, old_dsrp_tf)
def error(exc, ran_init, init_val): mirror_tf.delete() mirror_tf.rename(dsrp)
def final(init_val): old_dsrp_tf.delete()
def error(exc, ran_init, init_val):
if ran_init: old_dsrp_tf.delete() # everything is fine
else: # restore to previous state
if old_dsrp_tf.lstat(): old_dsrp_tf.rename(dsrp)
if self.incrp: self.incrp.delete()
RobustAction(init_thunk, final, error).execute() RobustAction(init_thunk, final, error).execute()
else: self.incrp = Robust.chain( else: self.incrp = Robust.chain(
Inc.Increment_action(diff_rorp, dsrp, incpref), Inc.Increment_action(diff_rorp, dsrp, incpref),
......
...@@ -54,7 +54,7 @@ class Iter: ...@@ -54,7 +54,7 @@ class Iter:
return None return None
try: i2 = iter2.next() try: i2 = iter2.next()
except StopIteration: return 1 except StopIteration: return 1
if verbose: print "End when i2 = %s" % i2 if verbose: print "End when i2 = %s" % (i2,)
return None return None
def Or(iter): def Or(iter):
......
...@@ -33,9 +33,9 @@ class Main: ...@@ -33,9 +33,9 @@ class Main:
"include-filelist=", "include-filelist-stdin", "include-filelist=", "include-filelist-stdin",
"include-regexp=", "list-increments", "mirror-only", "include-regexp=", "list-increments", "mirror-only",
"no-compression", "no-compression-regexp=", "no-compression", "no-compression-regexp=",
"no-hard-links", "no-resume", "parsable-output", "no-hard-links", "no-resume", "null-separator",
"print-statistics", "quoting-char=", "remote-cmd=", "parsable-output", "print-statistics", "quoting-char=",
"remote-schema=", "remove-older-than=", "remote-cmd=", "remote-schema=", "remove-older-than=",
"restore-as-of=", "resume", "resume-window=", "server", "restore-as-of=", "resume", "resume-window=", "server",
"ssh-no-compression", "terminal-verbosity=", "ssh-no-compression", "terminal-verbosity=",
"test-server", "verbosity", "version", "windows-mode", "test-server", "verbosity", "version", "windows-mode",
...@@ -88,6 +88,7 @@ class Main: ...@@ -88,6 +88,7 @@ class Main:
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 == '--no-resume': Globals.resume = 0
elif opt == "--null-separator": Globals.set("null_separator", 1)
elif opt == "-r" or opt == "--restore-as-of": elif opt == "-r" or opt == "--restore-as-of":
self.restore_timestr = arg self.restore_timestr = arg
self.action = "restore-as-of" self.action = "restore-as-of"
......
...@@ -281,19 +281,25 @@ probably isn't what you meant.""" % ...@@ -281,19 +281,25 @@ probably isn't what you meant.""" %
def filelist_read(self, filelist_fp, include, filelist_name): def filelist_read(self, filelist_fp, include, filelist_name):
"""Read filelist from fp, return (tuplelist, something_excluded)""" """Read filelist from fp, return (tuplelist, something_excluded)"""
prefix_warnings = [0]
def incr_warnings(exc):
"""Warn if prefix is incorrect"""
prefix_warnings[0] += 1
if prefix_warnings[0] < 6:
Log("Warning: file specification '%s' in filelist %s\n"
"doesn't start with correct prefix %s. Ignoring." %
(exc, filelist_name, self.prefix), 2)
if prefix_warnings[0] == 5:
Log("Future prefix errors will not be logged.", 2)
something_excluded, tuple_list = None, [] something_excluded, tuple_list = None, []
prefix_warnings = 0 separator = Globals.null_separator and "\0" or "\n"
for line in filelist_fp: for line in filelist_fp.read().split(separator):
if not line.strip(): continue # skip blanks if not line: continue # skip blanks
try: tuple = self.filelist_parse_line(line, include) try: tuple = self.filelist_parse_line(line, include)
except FilePrefixError, exc: except FilePrefixError, exc:
prefix_warnings += 1 incr_warnings(exc)
if prefix_warnings < 6: continue
Log("Warning: file specification %s in filelist %s\n"
"doesn't start with correct prefix %s, ignoring." %
(exc, filelist_name, self.prefix), 2)
if prefix_warnings == 5:
Log("Future prefix errors will not be logged.", 2)
tuple_list.append(tuple) tuple_list.append(tuple)
if not tuple[1]: something_excluded = 1 if not tuple[1]: something_excluded = 1
if filelist_fp.close(): if filelist_fp.close():
......
...@@ -56,15 +56,17 @@ class StatsObj: ...@@ -56,15 +56,17 @@ class StatsObj:
"""Add 1 to value of attribute""" """Add 1 to value of attribute"""
self.__dict__[attr] = self.get_stat(attr) + 1 self.__dict__[attr] = self.get_stat(attr) + 1
def get_stats_line(self, index): def get_stats_line(self, index, use_repr = 1):
"""Return one line abbreviated version of full stats string""" """Return one line abbreviated version of full stats string"""
file_attrs = map(lambda attr: str(self.get_stat(attr)), file_attrs = map(lambda attr: str(self.get_stat(attr)),
self.stat_file_attrs) self.stat_file_attrs)
if not index: filename = "." if not index: filename = "."
else: else:
# use repr to quote newlines in relative filename, then filename = apply(os.path.join, index)
# take of leading and trailing quote. if use_repr:
filename = repr(apply(os.path.join, index))[1:-1] # use repr to quote newlines in relative filename, then
# take of leading and trailing quote.
filename = repr(filename)[1:-1]
return " ".join([filename,] + file_attrs) return " ".join([filename,] + file_attrs)
def set_stats_from_line(self, line): def set_stats_from_line(self, line):
...@@ -227,39 +229,45 @@ class StatsITR(IterTreeReducer, StatsObj): ...@@ -227,39 +229,45 @@ class StatsITR(IterTreeReducer, StatsObj):
""" """
if mirror_dsrp.lstat(): if mirror_dsrp.lstat():
self.mirror_base_exists = 1 self.mirror_base_exists = 1
self.mirror_base_size = mirror_dsrp.getsize() self.mirror_base_size = self.stats_getsize(mirror_dsrp)
else: self.mirror_base_exists = None else: self.mirror_base_exists = None
def stats_getsize(self, rp):
"""Return size of rp, with error checking"""
try: return rp.getsize()
except KeyError: return 0
def end_stats(self, diff_rorp, mirror_dsrp, inc_rp = None): def end_stats(self, diff_rorp, mirror_dsrp, inc_rp = None):
"""Set various statistics after mirror processed""" """Set various statistics after mirror processed"""
if mirror_dsrp.lstat(): if mirror_dsrp.lstat():
source_size = self.stats_getsize(mirror_dsrp)
self.SourceFiles += 1 self.SourceFiles += 1
self.SourceFileSize += mirror_dsrp.getsize() self.SourceFileSize += source_size
if self.mirror_base_exists: if self.mirror_base_exists:
self.MirrorFiles += 1 self.MirrorFiles += 1
self.MirrorFileSize += self.mirror_base_size self.MirrorFileSize += self.mirror_base_size
if diff_rorp: # otherwise no change if diff_rorp: # otherwise no change
self.ChangedFiles += 1 self.ChangedFiles += 1
self.ChangedSourceSize += mirror_dsrp.getsize() self.ChangedSourceSize += source_size
self.ChangedMirrorSize += self.mirror_base_size self.ChangedMirrorSize += self.mirror_base_size
if inc_rp: self.stats_incr_incfiles(inc_rp)
self.IncrementFiles += 1
self.IncrementFileSize += inc_rp.getsize()
else: # new file was created else: # new file was created
self.NewFiles += 1 self.NewFiles += 1
self.NewFileSize += mirror_dsrp.getsize() self.NewFileSize += source_size
if inc_rp: self.stats_incr_incfiles(inc_rp)
self.IncrementFiles += 1
self.IncrementFileSize += inc_rp.getsize()
else: else:
if self.mirror_base_exists: # file was deleted from mirror if self.mirror_base_exists: # file was deleted from mirror
self.MirrorFiles += 1 self.MirrorFiles += 1
self.MirrorFileSize += self.mirror_base_size self.MirrorFileSize += self.mirror_base_size
self.DeletedFiles += 1 self.DeletedFiles += 1
self.DeletedFileSize += self.mirror_base_size self.DeletedFileSize += self.mirror_base_size
if inc_rp: self.stats_incr_incfiles(inc_rp)
self.IncrementFiles += 1
self.IncrementFileSize += inc_rp.getsize() def stats_incr_incfiles(self, inc_rp):
"""Increment IncrementFile statistics"""
if inc_rp:
self.IncrementFiles += 1
self.IncrementFileSize += self.stats_getsize(inc_rp)
def add_file_stats(self, subinstance): def add_file_stats(self, subinstance):
"""Add all file statistics from subinstance to current totals""" """Add all file statistics from subinstance to current totals"""
...@@ -304,7 +312,9 @@ class Stats: ...@@ -304,7 +312,9 @@ class Stats:
def write_dir_stats_line(cls, statobj, index): def write_dir_stats_line(cls, statobj, index):
"""Write info from statobj about rpath to statistics file""" """Write info from statobj about rpath to statistics file"""
cls._dir_stats_fp.write(statobj.get_stats_line(index) +"\n") if Globals.null_separator:
cls._dir_stats_fp.write(statobj.get_stats_line(index, None) + "\0")
else: cls._dir_stats_fp.write(statobj.get_stats_line(index) + "\n")
def close_dir_stats_file(cls): def close_dir_stats_file(cls):
"""Close directory statistics file if its open""" """Close directory statistics file if its open"""
......
...@@ -13,7 +13,7 @@ testfiles ...@@ -13,7 +13,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
......
...@@ -90,11 +90,29 @@ testfiles/select/3/3/2""") ...@@ -90,11 +90,29 @@ testfiles/select/3/3/2""")
assert sf(self.makeext("3/3")) == 1 assert sf(self.makeext("3/3")) == 1
assert sf(self.makeext("3/3/3")) == None assert sf(self.makeext("3/3/3")) == None
def testFilelistIncludeNullSep(self):
"""Test included filelist but with null_separator set"""
fp = StringIO.StringIO("""\0testfiles/select/1/2\0testfiles/select/1\0testfiles/select/1/2/3\0testfiles/select/3/3/2\0testfiles/select/hello\nthere\0""")
Globals.null_separator = 1
sf = self.Select.filelist_get_sf(fp, 1, "test")
assert sf(self.root) == 1
assert sf(self.makeext("1")) == 1
assert sf(self.makeext("1/1")) == None
assert sf(self.makeext("1/2/3")) == 1
assert sf(self.makeext("2/2")) == None
assert sf(self.makeext("3")) == 1
assert sf(self.makeext("3/3")) == 1
assert sf(self.makeext("3/3/3")) == None
assert sf(self.makeext("hello\nthere")) == 1
Globals.null_separator = 1
def testFilelistExclude(self): def testFilelistExclude(self):
"""Test included filelist""" """Test included filelist"""
fp = StringIO.StringIO(""" fp = StringIO.StringIO("""
testfiles/select/1/2 testfiles/select/1/2
testfiles/select/1 testfiles/select/1
this is a badly formed line which should be ignored
testfiles/select/1/2/3 testfiles/select/1/2/3
testfiles/select/3/3/2""") testfiles/select/3/3/2""")
sf = self.Select.filelist_get_sf(fp, 0, "test") sf = self.Select.filelist_get_sf(fp, 0, "test")
......
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