From 6fe6812df25279d9a19ff7573a96712940561380 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Borgstr=C3=B6m?= Date: Tue, 2 Nov 2010 22:47:39 +0100 Subject: [PATCH] Experimental --include/exclude support --- darc/archiver.py | 19 ++++++++++++++++++- darc/helpers.py | 45 +++++++++++++++++++++++++++++++++++++++++++++ darc/test.py | 4 +++- 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/darc/archiver.py b/darc/archiver.py index d2b965424..5e1f0d6eb 100644 --- a/darc/archiver.py +++ b/darc/archiver.py @@ -8,7 +8,8 @@ from .archive import Archive from .store import Store from .cache import Cache 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): @@ -50,6 +51,8 @@ class Archiver(object): cache = Cache(store, keychain) for path in args.paths: for path, st in walk_dir(unicode(path)): + if exclude_path(path, args.patterns): + continue self.print_verbose(path) if stat.S_ISDIR(st.st_mode): archive.process_dir(path, st) @@ -75,6 +78,8 @@ class Archiver(object): archive.get_items() dirs = [] for item in archive.items: + if exclude_path(item['path'], args.patterns): + continue self.print_verbose(item['path']) archive.extract_item(item, args.dest) if stat.S_ISDIR(item['mode']): @@ -186,6 +191,12 @@ class Archiver(object): subparser = subparsers.add_parser('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', type=location_validator(archive=True), help='Archive to create') @@ -194,6 +205,12 @@ class Archiver(object): subparser = subparsers.add_parser('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', type=location_validator(archive=True), help='Archive to create') diff --git a/darc/helpers.py b/darc/helpers.py index b9d4da40f..28261b05a 100644 --- a/darc/helpers.py +++ b/darc/helpers.py @@ -1,5 +1,6 @@ import argparse from datetime import datetime +from fnmatch import fnmatchcase import grp import os import pwd @@ -7,6 +8,50 @@ import re 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): st = os.lstat(path) yield path, st diff --git a/darc/test.py b/darc/test.py index ffd36e168..f6cbe475d 100644 --- a/darc/test.py +++ b/darc/test.py @@ -1,3 +1,4 @@ +import doctest import filecmp import os from StringIO import StringIO @@ -10,7 +11,7 @@ from xattr import xattr, XATTR_NOFOLLOW import getpass getpass.getpass = lambda m: 'abc123' -from . import store +from . import store, helpers from .archiver import Archiver @@ -118,6 +119,7 @@ def suite(): suite = unittest.TestSuite() suite.addTest(unittest.TestLoader().loadTestsFromTestCase(Test)) suite.addTest(store.suite()) + suite.addTest(doctest.DocTestSuite(helpers)) return suite if __name__ == '__main__':