From 5b615d51a41dd4c91eec9199db6b3dbba6261aca Mon Sep 17 00:00:00 2001 From: Dan Helfman Date: Sun, 29 May 2022 15:43:03 -0700 Subject: [PATCH] Add support for "borgmatic borg debug" command (#538). --- NEWS | 1 + borgmatic/borg/borg.py | 13 ++++++++++--- tests/unit/borg/test_borg.py | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index f566233df..0bb1e29b7 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,7 @@ https://torsion.org/borgmatic/docs/how-to/deal-with-very-large-backups/#check-frequency * #536: Fix generate-borgmatic-config to support more complex schema changes like the new Healthchecks configuration options when the "--source" flag is used. + * #538: Add support for "borgmatic borg debug" command. * Add Bash completion script so you can tab-complete the borgmatic command-line. See the documentation for more information: https://torsion.org/borgmatic/docs/how-to/set-up-backups/#shell-completion diff --git a/borgmatic/borg/borg.py b/borgmatic/borg/borg.py index ff3212f41..d40bb9292 100644 --- a/borgmatic/borg/borg.py +++ b/borgmatic/borg/borg.py @@ -7,6 +7,8 @@ logger = logging.getLogger(__name__) REPOSITORYLESS_BORG_COMMANDS = {'serve', None} +BORG_COMMANDS_WITH_SUBCOMMANDS = {'key', 'debug'} +BORG_SUBCOMMANDS_WITHOUT_REPOSITORY = (('debug', 'info'), ('debug', 'convert-profile')) def run_arbitrary_borg( @@ -22,15 +24,20 @@ def run_arbitrary_borg( try: options = options[1:] if options[0] == '--' else options - # Borg's "key" command has a sub-command ("export", etc.) that must follow it. - command_options_start_index = 2 if options[0] == 'key' else 1 + # Borg commands like "key" have a sub-command ("export", etc.) that must follow it. + command_options_start_index = 2 if options[0] in BORG_COMMANDS_WITH_SUBCOMMANDS else 1 borg_command = tuple(options[:command_options_start_index]) command_options = tuple(options[command_options_start_index:]) except IndexError: borg_command = () command_options = () - repository_archive = '::'.join((repository, archive)) if repository and archive else repository + if borg_command in BORG_SUBCOMMANDS_WITHOUT_REPOSITORY: + repository_archive = None + else: + repository_archive = ( + '::'.join((repository, archive)) if repository and archive else repository + ) full_command = ( (local_path,) diff --git a/tests/unit/borg/test_borg.py b/tests/unit/borg/test_borg.py index 0174a91c9..6cec02c6e 100644 --- a/tests/unit/borg/test_borg.py +++ b/tests/unit/borg/test_borg.py @@ -131,3 +131,37 @@ def test_run_arbitrary_borg_passes_key_sub_command_to_borg_before_repository(): module.run_arbitrary_borg( repository='repo', storage_config={}, options=['key', 'export'], ) + + +def test_run_arbitrary_borg_passes_debug_sub_command_to_borg_before_repository(): + flexmock(module).should_receive('execute_command').with_args( + ('borg', 'debug', 'dump-manifest', 'repo', 'path'), + output_log_level=logging.WARNING, + borg_local_path='borg', + ) + + module.run_arbitrary_borg( + repository='repo', storage_config={}, options=['debug', 'dump-manifest', 'path'], + ) + + +def test_run_arbitrary_borg_with_debug_info_command_does_not_pass_borg_repository(): + flexmock(module).should_receive('execute_command').with_args( + ('borg', 'debug', 'info'), output_log_level=logging.WARNING, borg_local_path='borg', + ) + + module.run_arbitrary_borg( + repository='repo', storage_config={}, options=['debug', 'info'], + ) + + +def test_run_arbitrary_borg_with_debug_convert_profile_command_does_not_pass_borg_repository(): + flexmock(module).should_receive('execute_command').with_args( + ('borg', 'debug', 'convert-profile', 'in', 'out'), + output_log_level=logging.WARNING, + borg_local_path='borg', + ) + + module.run_arbitrary_borg( + repository='repo', storage_config={}, options=['debug', 'convert-profile', 'in', 'out'], + )