From 08417b52ec0b6848ecd5617424aedf4c40acf28f Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sat, 19 Sep 2015 17:48:41 +0200 Subject: [PATCH 1/4] implement counters for Include/ExcludePatterns --- borg/helpers.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/borg/helpers.py b/borg/helpers.py index 9dab70aa8..820efa9ed 100644 --- a/borg/helpers.py +++ b/borg/helpers.py @@ -242,6 +242,7 @@ def normalized(func): # always have to enter an exact match return func + class IncludePattern: """Literal files or directories listed on the command line for some operations (e.g. extract, but not create). @@ -249,6 +250,8 @@ class IncludePattern: path match as well. A trailing slash makes no difference. """ def __init__(self, pattern): + self.match_count = 0 + if sys.platform in ('darwin',): pattern = unicodedata.normalize("NFD", pattern) @@ -256,7 +259,10 @@ class IncludePattern: @normalized def match(self, path): - return (path+os.path.sep).startswith(self.pattern) + matches = (path+os.path.sep).startswith(self.pattern) + if matches: + self.match_count += 1 + return matches def __repr__(self): return '%s(%s)' % (type(self), self.pattern) @@ -267,6 +273,8 @@ class ExcludePattern(IncludePattern): exclude the contents of a directory, but not the directory itself. """ def __init__(self, pattern): + self.match_count = 0 + if pattern.endswith(os.path.sep): self.pattern = os.path.normpath(pattern).rstrip(os.path.sep)+os.path.sep+'*'+os.path.sep else: @@ -281,7 +289,10 @@ class ExcludePattern(IncludePattern): @normalized def match(self, path): - return self.regex.match(path+os.path.sep) is not None + matches = self.regex.match(path+os.path.sep) is not None + if matches: + self.match_count += 1 + return matches def __repr__(self): return '%s(%s)' % (type(self), self.pattern) From 15b003e344cfbad046f99eee9686fcb6dd85af5c Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sat, 19 Sep 2015 18:03:53 +0200 Subject: [PATCH 2/4] add a string representation for Include/ExcludePattern it just gives the original string that was used. --- borg/helpers.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/borg/helpers.py b/borg/helpers.py index 820efa9ed..f9450c1b8 100644 --- a/borg/helpers.py +++ b/borg/helpers.py @@ -250,6 +250,7 @@ class IncludePattern: path match as well. A trailing slash makes no difference. """ def __init__(self, pattern): + self.pattern_orig = pattern self.match_count = 0 if sys.platform in ('darwin',): @@ -267,12 +268,16 @@ class IncludePattern: def __repr__(self): return '%s(%s)' % (type(self), self.pattern) + def __str__(self): + return self.pattern_orig + class ExcludePattern(IncludePattern): """Shell glob patterns to exclude. A trailing slash means to exclude the contents of a directory, but not the directory itself. """ def __init__(self, pattern): + self.pattern_orig = pattern self.match_count = 0 if pattern.endswith(os.path.sep): @@ -297,6 +302,9 @@ class ExcludePattern(IncludePattern): def __repr__(self): return '%s(%s)' % (type(self), self.pattern) + def __str__(self): + return self.pattern_orig + def timestamp(s): """Convert a --timestamp=s argument to a datetime object""" From e0a08c5caeafdd920a2e98d3755b7beded2d8d5f Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sat, 19 Sep 2015 18:16:47 +0200 Subject: [PATCH 3/4] borg extract: warn if a include pattern never matched, fixes #209 --- borg/archiver.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/borg/archiver.py b/borg/archiver.py index e393fad0d..75b6e72b6 100644 --- a/borg/archiver.py +++ b/borg/archiver.py @@ -21,7 +21,7 @@ from .repository import Repository from .cache import Cache from .key import key_creator from .helpers import Error, location_validator, format_time, format_file_size, \ - format_file_mode, ExcludePattern, exclude_path, adjust_patterns, to_localtime, timestamp, \ + format_file_mode, ExcludePattern, IncludePattern, exclude_path, adjust_patterns, to_localtime, timestamp, \ get_cache_dir, get_keys_dir, format_timedelta, prune_within, prune_split, \ Manifest, remove_surrogates, update_excludes, format_archive, check_extension_modules, Statistics, \ is_cachedir, bigint_to_int, ChunkerParams, CompressionSpec @@ -286,6 +286,9 @@ Type "Yes I am sure" if you understand this and want to continue.\n""") if not args.dry_run: while dirs: archive.extract_item(dirs.pop(-1)) + for pattern in patterns: + if isinstance(pattern, IncludePattern) and pattern.match_count == 0: + self.print_error("Warning: Include pattern '%s' never matched.", pattern) return self.exit_code def do_rename(self, args): From ab76176553047d101a14c1ed92eba664044100c1 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sat, 19 Sep 2015 18:38:44 +0200 Subject: [PATCH 4/4] fix: patterns might be None --- borg/archiver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/borg/archiver.py b/borg/archiver.py index 75b6e72b6..28f1d8a3f 100644 --- a/borg/archiver.py +++ b/borg/archiver.py @@ -286,7 +286,7 @@ Type "Yes I am sure" if you understand this and want to continue.\n""") if not args.dry_run: while dirs: archive.extract_item(dirs.pop(-1)) - for pattern in patterns: + for pattern in (patterns or []): if isinstance(pattern, IncludePattern) and pattern.match_count == 0: self.print_error("Warning: Include pattern '%s' never matched.", pattern) return self.exit_code