فهرست منبع

Fix minor bugs in IncludePattern and ExcludePattern, and speed up
ExcludePattern by storing a compiled regular expression.

Dan Christensen 11 سال پیش
والد
کامیت
9c5e3d4ddc
1فایلهای تغییر یافته به همراه21 افزوده شده و 12 حذف شده
  1. 21 12
      attic/helpers.py

+ 21 - 12
attic/helpers.py

@@ -9,7 +9,7 @@ import stat
 import sys
 import sys
 import time
 import time
 from datetime import datetime, timezone
 from datetime import datetime, timezone
-from fnmatch import fnmatchcase
+from fnmatch import translate
 from operator import attrgetter
 from operator import attrgetter
 import fcntl
 import fcntl
 
 
@@ -150,7 +150,7 @@ def adjust_patterns(paths, excludes):
 
 
 def exclude_path(path, patterns):
 def exclude_path(path, patterns):
     """Used by create and extract sub-commands to determine
     """Used by create and extract sub-commands to determine
-    if an item should be processed or not
+    whether or not an item should be processed.
     """
     """
     for pattern in (patterns or []):
     for pattern in (patterns or []):
         if pattern.match(path):
         if pattern.match(path):
@@ -159,31 +159,40 @@ def exclude_path(path, patterns):
 
 
 
 
 class IncludePattern:
 class IncludePattern:
-    """--include PATTERN
+    """Literal files or directories listed on the command line
+    for some operations (e.g. extract, but create).
+    If a directory is specified, all paths that start with that
+    path match as well.  A trailing slash makes no difference.
     """
     """
     def __init__(self, pattern):
     def __init__(self, pattern):
-        self.pattern = pattern
+        self.pattern = pattern.rstrip(os.path.sep)
 
 
     def match(self, path):
     def match(self, path):
-        dir, name = os.path.split(path)
         return (path == self.pattern
         return (path == self.pattern
-                or (dir + os.path.sep).startswith(self.pattern))
+                or path.startswith(self.pattern+os.path.sep))
 
 
     def __repr__(self):
     def __repr__(self):
         return '%s(%s)' % (type(self), self.pattern)
         return '%s(%s)' % (type(self), self.pattern)
 
 
 
 
 class ExcludePattern(IncludePattern):
 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):
     def __init__(self, pattern):
-        self.pattern = self.dirpattern = pattern
-        if not pattern.endswith('/'):
-            self.dirpattern += '/*'
+        self.pattern = pattern
+        # fnmatch and re.match both cache compiled regular expressions.
+        # Nevertheless, this is about 10 times faster.
+        if pattern.endswith(os.path.sep):
+            regex = translate(pattern+'*')
+        else:
+            regex1 = translate(pattern)
+            regex2 = translate(pattern+os.path.sep+'*')
+            regex = '(' + regex1 + ')|(' + regex2 + ')'
+        self.regobj = re.compile(regex)
 
 
     def match(self, path):
     def match(self, path):
-        dir, name = os.path.split(path)
-        return fnmatchcase(path, self.pattern) or fnmatchcase(dir + '/', self.dirpattern)
+        return self.regobj.match(path) is not None
 
 
     def __repr__(self):
     def __repr__(self):
         return '%s(%s)' % (type(self), self.pattern)
         return '%s(%s)' % (type(self), self.pattern)