Browse Source

Experimental --include/exclude support

Jonas Borgström 14 years ago
parent
commit
6fe6812df2
3 changed files with 66 additions and 2 deletions
  1. 18 1
      darc/archiver.py
  2. 45 0
      darc/helpers.py
  3. 3 1
      darc/test.py

+ 18 - 1
darc/archiver.py

@@ -8,7 +8,8 @@ from .archive import Archive
 from .store import Store
 from .store import Store
 from .cache import Cache
 from .cache import Cache
 from .keychain import Keychain
 from .keychain import Keychain
-from .helpers import location_validator, format_file_size, format_time, format_file_mode, walk_dir
+from .helpers import location_validator, format_file_size, format_time,\
+    format_file_mode, walk_dir, IncludePattern, ExcludePattern, exclude_path
 
 
 
 
 class Archiver(object):
 class Archiver(object):
@@ -50,6 +51,8 @@ class Archiver(object):
         cache = Cache(store, keychain)
         cache = Cache(store, keychain)
         for path in args.paths:
         for path in args.paths:
             for path, st in walk_dir(unicode(path)):
             for path, st in walk_dir(unicode(path)):
+                if exclude_path(path, args.patterns):
+                    continue
                 self.print_verbose(path)
                 self.print_verbose(path)
                 if stat.S_ISDIR(st.st_mode):
                 if stat.S_ISDIR(st.st_mode):
                     archive.process_dir(path, st)
                     archive.process_dir(path, st)
@@ -75,6 +78,8 @@ class Archiver(object):
         archive.get_items()
         archive.get_items()
         dirs = []
         dirs = []
         for item in archive.items:
         for item in archive.items:
+            if exclude_path(item['path'], args.patterns):
+                continue
             self.print_verbose(item['path'])
             self.print_verbose(item['path'])
             archive.extract_item(item, args.dest)
             archive.extract_item(item, args.dest)
             if stat.S_ISDIR(item['mode']):
             if stat.S_ISDIR(item['mode']):
@@ -186,6 +191,12 @@ class Archiver(object):
 
 
         subparser = subparsers.add_parser('create')
         subparser = subparsers.add_parser('create')
         subparser.set_defaults(func=self.do_create)
         subparser.set_defaults(func=self.do_create)
+        subparser.add_argument('-i', '--include', dest='patterns',
+                               type=IncludePattern, action='append',
+                               help='Include condition')
+        subparser.add_argument('-e', '--exclude', dest='patterns',
+                               type=ExcludePattern, action='append',
+                               help='Include condition')
         subparser.add_argument('archive', metavar='ARCHIVE',
         subparser.add_argument('archive', metavar='ARCHIVE',
                                type=location_validator(archive=True),
                                type=location_validator(archive=True),
                                help='Archive to create')
                                help='Archive to create')
@@ -194,6 +205,12 @@ class Archiver(object):
 
 
         subparser = subparsers.add_parser('extract')
         subparser = subparsers.add_parser('extract')
         subparser.set_defaults(func=self.do_extract)
         subparser.set_defaults(func=self.do_extract)
+        subparser.add_argument('-i', '--include', dest='patterns',
+                               type=IncludePattern, action='append',
+                               help='Include condition')
+        subparser.add_argument('-e', '--exclude', dest='patterns',
+                               type=ExcludePattern, action='append',
+                               help='Include condition')
         subparser.add_argument('archive', metavar='ARCHIVE',
         subparser.add_argument('archive', metavar='ARCHIVE',
                                type=location_validator(archive=True),
                                type=location_validator(archive=True),
                                help='Archive to create')
                                help='Archive to create')

+ 45 - 0
darc/helpers.py

@@ -1,5 +1,6 @@
 import argparse
 import argparse
 from datetime import datetime
 from datetime import datetime
+from fnmatch import fnmatchcase
 import grp
 import grp
 import os
 import os
 import pwd
 import pwd
@@ -7,6 +8,50 @@ import re
 import stat
 import stat
 
 
 
 
+def exclude_path(path, patterns):
+    """Used by create and extract sub-commands to determine
+    if an item should be processed or not
+    """
+    for pattern in (patterns or []):
+        if pattern.match(path):
+            return isinstance(pattern, ExcludePattern)
+    return False
+
+
+class IncludePattern(object):
+    """--include PATTERN
+
+    >>> py = IncludePattern('*.py')
+    >>> foo = IncludePattern('/foo')
+    >>> py.match('/foo/foo.py')
+    True
+    >>> py.match('/bar/foo.java')
+    False
+    >>> foo.match('/foo/foo.py')
+    True
+    >>> foo.match('/bar/foo.java')
+    False
+    >>> foo.match('/foobar/foo.py')
+    False
+    """
+    def __init__(self, pattern):
+        self.pattern = self.dirpattern = pattern
+        if not pattern.endswith(os.path.sep):
+            self.dirpattern += os.path.sep
+
+    def match(self, path):
+        dir, name = os.path.split(path)
+        return (dir + os.path.sep).startswith(self.dirpattern) or fnmatchcase(name, self.pattern)
+
+    def __repr__(self):
+        return '%s(%s)' % (type(self), self.pattern)
+
+
+class ExcludePattern(IncludePattern):
+    """
+    """
+
+
 def walk_dir(path):
 def walk_dir(path):
     st = os.lstat(path)
     st = os.lstat(path)
     yield path, st
     yield path, st

+ 3 - 1
darc/test.py

@@ -1,3 +1,4 @@
+import doctest
 import filecmp
 import filecmp
 import os
 import os
 from StringIO import StringIO
 from StringIO import StringIO
@@ -10,7 +11,7 @@ from xattr import xattr, XATTR_NOFOLLOW
 import getpass
 import getpass
 getpass.getpass = lambda m: 'abc123'
 getpass.getpass = lambda m: 'abc123'
 
 
-from . import store
+from . import store, helpers
 from .archiver import Archiver
 from .archiver import Archiver
 
 
 
 
@@ -118,6 +119,7 @@ def suite():
     suite = unittest.TestSuite()
     suite = unittest.TestSuite()
     suite.addTest(unittest.TestLoader().loadTestsFromTestCase(Test))
     suite.addTest(unittest.TestLoader().loadTestsFromTestCase(Test))
     suite.addTest(store.suite())
     suite.addTest(store.suite())
+    suite.addTest(doctest.DocTestSuite(helpers))
     return suite
     return suite
 
 
 if __name__ == '__main__':
 if __name__ == '__main__':