Browse Source

Merge pull request #212 from ThomasWaldmann/match-counting

Match counting
TW 9 years ago
parent
commit
07ff905276
2 changed files with 25 additions and 3 deletions
  1. 4 1
      borg/archiver.py
  2. 21 2
      borg/helpers.py

+ 4 - 1
borg/archiver.py

@@ -21,7 +21,7 @@ from .repository import Repository
 from .cache import Cache
 from .cache import Cache
 from .key import key_creator
 from .key import key_creator
 from .helpers import Error, location_validator, format_time, format_file_size, \
 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, \
     get_cache_dir, get_keys_dir, format_timedelta, prune_within, prune_split, \
     Manifest, remove_surrogates, update_excludes, format_archive, check_extension_modules, Statistics, \
     Manifest, remove_surrogates, update_excludes, format_archive, check_extension_modules, Statistics, \
     is_cachedir, bigint_to_int, ChunkerParams, CompressionSpec
     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:
         if not args.dry_run:
             while dirs:
             while dirs:
                 archive.extract_item(dirs.pop(-1))
                 archive.extract_item(dirs.pop(-1))
+        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
         return self.exit_code
 
 
     def do_rename(self, args):
     def do_rename(self, args):

+ 21 - 2
borg/helpers.py

@@ -242,6 +242,7 @@ def normalized(func):
         # always have to enter an exact match
         # always have to enter an exact match
         return func
         return func
 
 
+
 class IncludePattern:
 class IncludePattern:
     """Literal files or directories listed on the command line
     """Literal files or directories listed on the command line
     for some operations (e.g. extract, but not create).
     for some operations (e.g. extract, but not create).
@@ -249,6 +250,9 @@ class IncludePattern:
     path match as well.  A trailing slash makes no difference.
     path match as well.  A trailing slash makes no difference.
     """
     """
     def __init__(self, pattern):
     def __init__(self, pattern):
+        self.pattern_orig = pattern
+        self.match_count = 0
+
         if sys.platform in ('darwin',):
         if sys.platform in ('darwin',):
             pattern = unicodedata.normalize("NFD", pattern)
             pattern = unicodedata.normalize("NFD", pattern)
 
 
@@ -256,17 +260,26 @@ class IncludePattern:
 
 
     @normalized
     @normalized
     def match(self, path):
     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):
     def __repr__(self):
         return '%s(%s)' % (type(self), self.pattern)
         return '%s(%s)' % (type(self), self.pattern)
 
 
+    def __str__(self):
+        return self.pattern_orig
+
 
 
 class ExcludePattern(IncludePattern):
 class ExcludePattern(IncludePattern):
     """Shell glob patterns to exclude.  A trailing slash means to
     """Shell glob patterns to exclude.  A trailing slash means to
     exclude the contents of a directory, but not the directory itself.
     exclude the contents of a directory, but not the directory itself.
     """
     """
     def __init__(self, pattern):
     def __init__(self, pattern):
+        self.pattern_orig = pattern
+        self.match_count = 0
+
         if pattern.endswith(os.path.sep):
         if pattern.endswith(os.path.sep):
             self.pattern = os.path.normpath(pattern).rstrip(os.path.sep)+os.path.sep+'*'+os.path.sep
             self.pattern = os.path.normpath(pattern).rstrip(os.path.sep)+os.path.sep+'*'+os.path.sep
         else:
         else:
@@ -281,11 +294,17 @@ class ExcludePattern(IncludePattern):
 
 
     @normalized
     @normalized
     def match(self, path):
     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):
     def __repr__(self):
         return '%s(%s)' % (type(self), self.pattern)
         return '%s(%s)' % (type(self), self.pattern)
 
 
+    def __str__(self):
+        return self.pattern_orig
+
 
 
 def timestamp(s):
 def timestamp(s):
     """Convert a --timestamp=s argument to a datetime object"""
     """Convert a --timestamp=s argument to a datetime object"""