diff --git a/NEWS b/NEWS index f41fb78f..1d5a0816 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,7 @@ 2.0.10.dev0 + * #427: Expand the "borg_extra_options" option to support passing arbitrary Borg flags to every + Borg sub-command that borgmatic uses. As part of this, deprecate the "init" option under + "borg_extra_options" in favor of "repo_create". * #942: Factor reference material out of the documentation how-to guides. This means there's now a whole reference section in the docs! Check it out: https://torsion.org/borgmatic/ * #973: For the MariaDB and MySQL database hooks, add a "skip_names" option to ignore particular diff --git a/borgmatic/borg/break_lock.py b/borgmatic/borg/break_lock.py index 9ce4f279..74749160 100644 --- a/borgmatic/borg/break_lock.py +++ b/borgmatic/borg/break_lock.py @@ -1,4 +1,5 @@ import logging +import shlex import borgmatic.config.paths from borgmatic.borg import environment, flags @@ -22,6 +23,7 @@ def break_lock( ''' umask = config.get('umask', None) lock_wait = config.get('lock_wait', None) + extra_borg_options = config.get('extra_borg_options', {}).get('break_lock', '') full_command = ( (local_path, 'break-lock') @@ -31,6 +33,7 @@ def break_lock( + (('--lock-wait', str(lock_wait)) if lock_wait else ()) + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ()) + (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ()) + + (tuple(shlex.split(extra_borg_options)) if extra_borg_options else ()) + flags.make_repository_flags(repository_path, local_borg_version) ) diff --git a/borgmatic/borg/change_passphrase.py b/borgmatic/borg/change_passphrase.py index 8f495253..8769802f 100644 --- a/borgmatic/borg/change_passphrase.py +++ b/borgmatic/borg/change_passphrase.py @@ -1,4 +1,5 @@ import logging +import shlex import borgmatic.config.paths import borgmatic.execute @@ -25,6 +26,7 @@ def change_passphrase( borgmatic.logger.add_custom_log_levels() umask = config.get('umask', None) lock_wait = config.get('lock_wait', None) + extra_borg_options = config.get('extra_borg_options', {}).get('key_change_passphrase', '') full_command = ( (local_path, 'key', 'change-passphrase') @@ -34,6 +36,7 @@ def change_passphrase( + (('--lock-wait', str(lock_wait)) if lock_wait else ()) + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ()) + (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ()) + + (tuple(shlex.split(extra_borg_options)) if extra_borg_options else ()) + flags.make_repository_flags( repository_path, local_borg_version, diff --git a/borgmatic/borg/delete.py b/borgmatic/borg/delete.py index 34486b86..fbfc8a9e 100644 --- a/borgmatic/borg/delete.py +++ b/borgmatic/borg/delete.py @@ -1,5 +1,6 @@ import argparse import logging +import shlex import borgmatic.borg.environment import borgmatic.borg.feature @@ -28,6 +29,8 @@ def make_delete_command( arguments to the delete action as an argparse.Namespace, and global arguments, return a command as a tuple to delete archives from the repository. ''' + extra_borg_options = config.get('extra_borg_options', {}).get('delete', '') + return ( (local_path, 'delete') + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ()) @@ -66,6 +69,7 @@ def make_delete_command( 'repository', ), ) + + (tuple(shlex.split(extra_borg_options)) if extra_borg_options else ()) + borgmatic.borg.flags.make_repository_flags(repository['path'], local_borg_version) ) diff --git a/borgmatic/borg/export_key.py b/borgmatic/borg/export_key.py index df22e82c..a85d2470 100644 --- a/borgmatic/borg/export_key.py +++ b/borgmatic/borg/export_key.py @@ -1,5 +1,6 @@ import logging import os +import shlex import borgmatic.config.paths import borgmatic.logger @@ -31,6 +32,7 @@ def export_key( umask = config.get('umask', None) lock_wait = config.get('lock_wait', None) working_directory = borgmatic.config.paths.get_working_directory(config) + extra_borg_options = config.get('extra_borg_options', {}).get('key_export', '') if export_arguments.path and export_arguments.path != '-': if os.path.exists(os.path.join(working_directory or '', export_arguments.path)): @@ -52,6 +54,7 @@ def export_key( + (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ()) + flags.make_flags('paper', export_arguments.paper) + flags.make_flags('qr-html', export_arguments.qr_html) + + (tuple(shlex.split(extra_borg_options)) if extra_borg_options else ()) + flags.make_repository_flags( repository_path, local_borg_version, diff --git a/borgmatic/borg/export_tar.py b/borgmatic/borg/export_tar.py index 891d577c..d7cf4d28 100644 --- a/borgmatic/borg/export_tar.py +++ b/borgmatic/borg/export_tar.py @@ -1,4 +1,5 @@ import logging +import shlex import borgmatic.config.paths import borgmatic.logger @@ -34,6 +35,7 @@ def export_tar_archive( borgmatic.logger.add_custom_log_levels() umask = config.get('umask', None) lock_wait = config.get('lock_wait', None) + extra_borg_options = config.get('extra_borg_options', {}).get('export_tar', '') full_command = ( (local_path, 'export-tar') @@ -47,6 +49,7 @@ 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 ()) + + (tuple(shlex.split(extra_borg_options)) if extra_borg_options else ()) + flags.make_repository_archive_flags( repository_path, archive, diff --git a/borgmatic/borg/extract.py b/borgmatic/borg/extract.py index 21fbd739..3004a47e 100644 --- a/borgmatic/borg/extract.py +++ b/borgmatic/borg/extract.py @@ -1,5 +1,6 @@ import logging import os +import shlex import subprocess import borgmatic.config.paths @@ -23,6 +24,7 @@ def extract_last_archive_dry_run( Perform an extraction dry-run of the most recent archive. If there are no archives, skip the dry-run. ''' + extra_borg_options = config.get('extra_borg_options', {}).get('extract', '') verbosity_flags = () if logger.isEnabledFor(logging.DEBUG): verbosity_flags = ('--debug', '--show-rc') @@ -51,6 +53,7 @@ def extract_last_archive_dry_run( + (('--lock-wait', str(lock_wait)) if lock_wait else ()) + verbosity_flags + list_flag + + (tuple(shlex.split(extra_borg_options)) if extra_borg_options else ()) + flags.make_repository_archive_flags( repository_path, last_archive_name, @@ -92,6 +95,7 @@ def extract_archive( ''' umask = config.get('umask', None) lock_wait = config.get('lock_wait', None) + extra_borg_options = config.get('extra_borg_options', {}).get('extract', '') if config.get('progress') and extract_to_stdout: raise ValueError('progress and extract to stdout cannot both be set') @@ -131,6 +135,7 @@ def extract_archive( + (('--strip-components', str(strip_components)) if strip_components else ()) + (('--progress',) if config.get('progress') else ()) + (('--stdout',) if extract_to_stdout else ()) + + (tuple(shlex.split(extra_borg_options)) if extra_borg_options else ()) + flags.make_repository_archive_flags( # Make the repository path absolute so the destination directory used below via changing # the working directory doesn't prevent Borg from finding the repo. But also apply the diff --git a/borgmatic/borg/import_key.py b/borgmatic/borg/import_key.py index 263f83a9..042c73aa 100644 --- a/borgmatic/borg/import_key.py +++ b/borgmatic/borg/import_key.py @@ -1,5 +1,6 @@ import logging import os +import shlex import borgmatic.config.paths import borgmatic.logger @@ -30,6 +31,7 @@ def import_key( umask = config.get('umask', None) lock_wait = config.get('lock_wait', None) working_directory = borgmatic.config.paths.get_working_directory(config) + extra_borg_options = config.get('extra_borg_options', {}).get('key_import', '') if import_arguments.path and import_arguments.path != '-': if not os.path.exists(os.path.join(working_directory or '', import_arguments.path)): @@ -48,6 +50,7 @@ def import_key( + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ()) + (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ()) + flags.make_flags('paper', import_arguments.paper) + + (tuple(shlex.split(extra_borg_options)) if extra_borg_options else ()) + flags.make_repository_flags( repository_path, local_borg_version, diff --git a/borgmatic/borg/info.py b/borgmatic/borg/info.py index 3b1c6a01..32de1057 100644 --- a/borgmatic/borg/info.py +++ b/borgmatic/borg/info.py @@ -1,5 +1,6 @@ import argparse import logging +import shlex import borgmatic.config.paths import borgmatic.logger @@ -23,6 +24,8 @@ def make_info_command( arguments to the info action as an argparse.Namespace, and global arguments, return a command as a tuple to display summary information for archives in the repository. ''' + extra_borg_options = config.get('extra_borg_options', {}).get('info', '') + return ( (local_path, 'info') + ( @@ -58,6 +61,7 @@ def make_info_command( info_arguments, excludes=('repository', 'archive', 'prefix', 'match_archives'), ) + + (tuple(shlex.split(extra_borg_options)) if extra_borg_options else ()) + flags.make_repository_flags(repository_path, local_borg_version) ) diff --git a/borgmatic/borg/list.py b/borgmatic/borg/list.py index f5d720b3..1f8d13b6 100644 --- a/borgmatic/borg/list.py +++ b/borgmatic/borg/list.py @@ -2,6 +2,7 @@ import argparse import copy import logging import re +import shlex import borgmatic.config.paths import borgmatic.logger @@ -35,6 +36,8 @@ def make_list_command( and local and remote Borg paths, return a command as a tuple to list archives or paths within an archive. ''' + extra_borg_options = config.get('extra_borg_options', {}).get('list', '') + return ( (local_path, 'list') + ( @@ -52,6 +55,7 @@ def make_list_command( + flags.make_flags('log-json', config.get('log_json')) + flags.make_flags('lock-wait', config.get('lock_wait')) + flags.make_flags_from_arguments(list_arguments, excludes=MAKE_FLAGS_EXCLUDES) + + (tuple(shlex.split(extra_borg_options)) if extra_borg_options else ()) + ( flags.make_repository_archive_flags( repository_path, diff --git a/borgmatic/borg/mount.py b/borgmatic/borg/mount.py index 6a383567..369b3b3b 100644 --- a/borgmatic/borg/mount.py +++ b/borgmatic/borg/mount.py @@ -1,4 +1,5 @@ import logging +import shlex import borgmatic.config.paths from borgmatic.borg import environment, feature, flags @@ -25,6 +26,7 @@ def mount_archive( ''' umask = config.get('umask', None) lock_wait = config.get('lock_wait', None) + extra_borg_options = config.get('extra_borg_options', {}).get('mount', '') full_command = ( (local_path, 'mount') @@ -39,6 +41,7 @@ def mount_archive( excludes=('repository', 'archive', 'mount_point', 'paths', 'options'), ) + (('-o', mount_arguments.options) if mount_arguments.options else ()) + + (tuple(shlex.split(extra_borg_options)) if extra_borg_options else ()) + ( ( flags.make_repository_flags(repository_path, local_borg_version) diff --git a/borgmatic/borg/recreate.py b/borgmatic/borg/recreate.py index 0f62f155..87091ba1 100644 --- a/borgmatic/borg/recreate.py +++ b/borgmatic/borg/recreate.py @@ -32,6 +32,7 @@ def recreate_archive( exclude_flags = flags.make_exclude_flags(config) compression = config.get('compression', None) chunker_params = config.get('chunker_params', None) + extra_borg_options = config.get('extra_borg_options', {}).get('recreate', '') # Available recompress MODES: "if-different", "always", "never" (default) recompress = config.get('recompress', None) @@ -71,6 +72,7 @@ def recreate_archive( + (('--chunker-params', chunker_params) if chunker_params else ()) + (('--recompress', recompress) if recompress else ()) + exclude_flags + + (tuple(shlex.split(extra_borg_options)) if extra_borg_options else ()) + ( ( flags.make_repository_flags(repository, local_borg_version) diff --git a/borgmatic/borg/rename.py b/borgmatic/borg/rename.py index b351be2b..9b73e96b 100644 --- a/borgmatic/borg/rename.py +++ b/borgmatic/borg/rename.py @@ -1,4 +1,5 @@ import logging +import shlex import borgmatic.borg.flags @@ -15,6 +16,8 @@ def make_rename_command( local_path, remote_path, ): + extra_borg_options = config.get('extra_borg_options', {}).get('rename', '') + return ( (local_path, 'rename') + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ()) @@ -24,6 +27,7 @@ def make_rename_command( + borgmatic.borg.flags.make_flags('umask', config.get('umask')) + borgmatic.borg.flags.make_flags('log-json', config.get('log_json')) + borgmatic.borg.flags.make_flags('lock-wait', config.get('lock_wait')) + + (tuple(shlex.split(extra_borg_options)) if extra_borg_options else ()) + borgmatic.borg.flags.make_repository_archive_flags( repository_name, old_archive_name, diff --git a/borgmatic/borg/repo_create.py b/borgmatic/borg/repo_create.py index 88f58e0a..1e3c0df9 100644 --- a/borgmatic/borg/repo_create.py +++ b/borgmatic/borg/repo_create.py @@ -66,8 +66,14 @@ def create_repository( lock_wait = config.get('lock_wait') umask = config.get('umask') + extra_borg_options_from_init = config.get('extra_borg_options', {}).get('init', '') extra_borg_options = config.get('extra_borg_options', {}).get('repo-create', '') + if extra_borg_options_from_init: + logger.warning( + 'The "init" option in "extra_borg_options" is deprecated and will be removed from a future release; use "repo_create" instead.' + ) + repo_create_command = ( (local_path,) + ( @@ -88,6 +94,7 @@ def create_repository( + (('--remote-path', remote_path) if remote_path else ()) + (('--umask', str(umask)) if umask else ()) + (tuple(shlex.split(extra_borg_options)) if extra_borg_options else ()) + + (tuple(shlex.split(extra_borg_options_from_init)) if extra_borg_options_from_init else ()) + flags.make_repository_flags(repository_path, local_borg_version) ) diff --git a/borgmatic/borg/repo_delete.py b/borgmatic/borg/repo_delete.py index 652afbb7..e03bda99 100644 --- a/borgmatic/borg/repo_delete.py +++ b/borgmatic/borg/repo_delete.py @@ -1,4 +1,5 @@ import logging +import shlex import borgmatic.borg.environment import borgmatic.borg.feature @@ -26,6 +27,8 @@ def make_repo_delete_command( arguments to the repo_delete action as an argparse.Namespace, and global arguments, return a command as a tuple to repo_delete the entire repository. ''' + extra_borg_options = config.get('extra_borg_options', {}).get('repo_delete', '') + return ( (local_path,) + ( @@ -56,6 +59,7 @@ def make_repo_delete_command( repo_delete_arguments, excludes=('list_details', 'force', 'repository'), ) + + (tuple(shlex.split(extra_borg_options)) if extra_borg_options else ()) + borgmatic.borg.flags.make_repository_flags(repository['path'], local_borg_version) ) diff --git a/borgmatic/borg/repo_info.py b/borgmatic/borg/repo_info.py index cf737513..be7526c9 100644 --- a/borgmatic/borg/repo_info.py +++ b/borgmatic/borg/repo_info.py @@ -1,4 +1,5 @@ import logging +import shlex import borgmatic.config.paths import borgmatic.logger @@ -24,6 +25,7 @@ def display_repository_info( ''' borgmatic.logger.add_custom_log_levels() lock_wait = config.get('lock_wait', None) + extra_borg_options = config.get('extra_borg_options', {}).get('repo_info', '') full_command = ( (local_path,) @@ -47,6 +49,7 @@ def display_repository_info( + flags.make_flags('log-json', config.get('log_json')) + flags.make_flags('lock-wait', lock_wait) + (('--json',) if repo_info_arguments.json else ()) + + (tuple(shlex.split(extra_borg_options)) if extra_borg_options else ()) + flags.make_repository_flags(repository_path, local_borg_version) ) diff --git a/borgmatic/borg/repo_list.py b/borgmatic/borg/repo_list.py index 03ec2de9..21c23c15 100644 --- a/borgmatic/borg/repo_list.py +++ b/borgmatic/borg/repo_list.py @@ -1,6 +1,7 @@ import argparse import json import logging +import shlex import borgmatic.config.paths import borgmatic.logger @@ -62,6 +63,7 @@ def get_latest_archive( Raises ValueError if there are no archives in the repository. ''' + extra_borg_options = config.get('extra_borg_options', {}).get('repo_list', '') full_command = ( local_path, @@ -81,6 +83,7 @@ def get_latest_archive( ), *flags.make_flags('last', 1), '--json', + *(tuple(shlex.split(extra_borg_options)) if extra_borg_options else ()), *flags.make_repository_flags(repository_path, local_borg_version), ) @@ -121,6 +124,8 @@ def make_repo_list_command( arguments to the repo_list action, global arguments as an argparse.Namespace instance, and local and remote Borg paths, return a command as a tuple to list archives with a repository. ''' + extra_borg_options = config.get('extra_borg_options', {}).get('repo_list', '') + return ( ( local_path, @@ -160,6 +165,7 @@ def make_repo_list_command( ) ) + flags.make_flags_from_arguments(repo_list_arguments, excludes=MAKE_FLAGS_EXCLUDES) + + (tuple(shlex.split(extra_borg_options)) if extra_borg_options else ()) + flags.make_repository_flags(repository_path, local_borg_version) ) diff --git a/borgmatic/borg/transfer.py b/borgmatic/borg/transfer.py index a17c81ac..a6df4b37 100644 --- a/borgmatic/borg/transfer.py +++ b/borgmatic/borg/transfer.py @@ -1,4 +1,5 @@ import logging +import shlex import borgmatic.config.paths import borgmatic.logger @@ -24,6 +25,7 @@ def transfer_archives( instance, transfer archives to the given repository. ''' borgmatic.logger.add_custom_log_levels() + extra_borg_options = config.get('extra_borg_options', {}).get('transfer', '') full_command = ( (local_path, 'transfer') @@ -53,6 +55,7 @@ def transfer_archives( ) ) ) + + (tuple(shlex.split(extra_borg_options)) if extra_borg_options else ()) + flags.make_repository_flags(repository_path, local_borg_version) + flags.make_flags('other-repo', transfer_arguments.source_repository) + flags.make_flags('dry-run', dry_run) diff --git a/borgmatic/borg/umount.py b/borgmatic/borg/umount.py index 3f700d6e..0a43d2ef 100644 --- a/borgmatic/borg/umount.py +++ b/borgmatic/borg/umount.py @@ -1,4 +1,5 @@ import logging +import shlex import borgmatic.config.paths from borgmatic.execute import execute_command @@ -11,10 +12,12 @@ def unmount_archive(config, mount_point, local_path='borg'): Given a mounted filesystem mount point, and an optional local Borg paths, umount the filesystem from the mount point. ''' + extra_borg_options = config.get('extra_borg_options', {}).get('umount', '') full_command = ( (local_path, 'umount') + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ()) + (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ()) + + (tuple(shlex.split(extra_borg_options)) if extra_borg_options else ()) + (mount_point,) ) diff --git a/borgmatic/borg/version.py b/borgmatic/borg/version.py index 1c07dce6..6bd97690 100644 --- a/borgmatic/borg/version.py +++ b/borgmatic/borg/version.py @@ -19,6 +19,7 @@ def local_borg_version(config, local_path='borg'): + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ()) + (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ()) ) + output = execute_command_and_capture_output( full_command, environment=environment.make_environment(config), diff --git a/borgmatic/config/schema.yaml b/borgmatic/config/schema.yaml index bb0ec2e3..42aa985b 100644 --- a/borgmatic/config/schema.yaml +++ b/borgmatic/config/schema.yaml @@ -525,30 +525,118 @@ properties: type: object additionalProperties: false properties: - init: + break_lock: type: string description: | - Extra command-line options to pass to "borg init". + Extra command-line options to pass to "borg break-lock". example: "--extra-option" - create: + check: type: string description: | - Extra command-line options to pass to "borg create". - example: "--extra-option" - prune: - type: string - description: | - Extra command-line options to pass to "borg prune". + Extra command-line options to pass to "borg check". example: "--extra-option" compact: type: string description: | Extra command-line options to pass to "borg compact". example: "--extra-option" - check: + create: type: string description: | - Extra command-line options to pass to "borg check". + Extra command-line options to pass to "borg create". + example: "--extra-option" + delete: + type: string + description: | + Extra command-line options to pass to "borg delete". + example: "--extra-option" + export_tar: + type: string + description: | + Extra command-line options to pass to "borg export-tar". + example: "--extra-option" + extract: + type: string + description: | + Extra command-line options to pass to "borg extract". + example: "--extra-option" + key_export: + type: string + description: | + Extra command-line options to pass to "borg key export". + example: "--extra-option" + key_import: + type: string + description: | + Extra command-line options to pass to "borg key import". + example: "--extra-option" + key_change_passphrase: + type: string + description: | + Extra command-line options to pass to "borg key + change-passphrase". + example: "--extra-option" + info: + type: string + description: | + Extra command-line options to pass to "borg info". + example: "--extra-option" + init: + type: string + description: | + Deprecated. Use "repo_create" instead. Extra command-line + options to pass to "borg init" / "borg repo-create". + example: "--extra-option" + list: + type: string + description: | + Extra command-line options to pass to "borg list". + example: "--extra-option" + mount: + type: string + description: | + Extra command-line options to pass to "borg mount". + example: "--extra-option" + prune: + type: string + description: | + Extra command-line options to pass to "borg prune". + example: "--extra-option" + recreate: + type: string + description: | + Extra command-line options to pass to "borg recreate". + example: "--extra-option" + repo_create: + type: string + description: | + Extra command-line options to pass to "borg init" / "borg + repo-create". + example: "--extra-option" + repo_delete: + type: string + description: | + Extra command-line options to pass to "borg repo-delete". + example: "--extra-option" + repo_info: + type: string + description: | + Extra command-line options to pass to "borg repo-info". + example: "--extra-option" + repo_list: + type: string + description: | + Extra command-line options to pass to "borg repo-list". + example: "--extra-option" + transfer: + type: string + description: | + Extra command-line options to pass to "borg transfer". + example: "--extra-option" + umount: + type: string + description: | + Extra command-line options to pass to "borg umount". example: "--extra-option" description: | Additional options to pass directly to particular Borg commands, diff --git a/docs/how-to/run-arbitrary-borg-commands.md b/docs/how-to/run-arbitrary-borg-commands.md index dcf5faeb..611d200c 100644 --- a/docs/how-to/run-arbitrary-borg-commands.md +++ b/docs/how-to/run-arbitrary-borg-commands.md @@ -134,6 +134,7 @@ borgmatic's `borg` action is not without limitations: not disable certain borgmatic logs to avoid interfering with JSON output. * The `borg` action bypasses most of borgmatic's machinery, so for instance monitoring hooks will not get triggered when running `borgmatic borg create`. + * The `borg` action does not use `extra_borg_options`. * Prior to version 1.8.0 borgmatic implicitly injected the repository/archive arguments on the Borg command-line for you (based on your borgmatic configuration or the diff --git a/tests/integration/borg/test_rename.py b/tests/integration/borg/test_rename.py index 7269bfe6..c6586c43 100644 --- a/tests/integration/borg/test_rename.py +++ b/tests/integration/borg/test_rename.py @@ -118,3 +118,25 @@ def test_make_rename_command_includes_lock_wait(): ) assert command == ('borg', 'rename', '--lock-wait', '5', 'repo::old_archive', 'new_archive') + + +def test_make_rename_command_includes_extra_borg_options(): + command = module.make_rename_command( + dry_run=False, + repository_name='repo', + old_archive_name='old_archive', + new_archive_name='new_archive', + config={'extra_borg_options': {'rename': '--extra "value with space"'}}, + local_borg_version='1.2.3', + local_path='borg', + remote_path=None, + ) + + assert command == ( + 'borg', + 'rename', + '--extra', + 'value with space', + 'repo::old_archive', + 'new_archive', + ) diff --git a/tests/unit/borg/test_break_lock.py b/tests/unit/borg/test_break_lock.py index ff4a5c10..8f5e2f9a 100644 --- a/tests/unit/borg/test_break_lock.py +++ b/tests/unit/borg/test_break_lock.py @@ -108,6 +108,18 @@ def test_break_lock_calls_borg_with_lock_wait_flags(): ) +def test_break_lock_calls_borg_with_extra_borg_options(): + flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) + insert_execute_command_mock(('borg', 'break-lock', '--extra', 'value with space', 'repo')) + + module.break_lock( + repository_path='repo', + config={'extra_borg_options': {'break_lock': '--extra "value with space"'}}, + local_borg_version='1.2.3', + global_arguments=flexmock(), + ) + + def test_break_lock_with_log_info_calls_borg_with_info_parameter(): flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) insert_execute_command_mock(('borg', 'break-lock', '--info', 'repo')) diff --git a/tests/unit/borg/test_change_passphrase.py b/tests/unit/borg/test_change_passphrase.py index 8bb61397..517f1dfd 100644 --- a/tests/unit/borg/test_change_passphrase.py +++ b/tests/unit/borg/test_change_passphrase.py @@ -145,6 +145,23 @@ def test_change_passphrase_calls_borg_with_lock_wait_flags(): ) +def test_change_passphrase_calls_borg_with_extra_borg_options(): + flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) + config = {'extra_borg_options': {'key_change_passphrase': '--extra "value with space"'}} + insert_execute_command_mock( + ('borg', 'key', 'change-passphrase', '--extra', 'value with space', 'repo'), + config=config, + ) + + module.change_passphrase( + repository_path='repo', + config=config, + local_borg_version='1.2.3', + change_passphrase_arguments=flexmock(), + global_arguments=flexmock(dry_run=False), + ) + + def test_change_passphrase_with_log_info_calls_borg_with_info_parameter(): flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) insert_execute_command_mock(('borg', 'key', 'change-passphrase', '--info', 'repo')) diff --git a/tests/unit/borg/test_delete.py b/tests/unit/borg/test_delete.py index 5dc9719f..e876cfe5 100644 --- a/tests/unit/borg/test_delete.py +++ b/tests/unit/borg/test_delete.py @@ -175,6 +175,27 @@ def test_make_delete_command_includes_lock_wait(): assert command == ('borg', 'delete', '--lock-wait', '5', 'repo') +def test_make_delete_command_includes_extra_borg_options(): + flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(()) + flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(()) + flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(()) + flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return( + ('repo',), + ) + + command = module.make_delete_command( + repository={'path': 'repo'}, + config={'extra_borg_options': {'delete': '--extra "value with space"'}}, + local_borg_version='1.2.3', + delete_arguments=flexmock(list_details=False, force=0, match_archives=None, archive=None), + global_arguments=flexmock(dry_run=False), + local_path='borg', + remote_path=None, + ) + + assert command == ('borg', 'delete', '--extra', 'value with space', 'repo') + + def test_make_delete_command_with_list_config_calls_borg_with_list_flag(): flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(()) flexmock(module.borgmatic.borg.flags).should_receive('make_flags').with_args( diff --git a/tests/unit/borg/test_export_key.py b/tests/unit/borg/test_export_key.py index e24bd031..b3f1e860 100644 --- a/tests/unit/borg/test_export_key.py +++ b/tests/unit/borg/test_export_key.py @@ -133,6 +133,20 @@ def test_export_key_calls_borg_with_lock_wait_flags(): ) +def test_export_key_calls_borg_with_extra_borg_options(): + flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) + flexmock(module.os.path).should_receive('exists').never() + insert_execute_command_mock(('borg', 'key', 'export', '--extra', 'value with space', 'repo')) + + module.export_key( + repository_path='repo', + config={'extra_borg_options': {'key_export': '--extra "value with space"'}}, + local_borg_version='1.2.3', + export_arguments=flexmock(paper=False, qr_html=False, path=None), + global_arguments=flexmock(dry_run=False), + ) + + def test_export_key_with_log_info_calls_borg_with_info_parameter(): flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) flexmock(module.os.path).should_receive('exists').never() diff --git a/tests/unit/borg/test_export_tar.py b/tests/unit/borg/test_export_tar.py index 1a1a1e1d..3cb72733 100644 --- a/tests/unit/borg/test_export_tar.py +++ b/tests/unit/borg/test_export_tar.py @@ -187,6 +187,28 @@ def test_export_tar_archive_calls_borg_with_lock_wait_flags(): ) +def test_export_tar_archive_calls_borg_with_extra_borg_options(): + flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') + flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',), + ) + insert_execute_command_mock( + ('borg', 'export-tar', '--extra', 'value with space', 'repo::archive', 'test.tar'), + ) + + module.export_tar_archive( + dry_run=False, + repository_path='repo', + archive='archive', + paths=None, + destination_path='test.tar', + config={'extra_borg_options': {'export_tar': '--extra "value with space"'}}, + local_borg_version='1.2.3', + global_arguments=flexmock(), + ) + + def test_export_tar_archive_with_log_info_calls_borg_with_info_flag(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER diff --git a/tests/unit/borg/test_extract.py b/tests/unit/borg/test_extract.py index d0197ee0..e293e687 100644 --- a/tests/unit/borg/test_extract.py +++ b/tests/unit/borg/test_extract.py @@ -174,6 +174,23 @@ def test_extract_last_archive_dry_run_calls_borg_with_lock_wait_flags(): ) +def test_extract_last_archive_dry_run_calls_borg_with_extra_borg_options(): + flexmock(module.repo_list).should_receive('resolve_archive_name').and_return('archive') + insert_execute_command_mock( + ('borg', 'extract', '--dry-run', '--extra', 'value with space', 'repo::archive'), + ) + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',), + ) + + module.extract_last_archive_dry_run( + config={'extra_borg_options': {'extract': '--extra "value with space"'}}, + local_borg_version='1.2.3', + global_arguments=flexmock(), + repository_path='repo', + ) + + def test_extract_archive_calls_borg_with_path_flags(): flexmock(module.os.path).should_receive('abspath').and_return('repo') insert_execute_command_mock(('borg', 'extract', 'repo::archive', 'path1', 'path2')) @@ -368,6 +385,29 @@ def test_extract_archive_calls_borg_with_lock_wait_flags(): ) +def test_extract_archive_calls_borg_with_extra_borg_options(): + flexmock(module.os.path).should_receive('abspath').and_return('repo') + insert_execute_command_mock(('borg', 'extract', '--extra', 'value with space', 'repo::archive')) + flexmock(module.feature).should_receive('available').and_return(True) + flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None) + 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=None, + config={'extra_borg_options': {'extract': '--extra "value with space"'}}, + local_borg_version='1.2.3', + global_arguments=flexmock(), + ) + + def test_extract_archive_with_log_info_calls_borg_with_info_parameter(): flexmock(module.os.path).should_receive('abspath').and_return('repo') insert_execute_command_mock(('borg', 'extract', '--info', 'repo::archive')) diff --git a/tests/unit/borg/test_import_key.py b/tests/unit/borg/test_import_key.py index f33f9a61..59f0ca03 100644 --- a/tests/unit/borg/test_import_key.py +++ b/tests/unit/borg/test_import_key.py @@ -137,6 +137,21 @@ def test_import_key_calls_borg_with_lock_wait_flags(): ) +def test_import_key_calls_borg_with_extra_borg_options(): + flexmock(module.flags).should_receive('make_flags').and_return(()) + flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) + flexmock(module.os.path).should_receive('exists').never() + insert_execute_command_mock(('borg', 'key', 'import', '--extra', 'value with space', 'repo')) + + module.import_key( + repository_path='repo', + config={'extra_borg_options': {'key_import': '--extra "value with space"'}}, + local_borg_version='1.2.3', + import_arguments=flexmock(paper=False, path=None), + global_arguments=flexmock(dry_run=False), + ) + + def test_import_key_with_log_info_calls_borg_with_info_parameter(): flexmock(module.flags).should_receive('make_flags').and_return(()) flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) diff --git a/tests/unit/borg/test_info.py b/tests/unit/borg/test_info.py index fd0ab8d8..357f0dad 100644 --- a/tests/unit/borg/test_info.py +++ b/tests/unit/borg/test_info.py @@ -300,6 +300,30 @@ def test_make_info_command_with_lock_wait_passes_through_to_command(): assert command == ('borg', 'info', '--lock-wait', '5', '--repo', 'repo') +def test_make_info_command_with_extra_borg_options_passes_through_to_command(): + flexmock(module.flags).should_receive('make_flags').and_return(()) + flexmock(module.flags).should_receive('make_match_archives_flags').with_args( + None, + None, + '2.3.4', + ).and_return(()) + flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(()) + flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo')) + config = {'extra_borg_options': {'info': '--extra "value with space"'}} + + command = module.make_info_command( + repository_path='repo', + config=config, + local_borg_version='2.3.4', + global_arguments=flexmock(), + info_arguments=flexmock(archive=None, json=False, prefix=None, match_archives=None), + local_path='borg', + remote_path=None, + ) + + assert command == ('borg', 'info', '--extra', 'value with space', '--repo', 'repo') + + def test_make_info_command_transforms_prefix_into_match_archives_flags(): flexmock(module.flags).should_receive('make_flags').and_return(()) flexmock(module.flags).should_receive('make_flags').with_args( diff --git a/tests/unit/borg/test_list.py b/tests/unit/borg/test_list.py index 4f6ec0b5..90e55fb7 100644 --- a/tests/unit/borg/test_list.py +++ b/tests/unit/borg/test_list.py @@ -129,6 +129,22 @@ def test_make_list_command_includes_lock_wait(): assert command == ('borg', 'list', '--lock-wait', '5', 'repo') +def test_make_list_command_includes_extra_borg_options(): + flexmock(module.flags).should_receive('make_flags').and_return(()) + flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(()) + flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) + + command = module.make_list_command( + repository_path='repo', + config={'extra_borg_options': {'list': '--extra "value with space"'}}, + local_borg_version='1.2.3', + list_arguments=flexmock(archive=None, paths=None, json=False), + global_arguments=flexmock(), + ) + + assert command == ('borg', 'list', '--extra', 'value with space', 'repo') + + def test_make_list_command_includes_archive(): flexmock(module.flags).should_receive('make_flags').and_return(()) flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(()) diff --git a/tests/unit/borg/test_mount.py b/tests/unit/borg/test_mount.py index 501e8851..4aa8d647 100644 --- a/tests/unit/borg/test_mount.py +++ b/tests/unit/borg/test_mount.py @@ -217,6 +217,26 @@ def test_mount_archive_calls_borg_with_lock_wait_flags(): ) +def test_mount_archive_calls_borg_with_extra_borg_options(): + 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', '--extra', 'value with space', 'repo::archive', '/mnt') + ) + + mount_arguments = flexmock(mount_point='/mnt', options=None, paths=None, foreground=False) + module.mount_archive( + repository_path='repo', + archive='archive', + mount_arguments=mount_arguments, + config={'extra_borg_options': {'mount': '--extra "value with space"'}}, + local_borg_version='1.2.3', + global_arguments=flexmock(), + ) + + 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( diff --git a/tests/unit/borg/test_recreate.py b/tests/unit/borg/test_recreate.py index 8df94a4c..4b7b281e 100644 --- a/tests/unit/borg/test_recreate.py +++ b/tests/unit/borg/test_recreate.py @@ -162,6 +162,42 @@ def test_recreate_with_lock_wait(): ) +def test_recreate_with_extra_borg_options(): + flexmock(module.borgmatic.borg.flags).should_receive('make_exclude_flags').and_return(()) + flexmock(module.borgmatic.borg.pattern).should_receive('write_patterns_file').and_return(None) + flexmock(module.borgmatic.borg.flags).should_receive('make_list_filter_flags').and_return('') + flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(()) + flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True) + flexmock(module.borgmatic.borg.flags).should_receive( + 'make_repository_archive_flags', + ).and_return( + ( + '--repo', + 'repo', + ), + ) + insert_execute_command_mock( + ('borg', 'recreate', '--extra', 'value with space', '--repo', 'repo') + ) + + module.recreate_archive( + repository='repo', + archive='archive', + config={'extra_borg_options': {'recreate': '--extra "value with space"'}}, + local_borg_version='1.2.3', + recreate_arguments=flexmock( + list=None, + target=None, + comment=None, + timestamp=None, + match_archives=None, + ), + global_arguments=flexmock(dry_run=False), + local_path='borg', + patterns=None, + ) + + def test_recreate_with_log_info(): flexmock(module.borgmatic.borg.flags).should_receive('make_exclude_flags').and_return(()) flexmock(module.borgmatic.borg.pattern).should_receive('write_patterns_file').and_return(None) diff --git a/tests/unit/borg/test_repo_create.py b/tests/unit/borg/test_repo_create.py index 50888f55..7507cdb7 100644 --- a/tests/unit/borg/test_repo_create.py +++ b/tests/unit/borg/test_repo_create.py @@ -486,7 +486,7 @@ def test_create_repository_with_umask_calls_borg_with_umask_flag(): ) -def test_create_repository_with_extra_borg_options_calls_borg_with_extra_options(): +def test_create_repository_calls_borg_with_extra_borg_options(): insert_repo_info_command_not_found_mock() insert_repo_create_command_mock( (*REPO_CREATE_COMMAND, '--extra', '--options', 'value with space', '--repo', 'repo'), @@ -509,6 +509,30 @@ def test_create_repository_with_extra_borg_options_calls_borg_with_extra_options ) +def test_create_repository_calls_borg_with_extra_borg_options_from_deprecated_init_option(): + flexmock(module.logger).should_receive('warning').once() + insert_repo_info_command_not_found_mock() + insert_repo_create_command_mock( + (*REPO_CREATE_COMMAND, '--extra', '--options', 'value with space', '--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( + dry_run=False, + repository_path='repo', + config={'extra_borg_options': {'init': '--extra --options "value with space"'}}, + local_borg_version='2.3.4', + global_arguments=flexmock(), + encryption_mode='repokey', + ) + + def test_create_repository_calls_borg_with_working_directory(): insert_repo_info_command_not_found_mock() insert_repo_create_command_mock( diff --git a/tests/unit/borg/test_repo_delete.py b/tests/unit/borg/test_repo_delete.py index 03925b4d..b2033e3e 100644 --- a/tests/unit/borg/test_repo_delete.py +++ b/tests/unit/borg/test_repo_delete.py @@ -216,6 +216,27 @@ def test_make_repo_delete_command_includes_lock_wait(): assert command == ('borg', 'repo-delete', '--lock-wait', '5', 'repo') +def test_make_repo_delete_command_includes_extra_borg_options(): + flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True) + flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(()) + flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(()) + flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return( + ('repo',), + ) + + command = module.make_repo_delete_command( + repository={'path': 'repo'}, + config={'extra_borg_options': {'repo_delete': '--extra "value with space"'}}, + local_borg_version='1.2.3', + repo_delete_arguments=flexmock(list_details=False, force=0), + global_arguments=flexmock(dry_run=False), + local_path='borg', + remote_path=None, + ) + + assert command == ('borg', 'repo-delete', '--extra', 'value with space', 'repo') + + def test_make_repo_delete_command_includes_list(): flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True) flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(()) diff --git a/tests/unit/borg/test_repo_info.py b/tests/unit/borg/test_repo_info.py index b4791618..f5823e3a 100644 --- a/tests/unit/borg/test_repo_info.py +++ b/tests/unit/borg/test_repo_info.py @@ -528,6 +528,48 @@ def test_display_repository_info_with_lock_wait_calls_borg_with_lock_wait_flags( ) +def test_display_repository_info_calls_borg_with_extra_borg_options(): + flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') + flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER + config = {'extra_borg_options': {'repo_info': '--extra "value with space"'}} + flexmock(module.feature).should_receive('available').and_return(True) + flexmock(module.flags).should_receive('make_flags').replace_with( + lambda name, value: (f'--{name}', str(value)) if value else (), + ) + flexmock(module.flags).should_receive('make_repository_flags').and_return( + ( + '--repo', + 'repo', + ), + ) + flexmock(module.environment).should_receive('make_environment') + flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None) + flexmock(module).should_receive('execute_command_and_capture_output').with_args( + ('borg', 'repo-info', '--extra', 'value with space', '--json', '--repo', 'repo'), + environment=None, + working_directory=None, + borg_local_path='borg', + borg_exit_codes=None, + ).and_return('[]') + flexmock(module.flags).should_receive('warn_for_aggressive_archive_flags') + flexmock(module).should_receive('execute_command').with_args( + ('borg', 'repo-info', '--extra', 'value with space', '--repo', 'repo'), + output_log_level=module.borgmatic.logger.ANSWER, + environment=None, + working_directory=None, + borg_local_path='borg', + borg_exit_codes=None, + ) + + module.display_repository_info( + repository_path='repo', + config=config, + local_borg_version='2.3.4', + repo_info_arguments=flexmock(json=False), + global_arguments=flexmock(), + ) + + def test_display_repository_info_calls_borg_with_working_directory(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER diff --git a/tests/unit/borg/test_repo_list.py b/tests/unit/borg/test_repo_list.py index 7b3909ba..8814bf8b 100644 --- a/tests/unit/borg/test_repo_list.py +++ b/tests/unit/borg/test_repo_list.py @@ -412,6 +412,42 @@ def test_get_latest_archive_with_lock_wait_calls_borg_with_lock_wait_flags(): ) +def test_get_latest_archive_calls_borg_with_extra_borg_options(): + expected_archive = {'name': 'archive-name', 'id': 'd34db33f'} + flexmock(module.feature).should_receive('available').and_return(False) + flexmock(module.flags).should_receive('make_flags').and_return(()) + flexmock(module.flags).should_receive('make_flags').with_args('last', 1).and_return( + ('--last', '1') + ) + flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) + flexmock(module.environment).should_receive('make_environment') + flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None) + flexmock(module).should_receive('execute_command_and_capture_output').with_args( + ( + 'borg', + 'list', + *BORG_LIST_LATEST_ARGUMENTS[:-1], + '--extra', + 'value with space', + *BORG_LIST_LATEST_ARGUMENTS[-1:], + ), + environment=None, + working_directory=None, + borg_local_path='borg', + borg_exit_codes=None, + ).and_return(json.dumps({'archives': [expected_archive]})) + + assert ( + module.get_latest_archive( + 'repo', + config={'extra_borg_options': {'repo_list': '--extra "value with space"'}}, + local_borg_version='1.2.3', + global_arguments=flexmock(), + ) + == expected_archive + ) + + def test_get_latest_archive_with_consider_checkpoints_calls_borg_with_consider_checkpoints_flag(): expected_archive = {'name': 'archive-name', 'id': 'd34db33f'} flexmock(module.feature).should_receive('available').and_return(False) @@ -706,6 +742,33 @@ def test_make_repo_list_command_includes_lock_wait(): assert command == ('borg', 'list', '--lock-wait', '5', 'repo') +def test_make_repo_list_command_includes_extra_borg_options(): + flexmock(module.flags).should_receive('make_flags').and_return(()) + flexmock(module.flags).should_receive('make_match_archives_flags').with_args( + None, + None, + '1.2.3', + ).and_return(()) + flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(()) + flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) + + command = module.make_repo_list_command( + repository_path='repo', + config={'extra_borg_options': {'repo_list': '--extra "value with space"'}}, + local_borg_version='1.2.3', + repo_list_arguments=flexmock( + archive=None, + paths=None, + json=False, + prefix=None, + match_archives=None, + ), + global_arguments=flexmock(), + ) + + assert command == ('borg', 'list', '--extra', 'value with space', 'repo') + + def test_make_repo_list_command_includes_local_path(): flexmock(module.flags).should_receive('make_flags').and_return(()) flexmock(module.flags).should_receive('make_match_archives_flags').with_args( diff --git a/tests/unit/borg/test_transfer.py b/tests/unit/borg/test_transfer.py index 95dc001d..42ef0198 100644 --- a/tests/unit/borg/test_transfer.py +++ b/tests/unit/borg/test_transfer.py @@ -482,6 +482,41 @@ def test_transfer_archives_with_lock_wait_calls_borg_with_lock_wait_flags(): ) +def test_transfer_archives_calls_borg_with_extra_borg_options(): + flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') + flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER + flexmock(module.flags).should_receive('make_flags').and_return(()) + flexmock(module.flags).should_receive('make_match_archives_flags').and_return(()) + flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(()) + flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo')) + config = {'extra_borg_options': {'transfer': '--extra "value with space"'}} + flexmock(module.environment).should_receive('make_environment') + flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None) + flexmock(module).should_receive('execute_command').with_args( + ('borg', 'transfer', '--extra', 'value with space', '--repo', 'repo'), + output_log_level=module.borgmatic.logger.ANSWER, + output_file=None, + environment=None, + working_directory=None, + borg_local_path='borg', + borg_exit_codes=None, + ) + + module.transfer_archives( + dry_run=False, + repository_path='repo', + config=config, + local_borg_version='2.3.4', + transfer_arguments=flexmock( + archive=None, + progress=None, + match_archives=None, + source_repository=None, + ), + global_arguments=flexmock(), + ) + + def test_transfer_archives_with_progress_calls_borg_with_progress_flags(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER diff --git a/tests/unit/borg/test_umount.py b/tests/unit/borg/test_umount.py index 2f73c970..d03870c6 100644 --- a/tests/unit/borg/test_umount.py +++ b/tests/unit/borg/test_umount.py @@ -44,6 +44,16 @@ def test_unmount_archive_with_log_debug_calls_borg_with_debug_parameters(): module.unmount_archive(config={}, mount_point='/mnt') +def test_unmount_archive_calls_borg_with_extra_borg_options(): + insert_execute_command_mock( + ('borg', 'umount', '--extra', 'value with space', '/mnt'), borg_local_path='borg' + ) + + module.unmount_archive( + config={'extra_borg_options': {'umount': '--extra "value with space"'}}, mount_point='/mnt' + ) + + def test_unmount_archive_calls_borg_with_local_path(): insert_execute_command_mock(('borg1', 'umount', '/mnt'), borg_local_path='borg1')