From f36e38ec201d66971ffc0af61addcc0595124da7 Mon Sep 17 00:00:00 2001 From: Dan Helfman Date: Mon, 15 Aug 2022 19:32:37 -0700 Subject: [PATCH] Update mount action for Borg 2 support (#557). --- borgmatic/borg/mount.py | 15 ++++++-- borgmatic/commands/borgmatic.py | 1 + tests/unit/borg/test_mount.py | 64 +++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/borgmatic/borg/mount.py b/borgmatic/borg/mount.py index 4f5db81a4..370ca13ca 100644 --- a/borgmatic/borg/mount.py +++ b/borgmatic/borg/mount.py @@ -1,6 +1,6 @@ import logging -from borgmatic.borg import environment +from borgmatic.borg import environment, feature, flags from borgmatic.execute import DO_NOT_CAPTURE, execute_command logger = logging.getLogger(__name__) @@ -14,13 +14,15 @@ def mount_archive( foreground, options, storage_config, + local_borg_version, local_path='borg', remote_path=None, ): ''' Given a local or remote repository path, an optional archive name, a filesystem mount point, zero or more paths to mount from the archive, extra Borg mount options, a storage configuration - dict, and optional local and remote Borg paths, mount the archive onto the mount point. + dict, the local Borg version, and optional local and remote Borg paths, mount the archive onto + the mount point. ''' umask = storage_config.get('umask', None) lock_wait = storage_config.get('lock_wait', None) @@ -34,7 +36,14 @@ def mount_archive( + (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ()) + (('--foreground',) if foreground else ()) + (('-o', options) if options else ()) - + (('::'.join((repository, archive)),) if archive else (repository,)) + + ( + ( + flags.make_repository_flags(repository, local_borg_version) + + ('--glob-archives', archive) + ) + if feature.available(feature.Feature.SEPARATE_REPOSITORY_ARCHIVE, local_borg_version) + else flags.make_repository_archive_flags(repository, archive, local_borg_version) + ) + (mount_point,) + (tuple(paths) if paths else ()) ) diff --git a/borgmatic/commands/borgmatic.py b/borgmatic/commands/borgmatic.py index c526b102b..777b39f0a 100644 --- a/borgmatic/commands/borgmatic.py +++ b/borgmatic/commands/borgmatic.py @@ -517,6 +517,7 @@ def run_actions( arguments['mount'].foreground, arguments['mount'].options, storage, + local_borg_version, local_path=local_path, remote_path=remote_path, ) diff --git a/tests/unit/borg/test_mount.py b/tests/unit/borg/test_mount.py index c5638caa9..d87a18c83 100644 --- a/tests/unit/borg/test_mount.py +++ b/tests/unit/borg/test_mount.py @@ -15,6 +15,10 @@ def insert_execute_command_mock(command): def test_mount_archive_calls_borg_with_required_parameters(): + flexmock(module.feature).should_receive('available').and_return(False) + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) insert_execute_command_mock(('borg', 'mount', 'repo::archive', '/mnt')) module.mount_archive( @@ -25,10 +29,34 @@ def test_mount_archive_calls_borg_with_required_parameters(): foreground=False, options=None, storage_config={}, + local_borg_version='1.2.3', + ) + + +def test_mount_archive_with_borg_features_calls_borg_with_repository_and_glob_archives_flags(): + flexmock(module.feature).should_receive('available').and_return(True) + flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo',)) + insert_execute_command_mock( + ('borg', 'mount', '--repo', 'repo', '--glob-archives', 'archive', '/mnt') + ) + + module.mount_archive( + repository='repo', + archive='archive', + mount_point='/mnt', + paths=None, + foreground=False, + options=None, + storage_config={}, + local_borg_version='1.2.3', ) def test_mount_archive_calls_borg_with_path_parameters(): + flexmock(module.feature).should_receive('available').and_return(False) + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) insert_execute_command_mock(('borg', 'mount', 'repo::archive', '/mnt', 'path1', 'path2')) module.mount_archive( @@ -39,10 +67,15 @@ def test_mount_archive_calls_borg_with_path_parameters(): foreground=False, options=None, storage_config={}, + local_borg_version='1.2.3', ) def test_mount_archive_calls_borg_with_remote_path_parameters(): + flexmock(module.feature).should_receive('available').and_return(False) + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) insert_execute_command_mock( ('borg', 'mount', '--remote-path', 'borg1', 'repo::archive', '/mnt') ) @@ -55,11 +88,16 @@ def test_mount_archive_calls_borg_with_remote_path_parameters(): foreground=False, options=None, storage_config={}, + local_borg_version='1.2.3', remote_path='borg1', ) def test_mount_archive_calls_borg_with_umask_parameters(): + flexmock(module.feature).should_receive('available').and_return(False) + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) insert_execute_command_mock(('borg', 'mount', '--umask', '0770', 'repo::archive', '/mnt')) module.mount_archive( @@ -70,10 +108,15 @@ def test_mount_archive_calls_borg_with_umask_parameters(): foreground=False, options=None, storage_config={'umask': '0770'}, + local_borg_version='1.2.3', ) def test_mount_archive_calls_borg_with_lock_wait_parameters(): + flexmock(module.feature).should_receive('available').and_return(False) + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) insert_execute_command_mock(('borg', 'mount', '--lock-wait', '5', 'repo::archive', '/mnt')) module.mount_archive( @@ -84,10 +127,15 @@ def test_mount_archive_calls_borg_with_lock_wait_parameters(): foreground=False, options=None, storage_config={'lock_wait': '5'}, + local_borg_version='1.2.3', ) def test_mount_archive_with_log_info_calls_borg_with_info_parameter(): + flexmock(module.feature).should_receive('available').and_return(False) + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) insert_execute_command_mock(('borg', 'mount', '--info', 'repo::archive', '/mnt')) insert_logging_mock(logging.INFO) @@ -99,10 +147,15 @@ def test_mount_archive_with_log_info_calls_borg_with_info_parameter(): foreground=False, options=None, storage_config={}, + local_borg_version='1.2.3', ) def test_mount_archive_with_log_debug_calls_borg_with_debug_parameters(): + flexmock(module.feature).should_receive('available').and_return(False) + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) insert_execute_command_mock(('borg', 'mount', '--debug', '--show-rc', 'repo::archive', '/mnt')) insert_logging_mock(logging.DEBUG) @@ -114,10 +167,15 @@ def test_mount_archive_with_log_debug_calls_borg_with_debug_parameters(): foreground=False, options=None, storage_config={}, + local_borg_version='1.2.3', ) def test_mount_archive_calls_borg_with_foreground_parameter(): + flexmock(module.feature).should_receive('available').and_return(False) + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) flexmock(module.environment).should_receive('make_environment') flexmock(module).should_receive('execute_command').with_args( ('borg', 'mount', '--foreground', 'repo::archive', '/mnt'), @@ -134,10 +192,15 @@ def test_mount_archive_calls_borg_with_foreground_parameter(): foreground=True, options=None, storage_config={}, + local_borg_version='1.2.3', ) def test_mount_archive_calls_borg_with_options_parameters(): + flexmock(module.feature).should_receive('available').and_return(False) + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) insert_execute_command_mock(('borg', 'mount', '-o', 'super_mount', 'repo::archive', '/mnt')) module.mount_archive( @@ -148,4 +211,5 @@ def test_mount_archive_calls_borg_with_options_parameters(): foreground=False, options='super_mount', storage_config={}, + local_borg_version='1.2.3', )