From d807ce095ec4c8d1cf30072fd75646c75184fd0c Mon Sep 17 00:00:00 2001 From: Dan Helfman Date: Mon, 15 Aug 2022 17:34:12 -0700 Subject: [PATCH] Update export-tar action for Borg 2 support (#557). --- NEWS | 9 +++--- borgmatic/borg/export_tar.py | 17 ++++++---- borgmatic/commands/borgmatic.py | 1 + tests/unit/borg/test_export_tar.py | 52 ++++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 10 deletions(-) diff --git a/NEWS b/NEWS index a996306c3..b753753b2 100644 --- a/NEWS +++ b/NEWS @@ -1,8 +1,9 @@ 1.7.0.dev0 - * #557: Support for Borg 2 while still working with Borg 1. If you install Borg 2, you'll need to - manually "borg transfer" or "borgmatic transfer" any existing Borg 1 repositories before use. See - the Borg 2.0 changelog summary for more information about Borg 2: - https://www.borgbackup.org/releases/borg-2.0.html + * #557: Support for Borg 2 while still working with Borg 1. This includes new borgmatic actions + like "rcreate" (replaces "init"), "rlist" (list archives in repository), and "rinfo" (show + repository info). If you install Borg 2, you'll need to manually "borg transfer" or "borgmatic + transfer" your existing Borg 1 repositories before use. See the Borg 2.0 changelog for more + information about Borg 2: https://www.borgbackup.org/releases/borg-2.0.html * #565: Fix handling of "repository" and "data" consistency checks to prevent invalid Borg flags. * #566: Modify "mount" and "extract" actions to require the "--repository" flag when multiple repositories are configured. diff --git a/borgmatic/borg/export_tar.py b/borgmatic/borg/export_tar.py index 542092880..9bbd00823 100644 --- a/borgmatic/borg/export_tar.py +++ b/borgmatic/borg/export_tar.py @@ -1,7 +1,7 @@ import logging import os -from borgmatic.borg import environment +from borgmatic.borg import environment, flags from borgmatic.execute import DO_NOT_CAPTURE, execute_command logger = logging.getLogger(__name__) @@ -14,6 +14,7 @@ def export_tar_archive( paths, destination_path, storage_config, + local_borg_version, local_path='borg', remote_path=None, tar_filter=None, @@ -22,10 +23,10 @@ def export_tar_archive( ): ''' Given a dry-run flag, a local or remote repository path, an archive name, zero or more paths to - export from the archive, a destination path to export to, a storage configuration dict, optional - local and remote Borg paths, an optional filter program, whether to include per-file details, - and an optional number of path components to strip, export the archive into the given - destination path as a tar-formatted file. + export from the archive, a destination path to export to, a storage configuration dict, the + local Borg version, optional local and remote Borg paths, an optional filter program, whether to + include per-file details, and an optional number of path components to strip, export the archive + into the given destination path as a tar-formatted file. If the destination path is "-", then stream the output to stdout instead of to a file. ''' @@ -43,7 +44,11 @@ def export_tar_archive( + (('--dry-run',) if dry_run else ()) + (('--tar-filter', tar_filter) if tar_filter else ()) + (('--strip-components', str(strip_components)) if strip_components else ()) - + ('::'.join((repository if ':' in repository else os.path.abspath(repository), archive)),) + + flags.make_repository_archive_flags( + repository if ':' in repository else os.path.abspath(repository), + archive, + local_borg_version, + ) + (destination_path,) + (tuple(paths) if paths else ()) ) diff --git a/borgmatic/commands/borgmatic.py b/borgmatic/commands/borgmatic.py index e4455daa9..c526b102b 100644 --- a/borgmatic/commands/borgmatic.py +++ b/borgmatic/commands/borgmatic.py @@ -484,6 +484,7 @@ def run_actions( arguments['export-tar'].paths, arguments['export-tar'].destination, storage, + local_borg_version, local_path=local_path, remote_path=remote_path, tar_filter=arguments['export-tar'].tar_filter, diff --git a/tests/unit/borg/test_export_tar.py b/tests/unit/borg/test_export_tar.py index 11b2b20af..f8d56372b 100644 --- a/tests/unit/borg/test_export_tar.py +++ b/tests/unit/borg/test_export_tar.py @@ -21,6 +21,9 @@ def insert_execute_command_mock( def test_export_tar_archive_calls_borg_with_path_parameters(): + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) flexmock(module.os.path).should_receive('abspath').and_return('repo') insert_execute_command_mock( ('borg', 'export-tar', 'repo::archive', 'test.tar', 'path1', 'path2') @@ -33,10 +36,14 @@ def test_export_tar_archive_calls_borg_with_path_parameters(): paths=['path1', 'path2'], destination_path='test.tar', storage_config={}, + local_borg_version='1.2.3', ) def test_export_tar_archive_calls_borg_with_local_path_parameters(): + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) flexmock(module.os.path).should_receive('abspath').and_return('repo') insert_execute_command_mock( ('borg1', 'export-tar', 'repo::archive', 'test.tar'), borg_local_path='borg1' @@ -49,11 +56,15 @@ def test_export_tar_archive_calls_borg_with_local_path_parameters(): paths=None, destination_path='test.tar', storage_config={}, + local_borg_version='1.2.3', local_path='borg1', ) def test_export_tar_archive_calls_borg_with_remote_path_parameters(): + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) flexmock(module.os.path).should_receive('abspath').and_return('repo') insert_execute_command_mock( ('borg', 'export-tar', '--remote-path', 'borg1', 'repo::archive', 'test.tar') @@ -66,11 +77,15 @@ def test_export_tar_archive_calls_borg_with_remote_path_parameters(): paths=None, destination_path='test.tar', storage_config={}, + local_borg_version='1.2.3', remote_path='borg1', ) def test_export_tar_archive_calls_borg_with_umask_parameters(): + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) flexmock(module.os.path).should_receive('abspath').and_return('repo') insert_execute_command_mock( ('borg', 'export-tar', '--umask', '0770', 'repo::archive', 'test.tar') @@ -83,10 +98,14 @@ def test_export_tar_archive_calls_borg_with_umask_parameters(): paths=None, destination_path='test.tar', storage_config={'umask': '0770'}, + local_borg_version='1.2.3', ) def test_export_tar_archive_calls_borg_with_lock_wait_parameters(): + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) flexmock(module.os.path).should_receive('abspath').and_return('repo') insert_execute_command_mock( ('borg', 'export-tar', '--lock-wait', '5', 'repo::archive', 'test.tar') @@ -99,10 +118,14 @@ def test_export_tar_archive_calls_borg_with_lock_wait_parameters(): paths=None, destination_path='test.tar', storage_config={'lock_wait': '5'}, + local_borg_version='1.2.3', ) def test_export_tar_archive_with_log_info_calls_borg_with_info_parameter(): + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) flexmock(module.os.path).should_receive('abspath').and_return('repo') insert_execute_command_mock(('borg', 'export-tar', '--info', 'repo::archive', 'test.tar')) insert_logging_mock(logging.INFO) @@ -114,10 +137,14 @@ def test_export_tar_archive_with_log_info_calls_borg_with_info_parameter(): paths=None, destination_path='test.tar', storage_config={}, + local_borg_version='1.2.3', ) def test_export_tar_archive_with_log_debug_calls_borg_with_debug_parameters(): + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) flexmock(module.os.path).should_receive('abspath').and_return('repo') insert_execute_command_mock( ('borg', 'export-tar', '--debug', '--show-rc', 'repo::archive', 'test.tar') @@ -131,10 +158,14 @@ def test_export_tar_archive_with_log_debug_calls_borg_with_debug_parameters(): paths=None, destination_path='test.tar', storage_config={}, + local_borg_version='1.2.3', ) def test_export_tar_archive_calls_borg_with_dry_run_parameter(): + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) flexmock(module.os.path).should_receive('abspath').and_return('repo') flexmock(module).should_receive('execute_command').never() @@ -145,10 +176,14 @@ def test_export_tar_archive_calls_borg_with_dry_run_parameter(): paths=None, destination_path='test.tar', storage_config={}, + local_borg_version='1.2.3', ) def test_export_tar_archive_calls_borg_with_tar_filter_parameters(): + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) flexmock(module.os.path).should_receive('abspath').and_return('repo') insert_execute_command_mock( ('borg', 'export-tar', '--tar-filter', 'bzip2', 'repo::archive', 'test.tar') @@ -161,11 +196,15 @@ def test_export_tar_archive_calls_borg_with_tar_filter_parameters(): paths=None, destination_path='test.tar', storage_config={}, + local_borg_version='1.2.3', tar_filter='bzip2', ) def test_export_tar_archive_calls_borg_with_list_parameter(): + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) flexmock(module.os.path).should_receive('abspath').and_return('repo') insert_execute_command_mock( ('borg', 'export-tar', '--list', 'repo::archive', 'test.tar'), @@ -179,11 +218,15 @@ def test_export_tar_archive_calls_borg_with_list_parameter(): paths=None, destination_path='test.tar', storage_config={}, + local_borg_version='1.2.3', files=True, ) def test_export_tar_archive_calls_borg_with_strip_components_parameter(): + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) flexmock(module.os.path).should_receive('abspath').and_return('repo') insert_execute_command_mock( ('borg', 'export-tar', '--strip-components', '5', 'repo::archive', 'test.tar') @@ -196,11 +239,15 @@ def test_export_tar_archive_calls_borg_with_strip_components_parameter(): paths=None, destination_path='test.tar', storage_config={}, + local_borg_version='1.2.3', strip_components=5, ) def test_export_tar_archive_skips_abspath_for_remote_repository_parameter(): + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('server:repo::archive',) + ) flexmock(module.os.path).should_receive('abspath').never() insert_execute_command_mock(('borg', 'export-tar', 'server:repo::archive', 'test.tar')) @@ -211,10 +258,14 @@ def test_export_tar_archive_skips_abspath_for_remote_repository_parameter(): paths=None, destination_path='test.tar', storage_config={}, + local_borg_version='1.2.3', ) def test_export_tar_archive_calls_borg_with_stdout_destination_path(): + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) flexmock(module.os.path).should_receive('abspath').and_return('repo') insert_execute_command_mock(('borg', 'export-tar', 'repo::archive', '-'), capture=False) @@ -225,4 +276,5 @@ def test_export_tar_archive_calls_borg_with_stdout_destination_path(): paths=None, destination_path='-', storage_config={}, + local_borg_version='1.2.3', )