diff --git a/borgmatic/borg/rcreate.py b/borgmatic/borg/rcreate.py index 6babe0170..81be86465 100644 --- a/borgmatic/borg/rcreate.py +++ b/borgmatic/borg/rcreate.py @@ -16,9 +16,11 @@ def create_repository( storage_config, local_borg_version, encryption_mode, - other_repo=None, + key_repository=None, + copy_crypt_key=False, append_only=None, storage_quota=None, + make_parent_dirs=False, local_path='borg', remote_path=None, ): @@ -53,9 +55,11 @@ def create_repository( else ('init',) ) + (('--encryption', encryption_mode) if encryption_mode else ()) - + (('--other-repo', other_repo) if other_repo else ()) + + (('--other-repo', key_repository) if key_repository else ()) + + (('--copy-crypt-key',) if copy_crypt_key else ()) + (('--append-only',) if append_only else ()) + (('--storage-quota', storage_quota) if storage_quota else ()) + + (('--make-parent-dirs',) if make_parent_dirs else ()) + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ()) + (('--debug',) if logger.isEnabledFor(logging.DEBUG) else ()) + (('--remote-path', remote_path) if remote_path else ()) diff --git a/borgmatic/commands/arguments.py b/borgmatic/commands/arguments.py index 990b96866..a5b8afcfc 100644 --- a/borgmatic/commands/arguments.py +++ b/borgmatic/commands/arguments.py @@ -18,6 +18,7 @@ SUBPARSER_ALIASES = { 'list': ['--list', '-l'], 'rinfo': [], 'info': ['--info', '-i'], + 'transfer': [], 'borg': [], } @@ -240,20 +241,26 @@ def make_parsers(): required=True, ) rcreate_group.add_argument( + '--key-repository', '--other-repo', metavar='SOURCE_REPOSITORY', help='Path to an existing Borg repository whose key material should be reused (Borg 2.x+ only)', ) rcreate_group.add_argument( - '--append-only', - dest='append_only', + '--copy-crypt-key', action='store_true', - help='Create an append-only repository', + help='Copy the crypt key used for authenticated encryption from the key repository, defaults to a new random key (Borg 2.x+ only)', ) rcreate_group.add_argument( - '--storage-quota', - dest='storage_quota', - help='Create a repository with a fixed storage quota', + '--append-only', action='store_true', help='Create an append-only repository', + ) + rcreate_group.add_argument( + '--storage-quota', help='Create a repository with a fixed storage quota', + ) + rcreate_group.add_argument( + '--make-parent-dirs', + action='store_true', + help='Create any missing parent directories of the repository directory', ) rcreate_group.add_argument( '-h', '--help', action='help', help='Show this help message and exit' diff --git a/borgmatic/commands/borgmatic.py b/borgmatic/commands/borgmatic.py index 343b9a64d..a905713c2 100644 --- a/borgmatic/commands/borgmatic.py +++ b/borgmatic/commands/borgmatic.py @@ -258,9 +258,11 @@ def run_actions( storage, local_borg_version, arguments['rcreate'].encryption_mode, - arguments['rcreate'].other_repo, + arguments['rcreate'].key_repository, + arguments['rcreate'].copy_crypt_key, arguments['rcreate'].append_only, arguments['rcreate'].storage_quota, + arguments['rcreate'].make_parent_dirs, local_path=local_path, remote_path=remote_path, ) diff --git a/tests/unit/borg/test_rcreate.py b/tests/unit/borg/test_rcreate.py index 1a22e8e01..18166a9ff 100644 --- a/tests/unit/borg/test_rcreate.py +++ b/tests/unit/borg/test_rcreate.py @@ -32,7 +32,7 @@ def insert_rcreate_command_mock(rcreate_command, **kwargs): ).once() -def test_create_repository_calls_borg_with_parameters(): +def test_create_repository_calls_borg_with_flags(): insert_rinfo_command_not_found_mock() insert_rcreate_command_mock(RCREATE_COMMAND + ('--repo', 'repo')) flexmock(module.feature).should_receive('available').and_return(True) @@ -85,7 +85,7 @@ def test_create_repository_raises_for_unknown_rinfo_command_error(): ) -def test_create_repository_with_append_only_calls_borg_with_other_repo_parameter(): +def test_create_repository_with_key_repository_calls_borg_with_other_repo_flag(): insert_rinfo_command_not_found_mock() insert_rcreate_command_mock(RCREATE_COMMAND + ('--other-repo', 'other.borg', '--repo', 'repo')) flexmock(module.feature).should_receive('available').and_return(True) @@ -96,11 +96,26 @@ def test_create_repository_with_append_only_calls_borg_with_other_repo_parameter storage_config={}, local_borg_version='2.3.4', encryption_mode='repokey', - other_repo='other.borg', + key_repository='other.borg', ) -def test_create_repository_with_append_only_calls_borg_with_append_only_parameter(): +def test_create_repository_with_copy_crypt_key_calls_borg_with_copy_crypt_key_flag(): + insert_rinfo_command_not_found_mock() + insert_rcreate_command_mock(RCREATE_COMMAND + ('--copy-crypt-key', '--repo', 'repo')) + flexmock(module.feature).should_receive('available').and_return(True) + flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo',)) + + module.create_repository( + repository='repo', + storage_config={}, + local_borg_version='2.3.4', + encryption_mode='repokey', + copy_crypt_key=True, + ) + + +def test_create_repository_with_append_only_calls_borg_with_append_only_flag(): insert_rinfo_command_not_found_mock() insert_rcreate_command_mock(RCREATE_COMMAND + ('--append-only', '--repo', 'repo')) flexmock(module.feature).should_receive('available').and_return(True) @@ -115,7 +130,7 @@ def test_create_repository_with_append_only_calls_borg_with_append_only_paramete ) -def test_create_repository_with_storage_quota_calls_borg_with_storage_quota_parameter(): +def test_create_repository_with_storage_quota_calls_borg_with_storage_quota_flag(): insert_rinfo_command_not_found_mock() insert_rcreate_command_mock(RCREATE_COMMAND + ('--storage-quota', '5G', '--repo', 'repo')) flexmock(module.feature).should_receive('available').and_return(True) @@ -130,7 +145,22 @@ def test_create_repository_with_storage_quota_calls_borg_with_storage_quota_para ) -def test_create_repository_with_log_info_calls_borg_with_info_parameter(): +def test_create_repository_with_make_parent_dirs_calls_borg_with_make_parent_dirs_flag(): + insert_rinfo_command_not_found_mock() + insert_rcreate_command_mock(RCREATE_COMMAND + ('--make-parent-dirs', '--repo', 'repo')) + flexmock(module.feature).should_receive('available').and_return(True) + flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo',)) + + module.create_repository( + repository='repo', + storage_config={}, + local_borg_version='2.3.4', + encryption_mode='repokey', + make_parent_dirs=True, + ) + + +def test_create_repository_with_log_info_calls_borg_with_info_flag(): insert_rinfo_command_not_found_mock() insert_rcreate_command_mock(RCREATE_COMMAND + ('--info', '--repo', 'repo')) insert_logging_mock(logging.INFO) @@ -142,7 +172,7 @@ def test_create_repository_with_log_info_calls_borg_with_info_parameter(): ) -def test_create_repository_with_log_debug_calls_borg_with_debug_parameter(): +def test_create_repository_with_log_debug_calls_borg_with_debug_flag(): insert_rinfo_command_not_found_mock() insert_rcreate_command_mock(RCREATE_COMMAND + ('--debug', '--repo', 'repo')) insert_logging_mock(logging.DEBUG) @@ -169,7 +199,7 @@ def test_create_repository_with_local_path_calls_borg_via_local_path(): ) -def test_create_repository_with_remote_path_calls_borg_with_remote_path_parameter(): +def test_create_repository_with_remote_path_calls_borg_with_remote_path_flag(): insert_rinfo_command_not_found_mock() insert_rcreate_command_mock(RCREATE_COMMAND + ('--remote-path', 'borg1', '--repo', 'repo')) flexmock(module.feature).should_receive('available').and_return(True) diff --git a/tests/unit/commands/test_borgmatic.py b/tests/unit/commands/test_borgmatic.py index 670377e7f..4b9c43ea9 100644 --- a/tests/unit/commands/test_borgmatic.py +++ b/tests/unit/commands/test_borgmatic.py @@ -346,9 +346,11 @@ def test_run_actions_does_not_raise_for_rcreate_action(): 'global': flexmock(monitoring_verbosity=1, dry_run=False), 'rcreate': flexmock( encryption_mode=flexmock(), - other_repo=flexmock(), + key_repository=flexmock(), + copy_crypt_key=flexmock(), append_only=flexmock(), storage_quota=flexmock(), + make_parent_dirs=flexmock(), ), }