Browse Source

Fix lack of file extraction when using "extract --strip-components all" on a path with a leading slash (#851).

Dan Helfman 1 year ago
parent
commit
cb2fd7c5e8
4 changed files with 45 additions and 3 deletions
  1. 4 0
      NEWS
  2. 7 2
      borgmatic/borg/extract.py
  3. 1 1
      setup.py
  4. 33 0
      tests/unit/borg/test_extract.py

+ 4 - 0
NEWS

@@ -1,3 +1,7 @@
+1.8.11.dev0
+ * #851: Fix lack of file extraction when using "extract --strip-components all" on a path with a
+   leading slash.
+
 1.8.10
 1.8.10
  * #656 (beta): Add a "spot" consistency check that compares file counts and contents between your
  * #656 (beta): Add a "spot" consistency check that compares file counts and contents between your
    source files and the latest archive, ensuring they fall within configured tolerances. This can
    source files and the latest archive, ensuring they fall within configured tolerances. This can

+ 7 - 2
borgmatic/borg/extract.py

@@ -104,8 +104,13 @@ def extract_archive(
         if not paths:
         if not paths:
             raise ValueError('The --strip-components flag with "all" requires at least one --path')
             raise ValueError('The --strip-components flag with "all" requires at least one --path')
 
 
-        # Calculate the maximum number of leading path components of the given paths.
-        strip_components = max(0, *(len(path.split(os.path.sep)) - 1 for path in paths))
+        # Calculate the maximum number of leading path components of the given paths. "if piece"
+        # ignores empty path components, e.g. those resulting from a leading slash. And the "- 1"
+        # is so this doesn't count the final path component, e.g. the filename itself.
+        strip_components = max(
+            0,
+            *(len(tuple(piece for piece in path.split(os.path.sep) if piece)) - 1 for path in paths)
+        )
 
 
     full_command = (
     full_command = (
         (local_path, 'extract')
         (local_path, 'extract')

+ 1 - 1
setup.py

@@ -1,6 +1,6 @@
 from setuptools import find_packages, setup
 from setuptools import find_packages, setup
 
 
-VERSION = '1.8.10'
+VERSION = '1.8.11.dev0'
 
 
 
 
 setup(
 setup(

+ 33 - 0
tests/unit/borg/test_extract.py

@@ -507,6 +507,39 @@ def test_extract_archive_calls_borg_with_strip_components_calculated_from_all():
     )
     )
 
 
 
 
+def test_extract_archive_calls_borg_with_strip_components_calculated_from_all_with_leading_slash():
+    flexmock(module.os.path).should_receive('abspath').and_return('repo')
+    insert_execute_command_mock(
+        (
+            'borg',
+            'extract',
+            '--strip-components',
+            '2',
+            'repo::archive',
+            '/foo/bar/baz.txt',
+            '/foo/bar.txt',
+        )
+    )
+    flexmock(module.feature).should_receive('available').and_return(True)
+    flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
+        ('repo::archive',)
+    )
+    flexmock(module.borgmatic.config.validate).should_receive(
+        'normalize_repository_path'
+    ).and_return('repo')
+
+    module.extract_archive(
+        dry_run=False,
+        repository='repo',
+        archive='archive',
+        paths=['/foo/bar/baz.txt', '/foo/bar.txt'],
+        config={},
+        local_borg_version='1.2.3',
+        global_arguments=flexmock(log_json=False),
+        strip_components='all',
+    )
+
+
 def test_extract_archive_with_strip_components_all_and_no_paths_raises():
 def test_extract_archive_with_strip_components_all_and_no_paths_raises():
     flexmock(module.os.path).should_receive('abspath').and_return('repo')
     flexmock(module.os.path).should_receive('abspath').and_return('repo')
     flexmock(module.feature).should_receive('available').and_return(True)
     flexmock(module.feature).should_receive('available').and_return(True)