소스 검색

Fix for "before_backup" hook not triggering an error when the command contains "borg" and has an exit code of 1 (#256).

Dan Helfman 5 년 전
부모
커밋
00f62ca023

+ 2 - 0
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

+ 2 - 2
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)

+ 1 - 1
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]

+ 3 - 1
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,
     )

+ 1 - 1
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)

+ 3 - 1
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,
     )

+ 2 - 2
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)

+ 5 - 1
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,
+    )

+ 9 - 9
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))
 

+ 69 - 19
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(

+ 1 - 1
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()
 
 

+ 19 - 10
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(

+ 1 - 1
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()
 
 

+ 23 - 11
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(

+ 4 - 2
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(

+ 1 - 1
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()
 
 

+ 19 - 35
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'})