Explorar el Código

Add support for --exclude-from.

Dan Christensen hace 11 años
padre
commit
9d19550c1a
Se han modificado 3 ficheros con 31 adiciones y 1 borrados
  1. 12 1
      attic/archiver.py
  2. 13 0
      attic/helpers.py
  3. 6 0
      attic/testsuite/archiver.py

+ 12 - 1
attic/archiver.py

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

+ 13 - 0
attic/helpers.py

@@ -141,6 +141,19 @@ def to_localtime(ts):
     return datetime(*time.localtime((ts - datetime(1970, 1, 1, tzinfo=timezone.utc)).total_seconds())[:6])
     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):
 def adjust_patterns(paths, excludes):
     if paths:
     if paths:
         return (excludes or []) + [IncludePattern(path) for path in paths] + [ExcludePattern('*')]
         return (excludes or []) + [IncludePattern(path) for path in paths] + [ExcludePattern('*')]

+ 6 - 0
attic/testsuite/archiver.py

@@ -48,12 +48,15 @@ class ArchiverTestCase(AtticTestCase):
         self.output_path = os.path.join(self.tmpdir, 'output')
         self.output_path = os.path.join(self.tmpdir, 'output')
         self.keys_path = os.path.join(self.tmpdir, 'keys')
         self.keys_path = os.path.join(self.tmpdir, 'keys')
         self.cache_path = os.path.join(self.tmpdir, 'cache')
         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_KEYS_DIR'] = self.keys_path
         os.environ['ATTIC_CACHE_DIR'] = self.cache_path
         os.environ['ATTIC_CACHE_DIR'] = self.cache_path
         os.mkdir(self.input_path)
         os.mkdir(self.input_path)
         os.mkdir(self.output_path)
         os.mkdir(self.output_path)
         os.mkdir(self.keys_path)
         os.mkdir(self.keys_path)
         os.mkdir(self.cache_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()
         self._old_wd = os.getcwd()
         os.chdir(self.tmpdir)
         os.chdir(self.tmpdir)
 
 
@@ -157,6 +160,9 @@ class ArchiverTestCase(AtticTestCase):
         with changedir('output'):
         with changedir('output'):
             self.attic('extract', '--exclude=input/file2', self.repository_location + '::test')
             self.attic('extract', '--exclude=input/file2', self.repository_location + '::test')
         self.assert_equal(sorted(os.listdir('output/input')), ['file1', 'file3'])
         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):
     def test_path_normalization(self):
         self.attic('init', self.repository_location)
         self.attic('init', self.repository_location)