diff --git a/NEWS b/NEWS index c883ecb1b..5459f1c56 100644 --- a/NEWS +++ b/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 * #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 diff --git a/borgmatic/borg/extract.py b/borgmatic/borg/extract.py index 966e29713..e50a487fe 100644 --- a/borgmatic/borg/extract.py +++ b/borgmatic/borg/extract.py @@ -104,8 +104,13 @@ def extract_archive( if not paths: 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 = ( (local_path, 'extract') diff --git a/setup.py b/setup.py index a8960747a..2985f0618 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ from setuptools import find_packages, setup -VERSION = '1.8.10' +VERSION = '1.8.11.dev0' setup( diff --git a/tests/unit/borg/test_extract.py b/tests/unit/borg/test_extract.py index 191463216..d5c660b37 100644 --- a/tests/unit/borg/test_extract.py +++ b/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(): flexmock(module.os.path).should_receive('abspath').and_return('repo') flexmock(module.feature).should_receive('available').and_return(True)