Add support for --exclude-from.

This commit is contained in:
Dan Christensen 2014-02-08 12:44:48 -05:00
parent 2252616f9e
commit 9d19550c1a
3 changed files with 31 additions and 1 deletions

View File

@ -13,7 +13,8 @@ from attic.cache import Cache
from attic.key import key_creator
from attic.helpers import Error, location_validator, format_time, \
format_file_mode, ExcludePattern, exclude_path, adjust_patterns, to_localtime, \
get_cache_dir, get_keys_dir, format_timedelta, prune_split, Manifest, remove_surrogates, is_a_terminal
get_cache_dir, get_keys_dir, format_timedelta, prune_split, Manifest, remove_surrogates, \
is_a_terminal, update_excludes
from attic.remote import RepositoryServer, RemoteRepository
@ -403,6 +404,9 @@ class Archiver:
subparser.add_argument('-e', '--exclude', dest='excludes',
type=ExcludePattern, action='append',
metavar="PATTERN", help='exclude paths matching PATTERN')
subparser.add_argument('--exclude-from', dest='exclude_files',
type=argparse.FileType('r'), action='append',
metavar='EXCLUDEFILE', help='read exclude patterns from EXCLUDEFILE, one per line')
subparser.add_argument('-c', '--checkpoint-interval', dest='checkpoint_interval',
type=int, default=300, metavar='SECONDS',
help='write checkpoint every SECONDS seconds (Default: 300)')
@ -424,6 +428,9 @@ class Archiver:
subparser.add_argument('-e', '--exclude', dest='excludes',
type=ExcludePattern, action='append',
metavar="PATTERN", help='exclude paths matching PATTERN')
subparser.add_argument('--exclude-from', dest='exclude_files',
type=argparse.FileType('r'), action='append',
metavar='EXCLUDEFILE', help='read exclude patterns from EXCLUDEFILE, one per line')
subparser.add_argument('--numeric-owner', dest='numeric_owner',
action='store_true', default=False,
help='only obey numeric user and group identifiers')
@ -465,6 +472,9 @@ class Archiver:
subparser.add_argument('-e', '--exclude', dest='excludes',
type=ExcludePattern, action='append',
metavar="PATTERN", help='exclude paths matching PATTERN')
subparser.add_argument('--exclude-from', dest='exclude_files',
type=argparse.FileType('r'), action='append',
metavar='EXCLUDEFILE', help='read exclude patterns from EXCLUDEFILE, one per line')
subparser.add_argument('archive', metavar='ARCHIVE',
type=location_validator(archive=True),
help='archive to verity integrity of')
@ -512,6 +522,7 @@ class Archiver:
help='repository to prune')
args = parser.parse_args(args or ['-h'])
self.verbose = args.verbose
update_excludes(args)
return args.func(args)

View File

@ -141,6 +141,19 @@ def to_localtime(ts):
return datetime(*time.localtime((ts - datetime(1970, 1, 1, tzinfo=timezone.utc)).total_seconds())[:6])
def update_excludes(args):
"""Merge exclude patterns from files with those on command line.
Empty lines and lines starting with '#' are ignored, but whitespace
is not stripped."""
if hasattr(args, 'exclude_files') and args.exclude_files:
if not hasattr(args, 'excludes') or args.excludes is None:
args.excludes = []
for file in args.exclude_files:
patterns = [line.rstrip('\r\n') for line in file if not line.startswith('#')]
args.excludes += [ExcludePattern(pattern) for pattern in patterns if pattern]
file.close()
def adjust_patterns(paths, excludes):
if paths:
return (excludes or []) + [IncludePattern(path) for path in paths] + [ExcludePattern('*')]

View File

@ -48,12 +48,15 @@ class ArchiverTestCase(AtticTestCase):
self.output_path = os.path.join(self.tmpdir, 'output')
self.keys_path = os.path.join(self.tmpdir, 'keys')
self.cache_path = os.path.join(self.tmpdir, 'cache')
self.exclude_file_path = os.path.join(self.tmpdir, 'excludes')
os.environ['ATTIC_KEYS_DIR'] = self.keys_path
os.environ['ATTIC_CACHE_DIR'] = self.cache_path
os.mkdir(self.input_path)
os.mkdir(self.output_path)
os.mkdir(self.keys_path)
os.mkdir(self.cache_path)
with open(self.exclude_file_path, 'wb') as fd:
fd.write(b'input/file2\n# A commment line, then a blank line\n\n')
self._old_wd = os.getcwd()
os.chdir(self.tmpdir)
@ -157,6 +160,9 @@ class ArchiverTestCase(AtticTestCase):
with changedir('output'):
self.attic('extract', '--exclude=input/file2', self.repository_location + '::test')
self.assert_equal(sorted(os.listdir('output/input')), ['file1', 'file3'])
with changedir('output'):
self.attic('extract', '--exclude-from=' + self.exclude_file_path, self.repository_location + '::test')
self.assert_equal(sorted(os.listdir('output/input')), ['file1', 'file3'])
def test_path_normalization(self):
self.attic('init', self.repository_location)