diff --git a/NEWS b/NEWS index d019c5bf..dac9e98a 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,6 @@ 1.4.16 + * #256: Fix for "before_backup" hook not triggering an error when the command contains "borg" and + has an exit code of 1. * #257: Fix for garbled Borg file listing when using "borgmatic create --progress" with verbosity level 1 or 2. * #260: Fix for missing Healthchecks monitoring payload or HTTP 500 due to incorrect unicode diff --git a/borgmatic/borg/create.py b/borgmatic/borg/create.py index 3190a8fc..879a94a1 100644 --- a/borgmatic/borg/create.py +++ b/borgmatic/borg/create.py @@ -196,7 +196,7 @@ def create_archive( # The progress output isn't compatible with captured and logged output, as progress messes with # the terminal directly. if progress: - execute_command_without_capture(full_command) + execute_command_without_capture(full_command, error_on_warnings=False) return if json: @@ -206,4 +206,4 @@ def create_archive( else: output_log_level = logging.INFO - return execute_command(full_command, output_log_level) + return execute_command(full_command, output_log_level, error_on_warnings=False) diff --git a/borgmatic/borg/extract.py b/borgmatic/borg/extract.py index 7a32ef6d..09af5376 100644 --- a/borgmatic/borg/extract.py +++ b/borgmatic/borg/extract.py @@ -27,7 +27,7 @@ def extract_last_archive_dry_run(repository, lock_wait=None, local_path='borg', + (repository,) ) - list_output = execute_command(full_list_command, output_log_level=None) + list_output = execute_command(full_list_command, output_log_level=None, error_on_warnings=False) try: last_archive_name = list_output.strip().splitlines()[-1] diff --git a/borgmatic/borg/info.py b/borgmatic/borg/info.py index cbc50d12..3ff9312c 100644 --- a/borgmatic/borg/info.py +++ b/borgmatic/borg/info.py @@ -39,5 +39,7 @@ def display_archives_info( ) return execute_command( - full_command, output_log_level=None if info_arguments.json else logging.WARNING + full_command, + output_log_level=None if info_arguments.json else logging.WARNING, + error_on_warnings=False, ) diff --git a/borgmatic/borg/init.py b/borgmatic/borg/init.py index cb787ae9..1ec25c07 100644 --- a/borgmatic/borg/init.py +++ b/borgmatic/borg/init.py @@ -45,4 +45,4 @@ def initialize_repository( ) # Don't use execute_command() here because it doesn't support interactive prompts. - execute_command_without_capture(init_command) + execute_command_without_capture(init_command, error_on_warnings=False) diff --git a/borgmatic/borg/list.py b/borgmatic/borg/list.py index 854cefff..bcbe36e2 100644 --- a/borgmatic/borg/list.py +++ b/borgmatic/borg/list.py @@ -46,5 +46,7 @@ def list_archives(repository, storage_config, list_arguments, local_path='borg', ) return execute_command( - full_command, output_log_level=None if list_arguments.json else logging.WARNING + full_command, + output_log_level=None if list_arguments.json else logging.WARNING, + error_on_warnings=False, ) diff --git a/borgmatic/borg/mount.py b/borgmatic/borg/mount.py index 6580717c..4e700097 100644 --- a/borgmatic/borg/mount.py +++ b/borgmatic/borg/mount.py @@ -40,7 +40,7 @@ def mount_archive( # Don't capture the output when foreground mode is used so that ctrl-C can work properly. if foreground: - execute_command_without_capture(full_command) + execute_command_without_capture(full_command, error_on_warnings=False) return - execute_command(full_command) + execute_command(full_command, error_on_warnings=False) diff --git a/borgmatic/borg/prune.py b/borgmatic/borg/prune.py index ec5963f9..584973e1 100644 --- a/borgmatic/borg/prune.py +++ b/borgmatic/borg/prune.py @@ -64,4 +64,8 @@ def prune_archives( + (repository,) ) - execute_command(full_command, output_log_level=logging.WARNING if stats else logging.INFO) + execute_command( + full_command, + output_log_level=logging.WARNING if stats else logging.INFO, + error_on_warnings=False, + ) diff --git a/borgmatic/execute.py b/borgmatic/execute.py index 4b791b9b..0d5047c1 100644 --- a/borgmatic/execute.py +++ b/borgmatic/execute.py @@ -9,15 +9,15 @@ ERROR_OUTPUT_MAX_LINE_COUNT = 25 BORG_ERROR_EXIT_CODE = 2 -def exit_code_indicates_error(command, exit_code, error_on_warnings=False): +def exit_code_indicates_error(command, exit_code, error_on_warnings=True): ''' Return True if the given exit code from running the command corresponds to an error. + If error on warnings is False, then treat exit code 1 as a warning instead of an error. ''' - # If we're running something other than Borg, treat all non-zero exit codes as errors. - if 'borg' in command[0] and not error_on_warnings: - return bool(exit_code >= BORG_ERROR_EXIT_CODE) + if error_on_warnings: + return bool(exit_code != 0) - return bool(exit_code != 0) + return bool(exit_code >= BORG_ERROR_EXIT_CODE) def log_output(command, process, output_buffer, output_log_level, error_on_warnings): @@ -65,7 +65,7 @@ def execute_command( shell=False, extra_environment=None, working_directory=None, - error_on_warnings=False, + error_on_warnings=True, ): ''' Execute the given command (a sequence of command/argument strings) and log its output at the @@ -75,7 +75,7 @@ def execute_command( file. If shell is True, execute the command within a shell. If an extra environment dict is given, then use it to augment the current environment, and pass the result into the command. If a working directory is given, use that as the present working directory when running the - command. + command. If error on warnings is False, then treat exit code 1 as a warning instead of an error. Raise subprocesses.CalledProcessError if an error occurs while running the command. ''' @@ -110,14 +110,14 @@ def execute_command( ) -def execute_command_without_capture(full_command, working_directory=None, error_on_warnings=False): +def execute_command_without_capture(full_command, working_directory=None, error_on_warnings=True): ''' Execute the given command (a sequence of command/argument strings), but don't capture or log its output in any way. This is necessary for commands that monkey with the terminal (e.g. progress display) or provide interactive prompts. If a working directory is given, use that as the present working directory when running the - command. + command. If error on warnings is False, then treat exit code 1 as a warning instead of an error. ''' logger.debug(' '.join(full_command)) diff --git a/tests/unit/borg/test_create.py b/tests/unit/borg/test_create.py index d2cb12f0..5819df02 100644 --- a/tests/unit/borg/test_create.py +++ b/tests/unit/borg/test_create.py @@ -206,7 +206,9 @@ def test_create_archive_calls_borg_with_parameters(): flexmock(module).should_receive('_make_pattern_flags').and_return(()) flexmock(module).should_receive('_make_exclude_flags').and_return(()) flexmock(module).should_receive('execute_command').with_args( - ('borg', 'create') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO + ('borg', 'create') + ARCHIVE_WITH_PATHS, + output_log_level=logging.INFO, + error_on_warnings=False, ) module.create_archive( @@ -232,7 +234,9 @@ def test_create_archive_with_patterns_calls_borg_with_patterns(): flexmock(module).should_receive('_make_pattern_flags').and_return(pattern_flags) flexmock(module).should_receive('_make_exclude_flags').and_return(()) flexmock(module).should_receive('execute_command').with_args( - ('borg', 'create') + pattern_flags + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO + ('borg', 'create') + pattern_flags + ARCHIVE_WITH_PATHS, + output_log_level=logging.INFO, + error_on_warnings=False, ) module.create_archive( @@ -258,7 +262,9 @@ def test_create_archive_with_exclude_patterns_calls_borg_with_excludes(): flexmock(module).should_receive('_make_pattern_flags').and_return(()) flexmock(module).should_receive('_make_exclude_flags').and_return(exclude_flags) flexmock(module).should_receive('execute_command').with_args( - ('borg', 'create') + exclude_flags + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO + ('borg', 'create') + exclude_flags + ARCHIVE_WITH_PATHS, + output_log_level=logging.INFO, + error_on_warnings=False, ) module.create_archive( @@ -284,6 +290,7 @@ def test_create_archive_with_log_info_calls_borg_with_info_parameter(): flexmock(module).should_receive('execute_command').with_args( ('borg', 'create', '--list', '--filter', 'AME-', '--info', '--stats') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO, + error_on_warnings=False, ) insert_logging_mock(logging.INFO) @@ -308,7 +315,9 @@ def test_create_archive_with_log_info_and_json_suppresses_most_borg_output(): flexmock(module).should_receive('_make_pattern_flags').and_return(()) flexmock(module).should_receive('_make_exclude_flags').and_return(()) flexmock(module).should_receive('execute_command').with_args( - ('borg', 'create', '--json') + ARCHIVE_WITH_PATHS, output_log_level=None + ('borg', 'create', '--json') + ARCHIVE_WITH_PATHS, + output_log_level=None, + error_on_warnings=False, ) insert_logging_mock(logging.INFO) @@ -336,6 +345,7 @@ def test_create_archive_with_log_debug_calls_borg_with_debug_parameter(): ('borg', 'create', '--list', '--filter', 'AME-', '--stats', '--debug', '--show-rc') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO, + error_on_warnings=False, ) insert_logging_mock(logging.DEBUG) @@ -359,7 +369,9 @@ def test_create_archive_with_log_debug_and_json_suppresses_most_borg_output(): flexmock(module).should_receive('_make_pattern_flags').and_return(()) flexmock(module).should_receive('_make_exclude_flags').and_return(()) flexmock(module).should_receive('execute_command').with_args( - ('borg', 'create', '--json') + ARCHIVE_WITH_PATHS, output_log_level=None + ('borg', 'create', '--json') + ARCHIVE_WITH_PATHS, + output_log_level=None, + error_on_warnings=False, ) insert_logging_mock(logging.DEBUG) @@ -385,7 +397,9 @@ def test_create_archive_with_dry_run_calls_borg_with_dry_run_parameter(): flexmock(module).should_receive('_make_pattern_flags').and_return(()) flexmock(module).should_receive('_make_exclude_flags').and_return(()) flexmock(module).should_receive('execute_command').with_args( - ('borg', 'create', '--dry-run') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO + ('borg', 'create', '--dry-run') + ARCHIVE_WITH_PATHS, + output_log_level=logging.INFO, + error_on_warnings=False, ) module.create_archive( @@ -414,6 +428,7 @@ def test_create_archive_with_dry_run_and_log_info_calls_borg_without_stats_param ('borg', 'create', '--list', '--filter', 'AME-', '--info', '--dry-run') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO, + error_on_warnings=False, ) insert_logging_mock(logging.INFO) @@ -443,6 +458,7 @@ def test_create_archive_with_dry_run_and_log_debug_calls_borg_without_stats_para ('borg', 'create', '--list', '--filter', 'AME-', '--debug', '--show-rc', '--dry-run') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO, + error_on_warnings=False, ) insert_logging_mock(logging.DEBUG) @@ -468,6 +484,7 @@ def test_create_archive_with_checkpoint_interval_calls_borg_with_checkpoint_inte flexmock(module).should_receive('execute_command').with_args( ('borg', 'create', '--checkpoint-interval', '600') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO, + error_on_warnings=False, ) module.create_archive( @@ -492,6 +509,7 @@ def test_create_archive_with_chunker_params_calls_borg_with_chunker_params_param flexmock(module).should_receive('execute_command').with_args( ('borg', 'create', '--chunker-params', '1,2,3,4') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO, + error_on_warnings=False, ) module.create_archive( @@ -516,6 +534,7 @@ def test_create_archive_with_compression_calls_borg_with_compression_parameters( flexmock(module).should_receive('execute_command').with_args( ('borg', 'create', '--compression', 'rle') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO, + error_on_warnings=False, ) module.create_archive( @@ -540,6 +559,7 @@ def test_create_archive_with_remote_rate_limit_calls_borg_with_remote_ratelimit_ flexmock(module).should_receive('execute_command').with_args( ('borg', 'create', '--remote-ratelimit', '100') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO, + error_on_warnings=False, ) module.create_archive( @@ -562,7 +582,9 @@ def test_create_archive_with_one_file_system_calls_borg_with_one_file_system_par flexmock(module).should_receive('_make_pattern_flags').and_return(()) flexmock(module).should_receive('_make_exclude_flags').and_return(()) flexmock(module).should_receive('execute_command').with_args( - ('borg', 'create', '--one-file-system') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO + ('borg', 'create', '--one-file-system') + ARCHIVE_WITH_PATHS, + output_log_level=logging.INFO, + error_on_warnings=False, ) module.create_archive( @@ -586,7 +608,9 @@ def test_create_archive_with_numeric_owner_calls_borg_with_numeric_owner_paramet flexmock(module).should_receive('_make_pattern_flags').and_return(()) flexmock(module).should_receive('_make_exclude_flags').and_return(()) flexmock(module).should_receive('execute_command').with_args( - ('borg', 'create', '--numeric-owner') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO + ('borg', 'create', '--numeric-owner') + ARCHIVE_WITH_PATHS, + output_log_level=logging.INFO, + error_on_warnings=False, ) module.create_archive( @@ -610,7 +634,9 @@ def test_create_archive_with_read_special_calls_borg_with_read_special_parameter flexmock(module).should_receive('_make_pattern_flags').and_return(()) flexmock(module).should_receive('_make_exclude_flags').and_return(()) flexmock(module).should_receive('execute_command').with_args( - ('borg', 'create', '--read-special') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO + ('borg', 'create', '--read-special') + ARCHIVE_WITH_PATHS, + output_log_level=logging.INFO, + error_on_warnings=False, ) module.create_archive( @@ -635,7 +661,9 @@ def test_create_archive_with_option_true_calls_borg_without_corresponding_parame flexmock(module).should_receive('_make_pattern_flags').and_return(()) flexmock(module).should_receive('_make_exclude_flags').and_return(()) flexmock(module).should_receive('execute_command').with_args( - ('borg', 'create') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO + ('borg', 'create') + ARCHIVE_WITH_PATHS, + output_log_level=logging.INFO, + error_on_warnings=False, ) module.create_archive( @@ -662,6 +690,7 @@ def test_create_archive_with_option_false_calls_borg_with_corresponding_paramete flexmock(module).should_receive('execute_command').with_args( ('borg', 'create', '--no' + option_name.replace('_', '')) + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO, + error_on_warnings=False, ) module.create_archive( @@ -687,6 +716,7 @@ def test_create_archive_with_files_cache_calls_borg_with_files_cache_parameters( flexmock(module).should_receive('execute_command').with_args( ('borg', 'create', '--files-cache', 'ctime,size') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO, + error_on_warnings=False, ) module.create_archive( @@ -710,7 +740,9 @@ def test_create_archive_with_local_path_calls_borg_via_local_path(): flexmock(module).should_receive('_make_pattern_flags').and_return(()) flexmock(module).should_receive('_make_exclude_flags').and_return(()) flexmock(module).should_receive('execute_command').with_args( - ('borg1', 'create') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO + ('borg1', 'create') + ARCHIVE_WITH_PATHS, + output_log_level=logging.INFO, + error_on_warnings=False, ) module.create_archive( @@ -736,6 +768,7 @@ def test_create_archive_with_remote_path_calls_borg_with_remote_path_parameters( flexmock(module).should_receive('execute_command').with_args( ('borg', 'create', '--remote-path', 'borg1') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO, + error_on_warnings=False, ) module.create_archive( @@ -759,7 +792,9 @@ def test_create_archive_with_umask_calls_borg_with_umask_parameters(): flexmock(module).should_receive('_make_pattern_flags').and_return(()) flexmock(module).should_receive('_make_exclude_flags').and_return(()) flexmock(module).should_receive('execute_command').with_args( - ('borg', 'create', '--umask', '740') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO + ('borg', 'create', '--umask', '740') + ARCHIVE_WITH_PATHS, + output_log_level=logging.INFO, + error_on_warnings=False, ) module.create_archive( @@ -782,7 +817,9 @@ def test_create_archive_with_lock_wait_calls_borg_with_lock_wait_parameters(): flexmock(module).should_receive('_make_pattern_flags').and_return(()) flexmock(module).should_receive('_make_exclude_flags').and_return(()) flexmock(module).should_receive('execute_command').with_args( - ('borg', 'create', '--lock-wait', '5') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO + ('borg', 'create', '--lock-wait', '5') + ARCHIVE_WITH_PATHS, + output_log_level=logging.INFO, + error_on_warnings=False, ) module.create_archive( @@ -805,7 +842,9 @@ def test_create_archive_with_stats_calls_borg_with_stats_parameter(): flexmock(module).should_receive('_make_pattern_flags').and_return(()) flexmock(module).should_receive('_make_exclude_flags').and_return(()) flexmock(module).should_receive('execute_command').with_args( - ('borg', 'create', '--stats') + ARCHIVE_WITH_PATHS, output_log_level=logging.WARNING + ('borg', 'create', '--stats') + ARCHIVE_WITH_PATHS, + output_log_level=logging.WARNING, + error_on_warnings=False, ) module.create_archive( @@ -829,7 +868,8 @@ def test_create_archive_with_progress_and_log_info_calls_borg_with_progress_para flexmock(module).should_receive('_make_pattern_flags').and_return(()) flexmock(module).should_receive('_make_exclude_flags').and_return(()) flexmock(module).should_receive('execute_command_without_capture').with_args( - ('borg', 'create', '--info', '--stats', '--progress') + ARCHIVE_WITH_PATHS + ('borg', 'create', '--info', '--stats', '--progress') + ARCHIVE_WITH_PATHS, + error_on_warnings=False, ) insert_logging_mock(logging.INFO) @@ -854,7 +894,7 @@ def test_create_archive_with_progress_calls_borg_with_progress_parameter(): flexmock(module).should_receive('_make_pattern_flags').and_return(()) flexmock(module).should_receive('_make_exclude_flags').and_return(()) flexmock(module).should_receive('execute_command_without_capture').with_args( - ('borg', 'create', '--progress') + ARCHIVE_WITH_PATHS + ('borg', 'create', '--progress') + ARCHIVE_WITH_PATHS, error_on_warnings=False ) module.create_archive( @@ -878,7 +918,9 @@ def test_create_archive_with_json_calls_borg_with_json_parameter(): flexmock(module).should_receive('_make_pattern_flags').and_return(()) flexmock(module).should_receive('_make_exclude_flags').and_return(()) flexmock(module).should_receive('execute_command').with_args( - ('borg', 'create', '--json') + ARCHIVE_WITH_PATHS, output_log_level=None + ('borg', 'create', '--json') + ARCHIVE_WITH_PATHS, + output_log_level=None, + error_on_warnings=False, ).and_return('[]') json_output = module.create_archive( @@ -904,7 +946,9 @@ def test_create_archive_with_stats_and_json_calls_borg_without_stats_parameter() flexmock(module).should_receive('_make_pattern_flags').and_return(()) flexmock(module).should_receive('_make_exclude_flags').and_return(()) flexmock(module).should_receive('execute_command').with_args( - ('borg', 'create', '--json') + ARCHIVE_WITH_PATHS, output_log_level=None + ('borg', 'create', '--json') + ARCHIVE_WITH_PATHS, + output_log_level=None, + error_on_warnings=False, ).and_return('[]') json_output = module.create_archive( @@ -933,6 +977,7 @@ def test_create_archive_with_source_directories_glob_expands(): flexmock(module).should_receive('execute_command').with_args( ('borg', 'create', 'repo::{}'.format(DEFAULT_ARCHIVE_NAME), 'foo', 'food'), output_log_level=logging.INFO, + error_on_warnings=False, ) flexmock(module.glob).should_receive('glob').with_args('foo*').and_return(['foo', 'food']) @@ -958,6 +1003,7 @@ def test_create_archive_with_non_matching_source_directories_glob_passes_through flexmock(module).should_receive('execute_command').with_args( ('borg', 'create', 'repo::{}'.format(DEFAULT_ARCHIVE_NAME), 'foo*'), output_log_level=logging.INFO, + error_on_warnings=False, ) flexmock(module.glob).should_receive('glob').with_args('foo*').and_return([]) @@ -983,6 +1029,7 @@ def test_create_archive_with_glob_calls_borg_with_expanded_directories(): flexmock(module).should_receive('execute_command').with_args( ('borg', 'create', 'repo::{}'.format(DEFAULT_ARCHIVE_NAME), 'foo', 'food'), output_log_level=logging.INFO, + error_on_warnings=False, ) module.create_archive( @@ -1005,7 +1052,9 @@ def test_create_archive_with_archive_name_format_calls_borg_with_archive_name(): flexmock(module).should_receive('_make_pattern_flags').and_return(()) flexmock(module).should_receive('_make_exclude_flags').and_return(()) flexmock(module).should_receive('execute_command').with_args( - ('borg', 'create', 'repo::ARCHIVE_NAME', 'foo', 'bar'), output_log_level=logging.INFO + ('borg', 'create', 'repo::ARCHIVE_NAME', 'foo', 'bar'), + output_log_level=logging.INFO, + error_on_warnings=False, ) module.create_archive( @@ -1030,6 +1079,7 @@ def test_create_archive_with_archive_name_format_accepts_borg_placeholders(): flexmock(module).should_receive('execute_command').with_args( ('borg', 'create', 'repo::Documents_{hostname}-{now}', 'foo', 'bar'), output_log_level=logging.INFO, + error_on_warnings=False, ) module.create_archive( diff --git a/tests/unit/borg/test_extract.py b/tests/unit/borg/test_extract.py index 027523c8..f6c904e3 100644 --- a/tests/unit/borg/test_extract.py +++ b/tests/unit/borg/test_extract.py @@ -15,7 +15,7 @@ def insert_execute_command_mock(command, working_directory=None, error_on_warnin def insert_execute_command_output_mock(command, result): flexmock(module).should_receive('execute_command').with_args( - command, output_log_level=None + command, output_log_level=None, error_on_warnings=False ).and_return(result).once() diff --git a/tests/unit/borg/test_info.py b/tests/unit/borg/test_info.py index 93ff843a..f09d4e8d 100644 --- a/tests/unit/borg/test_info.py +++ b/tests/unit/borg/test_info.py @@ -10,7 +10,7 @@ from ..test_verbosity import insert_logging_mock def test_display_archives_info_calls_borg_with_parameters(): flexmock(module).should_receive('execute_command').with_args( - ('borg', 'info', 'repo'), output_log_level=logging.WARNING + ('borg', 'info', 'repo'), output_log_level=logging.WARNING, error_on_warnings=False ) module.display_archives_info( @@ -20,7 +20,9 @@ def test_display_archives_info_calls_borg_with_parameters(): def test_display_archives_info_with_log_info_calls_borg_with_info_parameter(): flexmock(module).should_receive('execute_command').with_args( - ('borg', 'info', '--info', 'repo'), output_log_level=logging.WARNING + ('borg', 'info', '--info', 'repo'), + output_log_level=logging.WARNING, + error_on_warnings=False, ) insert_logging_mock(logging.INFO) module.display_archives_info( @@ -30,7 +32,7 @@ def test_display_archives_info_with_log_info_calls_borg_with_info_parameter(): def test_display_archives_info_with_log_info_and_json_suppresses_most_borg_output(): flexmock(module).should_receive('execute_command').with_args( - ('borg', 'info', '--json', 'repo'), output_log_level=None + ('borg', 'info', '--json', 'repo'), output_log_level=None, error_on_warnings=False ).and_return('[]') insert_logging_mock(logging.INFO) @@ -43,7 +45,9 @@ def test_display_archives_info_with_log_info_and_json_suppresses_most_borg_outpu def test_display_archives_info_with_log_debug_calls_borg_with_debug_parameter(): flexmock(module).should_receive('execute_command').with_args( - ('borg', 'info', '--debug', '--show-rc', 'repo'), output_log_level=logging.WARNING + ('borg', 'info', '--debug', '--show-rc', 'repo'), + output_log_level=logging.WARNING, + error_on_warnings=False, ) insert_logging_mock(logging.DEBUG) @@ -54,7 +58,7 @@ def test_display_archives_info_with_log_debug_calls_borg_with_debug_parameter(): def test_display_archives_info_with_log_debug_and_json_suppresses_most_borg_output(): flexmock(module).should_receive('execute_command').with_args( - ('borg', 'info', '--json', 'repo'), output_log_level=None + ('borg', 'info', '--json', 'repo'), output_log_level=None, error_on_warnings=False ).and_return('[]') insert_logging_mock(logging.DEBUG) @@ -67,7 +71,7 @@ def test_display_archives_info_with_log_debug_and_json_suppresses_most_borg_outp def test_display_archives_info_with_json_calls_borg_with_json_parameter(): flexmock(module).should_receive('execute_command').with_args( - ('borg', 'info', '--json', 'repo'), output_log_level=None + ('borg', 'info', '--json', 'repo'), output_log_level=None, error_on_warnings=False ).and_return('[]') json_output = module.display_archives_info( @@ -79,7 +83,7 @@ def test_display_archives_info_with_json_calls_borg_with_json_parameter(): def test_display_archives_info_with_archive_calls_borg_with_archive_parameter(): flexmock(module).should_receive('execute_command').with_args( - ('borg', 'info', 'repo::archive'), output_log_level=logging.WARNING + ('borg', 'info', 'repo::archive'), output_log_level=logging.WARNING, error_on_warnings=False ) module.display_archives_info( @@ -89,7 +93,7 @@ def test_display_archives_info_with_archive_calls_borg_with_archive_parameter(): def test_display_archives_info_with_local_path_calls_borg_via_local_path(): flexmock(module).should_receive('execute_command').with_args( - ('borg1', 'info', 'repo'), output_log_level=logging.WARNING + ('borg1', 'info', 'repo'), output_log_level=logging.WARNING, error_on_warnings=False ) module.display_archives_info( @@ -102,7 +106,9 @@ def test_display_archives_info_with_local_path_calls_borg_via_local_path(): def test_display_archives_info_with_remote_path_calls_borg_with_remote_path_parameters(): flexmock(module).should_receive('execute_command').with_args( - ('borg', 'info', '--remote-path', 'borg1', 'repo'), output_log_level=logging.WARNING + ('borg', 'info', '--remote-path', 'borg1', 'repo'), + output_log_level=logging.WARNING, + error_on_warnings=False, ) module.display_archives_info( @@ -116,7 +122,9 @@ def test_display_archives_info_with_remote_path_calls_borg_with_remote_path_para def test_display_archives_info_with_lock_wait_calls_borg_with_lock_wait_parameters(): storage_config = {'lock_wait': 5} flexmock(module).should_receive('execute_command').with_args( - ('borg', 'info', '--lock-wait', '5', 'repo'), output_log_level=logging.WARNING + ('borg', 'info', '--lock-wait', '5', 'repo'), + output_log_level=logging.WARNING, + error_on_warnings=False, ) module.display_archives_info( @@ -131,6 +139,7 @@ def test_display_archives_info_passes_through_arguments_to_borg(argument_name): flexmock(module).should_receive('execute_command').with_args( ('borg', 'info', '--' + argument_name.replace('_', '-'), 'value', 'repo'), output_log_level=logging.WARNING, + error_on_warnings=False, ) module.display_archives_info( diff --git a/tests/unit/borg/test_init.py b/tests/unit/borg/test_init.py index 33c40b33..fffdfd7f 100644 --- a/tests/unit/borg/test_init.py +++ b/tests/unit/borg/test_init.py @@ -24,7 +24,7 @@ def insert_info_command_not_found_mock(): def insert_init_command_mock(init_command, **kwargs): flexmock(module).should_receive('execute_command_without_capture').with_args( - init_command + init_command, error_on_warnings=False ).once() diff --git a/tests/unit/borg/test_list.py b/tests/unit/borg/test_list.py index 2b84d0e4..4e3de334 100644 --- a/tests/unit/borg/test_list.py +++ b/tests/unit/borg/test_list.py @@ -10,7 +10,7 @@ from ..test_verbosity import insert_logging_mock def test_list_archives_calls_borg_with_parameters(): flexmock(module).should_receive('execute_command').with_args( - ('borg', 'list', 'repo'), output_log_level=logging.WARNING + ('borg', 'list', 'repo'), output_log_level=logging.WARNING, error_on_warnings=False ) module.list_archives( @@ -22,7 +22,9 @@ def test_list_archives_calls_borg_with_parameters(): def test_list_archives_with_log_info_calls_borg_with_info_parameter(): flexmock(module).should_receive('execute_command').with_args( - ('borg', 'list', '--info', 'repo'), output_log_level=logging.WARNING + ('borg', 'list', '--info', 'repo'), + output_log_level=logging.WARNING, + error_on_warnings=False, ) insert_logging_mock(logging.INFO) @@ -35,7 +37,7 @@ def test_list_archives_with_log_info_calls_borg_with_info_parameter(): def test_list_archives_with_log_info_and_json_suppresses_most_borg_output(): flexmock(module).should_receive('execute_command').with_args( - ('borg', 'list', '--json', 'repo'), output_log_level=None + ('borg', 'list', '--json', 'repo'), output_log_level=None, error_on_warnings=False ) insert_logging_mock(logging.INFO) @@ -48,7 +50,9 @@ def test_list_archives_with_log_info_and_json_suppresses_most_borg_output(): def test_list_archives_with_log_debug_calls_borg_with_debug_parameter(): flexmock(module).should_receive('execute_command').with_args( - ('borg', 'list', '--debug', '--show-rc', 'repo'), output_log_level=logging.WARNING + ('borg', 'list', '--debug', '--show-rc', 'repo'), + output_log_level=logging.WARNING, + error_on_warnings=False, ) insert_logging_mock(logging.DEBUG) @@ -61,7 +65,7 @@ def test_list_archives_with_log_debug_calls_borg_with_debug_parameter(): def test_list_archives_with_log_debug_and_json_suppresses_most_borg_output(): flexmock(module).should_receive('execute_command').with_args( - ('borg', 'list', '--json', 'repo'), output_log_level=None + ('borg', 'list', '--json', 'repo'), output_log_level=None, error_on_warnings=False ) insert_logging_mock(logging.DEBUG) @@ -75,7 +79,9 @@ def test_list_archives_with_log_debug_and_json_suppresses_most_borg_output(): def test_list_archives_with_lock_wait_calls_borg_with_lock_wait_parameters(): storage_config = {'lock_wait': 5} flexmock(module).should_receive('execute_command').with_args( - ('borg', 'list', '--lock-wait', '5', 'repo'), output_log_level=logging.WARNING + ('borg', 'list', '--lock-wait', '5', 'repo'), + output_log_level=logging.WARNING, + error_on_warnings=False, ) module.list_archives( @@ -88,7 +94,7 @@ def test_list_archives_with_lock_wait_calls_borg_with_lock_wait_parameters(): def test_list_archives_with_archive_calls_borg_with_archive_parameter(): storage_config = {} flexmock(module).should_receive('execute_command').with_args( - ('borg', 'list', 'repo::archive'), output_log_level=logging.WARNING + ('borg', 'list', 'repo::archive'), output_log_level=logging.WARNING, error_on_warnings=False ) module.list_archives( @@ -100,7 +106,7 @@ def test_list_archives_with_archive_calls_borg_with_archive_parameter(): def test_list_archives_with_local_path_calls_borg_via_local_path(): flexmock(module).should_receive('execute_command').with_args( - ('borg1', 'list', 'repo'), output_log_level=logging.WARNING + ('borg1', 'list', 'repo'), output_log_level=logging.WARNING, error_on_warnings=False ) module.list_archives( @@ -113,7 +119,9 @@ def test_list_archives_with_local_path_calls_borg_via_local_path(): def test_list_archives_with_remote_path_calls_borg_with_remote_path_parameters(): flexmock(module).should_receive('execute_command').with_args( - ('borg', 'list', '--remote-path', 'borg1', 'repo'), output_log_level=logging.WARNING + ('borg', 'list', '--remote-path', 'borg1', 'repo'), + output_log_level=logging.WARNING, + error_on_warnings=False, ) module.list_archives( @@ -126,7 +134,9 @@ def test_list_archives_with_remote_path_calls_borg_with_remote_path_parameters() def test_list_archives_with_short_calls_borg_with_short_parameter(): flexmock(module).should_receive('execute_command').with_args( - ('borg', 'list', '--short', 'repo'), output_log_level=logging.WARNING + ('borg', 'list', '--short', 'repo'), + output_log_level=logging.WARNING, + error_on_warnings=False, ).and_return('[]') module.list_archives( @@ -154,6 +164,7 @@ def test_list_archives_passes_through_arguments_to_borg(argument_name): flexmock(module).should_receive('execute_command').with_args( ('borg', 'list', '--' + argument_name.replace('_', '-'), 'value', 'repo'), output_log_level=logging.WARNING, + error_on_warnings=False, ).and_return('[]') module.list_archives( @@ -169,6 +180,7 @@ def test_list_archives_with_successful_calls_borg_to_exclude_checkpoints(): flexmock(module).should_receive('execute_command').with_args( ('borg', 'list', '--glob-archives', module.BORG_EXCLUDE_CHECKPOINTS_GLOB, 'repo'), output_log_level=logging.WARNING, + error_on_warnings=False, ).and_return('[]') module.list_archives( @@ -180,7 +192,7 @@ def test_list_archives_with_successful_calls_borg_to_exclude_checkpoints(): def test_list_archives_with_json_calls_borg_with_json_parameter(): flexmock(module).should_receive('execute_command').with_args( - ('borg', 'list', '--json', 'repo'), output_log_level=None + ('borg', 'list', '--json', 'repo'), output_log_level=None, error_on_warnings=False ).and_return('[]') json_output = module.list_archives( diff --git a/tests/unit/borg/test_mount.py b/tests/unit/borg/test_mount.py index 998dc648..10914063 100644 --- a/tests/unit/borg/test_mount.py +++ b/tests/unit/borg/test_mount.py @@ -8,7 +8,9 @@ from ..test_verbosity import insert_logging_mock def insert_execute_command_mock(command): - flexmock(module).should_receive('execute_command').with_args(command).once() + flexmock(module).should_receive('execute_command').with_args( + command, error_on_warnings=False + ).once() def test_mount_archive_calls_borg_with_required_parameters(): @@ -116,7 +118,7 @@ def test_mount_archive_with_log_debug_calls_borg_with_debug_parameters(): def test_mount_archive_calls_borg_with_foreground_parameter(): flexmock(module).should_receive('execute_command_without_capture').with_args( - ('borg', 'mount', '--foreground', 'repo::archive', '/mnt') + ('borg', 'mount', '--foreground', 'repo::archive', '/mnt'), error_on_warnings=False ).once() module.mount_archive( diff --git a/tests/unit/borg/test_prune.py b/tests/unit/borg/test_prune.py index d05e8c0d..ed1ee674 100644 --- a/tests/unit/borg/test_prune.py +++ b/tests/unit/borg/test_prune.py @@ -10,7 +10,7 @@ from ..test_verbosity import insert_logging_mock def insert_execute_command_mock(prune_command, output_log_level): flexmock(module).should_receive('execute_command').with_args( - prune_command, output_log_level=output_log_level + prune_command, output_log_level=output_log_level, error_on_warnings=False ).once() diff --git a/tests/unit/test_execute.py b/tests/unit/test_execute.py index f29feb57..b6fcb04c 100644 --- a/tests/unit/test_execute.py +++ b/tests/unit/test_execute.py @@ -4,44 +4,28 @@ from flexmock import flexmock from borgmatic import execute as module -def test_exit_code_indicates_error_with_borg_error_is_true(): - assert module.exit_code_indicates_error(('/usr/bin/borg1', 'init'), 2) - - -def test_exit_code_indicates_error_with_borg_warning_is_false(): - assert not module.exit_code_indicates_error(('/usr/bin/borg1', 'init'), 1) - - -def test_exit_code_indicates_error_with_borg_success_is_false(): - assert not module.exit_code_indicates_error(('/usr/bin/borg1', 'init'), 0) - - -def test_exit_code_indicates_error_with_borg_error_and_error_on_warnings_is_true(): - assert module.exit_code_indicates_error(('/usr/bin/borg1', 'init'), 2, error_on_warnings=True) - - -def test_exit_code_indicates_error_with_borg_warning_and_error_on_warnings_is_true(): - assert module.exit_code_indicates_error(('/usr/bin/borg1', 'init'), 1, error_on_warnings=True) - - -def test_exit_code_indicates_error_with_borg_success_and_error_on_warnings_is_false(): - assert not module.exit_code_indicates_error( - ('/usr/bin/borg1', 'init'), 0, error_on_warnings=True +@pytest.mark.parametrize( + 'exit_code,error_on_warnings,expected_result', + ( + (2, True, True), + (2, False, True), + (1, True, True), + (1, False, False), + (0, True, False), + (0, False, False), + ), +) +def test_exit_code_indicates_error_respects_exit_code_and_error_on_warnings( + exit_code, error_on_warnings, expected_result +): + assert ( + module.exit_code_indicates_error( + ('command',), exit_code, error_on_warnings=error_on_warnings + ) + is expected_result ) -def test_exit_code_indicates_error_with_non_borg_error_is_true(): - assert module.exit_code_indicates_error(('/usr/bin/command',), 2) - - -def test_exit_code_indicates_error_with_non_borg_warning_is_true(): - assert module.exit_code_indicates_error(('/usr/bin/command',), 1) - - -def test_exit_code_indicates_error_with_non_borg_success_is_false(): - assert not module.exit_code_indicates_error(('/usr/bin/command',), 0) - - def test_execute_command_calls_full_command(): full_command = ['foo', 'bar'] flexmock(module.os, environ={'a': 'b'})