浏览代码

extract: refactor filter building

Marian Beermann 8 年之前
父节点
当前提交
8268e26c6b
共有 2 个文件被更改,包括 35 次插入5 次删除
  1. 11 3
      borg/archiver.py
  2. 24 2
      borg/testsuite/archiver.py

+ 11 - 3
borg/archiver.py

@@ -343,6 +343,16 @@ class Archiver:
                 status = '-'  # dry run, item was not backed up
         self.print_file_status(status, path)
 
+    @staticmethod
+    def build_filter(matcher, strip_components=0):
+        if strip_components:
+            def item_filter(item):
+                return matcher.match(item[b'path']) and os.sep.join(item[b'path'].split(os.sep)[strip_components:])
+        else:
+            def item_filter(item):
+                return matcher.match(item[b'path'])
+        return item_filter
+
     @with_repository()
     @with_archive
     def do_extract(self, args, repository, manifest, key, archive):
@@ -371,9 +381,7 @@ class Archiver:
         sparse = args.sparse
         strip_components = args.strip_components
         dirs = []
-        filter = lambda item: matcher.match(item[b'path'])
-        if strip_components:
-            filter = lambda item: matcher.match(item[b'path']) and os.sep.join(item[b'path'].split(os.sep)[strip_components:])
+        filter = self.build_filter(matcher, strip_components)
         for item in archive.iter_items(filter, preload=True):
             orig_path = item[b'path']
             if strip_components:

+ 24 - 2
borg/testsuite/archiver.py

@@ -21,7 +21,7 @@ from ..archive import Archive, ChunkBuffer, CHUNK_MAX_EXP, flags_noatime, flags_
 from ..archiver import Archiver
 from ..cache import Cache
 from ..crypto import bytes_to_long, num_aes_blocks
-from ..helpers import Manifest, EXIT_SUCCESS, EXIT_WARNING, EXIT_ERROR
+from ..helpers import Manifest, PatternMatcher, parse_pattern, EXIT_SUCCESS, EXIT_WARNING, EXIT_ERROR
 from ..remote import RemoteRepository, PathNotAllowed
 from ..repository import Repository
 from . import BaseTestCase, changedir, environment_variable
@@ -1337,7 +1337,6 @@ class RemoteArchiverTestCase(ArchiverTestCase):
         self.cmd('create', self.repository_location + '::test', 'input')
         marker = 'cached responses left in RemoteRepository'
         with changedir('output'):
-            #import rpdb2; rpdb2.start_embedded_debugger("nopass")
             res = self.cmd('extract', "--debug", self.repository_location + '::test', '--strip-components', '3')
             self.assert_true(marker not in res)
             with self.assert_creates_file('file'):
@@ -1370,3 +1369,26 @@ def test_get_args():
     args = archiver.get_args(['borg', 'serve', '--restrict-to-path=/p1', '--restrict-to-path=/p2', ],
                              'borg init /')
     assert args.func == archiver.do_serve
+
+
+class TestBuildFilter:
+    def test_basic(self):
+        matcher = PatternMatcher()
+        matcher.add([parse_pattern('included')], True)
+        filter = Archiver.build_filter(matcher)
+        assert filter({b'path': 'included'})
+        assert filter({b'path': 'included/file'})
+        assert not filter({b'path': 'something else'})
+
+    def test_empty(self):
+        matcher = PatternMatcher(fallback=True)
+        filter = Archiver.build_filter(matcher)
+        assert filter({b'path': 'anything'})
+
+    def test_strip_components(self):
+        matcher = PatternMatcher(fallback=True)
+        filter = Archiver.build_filter(matcher, strip_components=1)
+        assert not filter({b'path': 'shallow'})
+        assert not filter({b'path': 'shallow/'})  # can this even happen? paths are normalized...
+        assert filter({b'path': 'deep enough/file'})
+        assert filter({b'path': 'something/dir/file'})