Skip to content

Commit

Permalink
Do not treat Borg warnings (exit code 1) as failures (#204).
Browse files Browse the repository at this point in the history
  • Loading branch information
witten committed Aug 3, 2019
1 parent a7cc2ea commit ccbd0b6
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 6 deletions.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
1.3.14
* #204: Do not treat Borg warnings (exit code 1) as failures.
* When validating configuration files, require strings instead of allowing any scalar type.

1.3.13
Expand Down
8 changes: 6 additions & 2 deletions borgmatic/borg/init.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging
import subprocess

from borgmatic.execute import execute_command
from borgmatic.execute import BORG_ERROR_EXIT_CODE, execute_command

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -44,4 +44,8 @@ def initialize_repository(
)

# Don't use execute_command() here because it doesn't support interactive prompts.
subprocess.check_call(init_command)
try:
subprocess.check_call(init_command)
except subprocess.CalledProcessError as error:
if error.returncode >= BORG_ERROR_EXIT_CODE:
raise
3 changes: 2 additions & 1 deletion borgmatic/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@


ERROR_OUTPUT_MAX_LINE_COUNT = 25
BORG_ERROR_EXIT_CODE = 2


def execute_and_log_output(full_command, output_log_level, shell):
Expand All @@ -31,7 +32,7 @@ def execute_and_log_output(full_command, output_log_level, shell):
logger.log(output_log_level, remaining_output)

exit_code = process.poll()
if exit_code != 0:
if exit_code >= BORG_ERROR_EXIT_CODE:
# If an error occurs, include its output in the raised exception so that we don't
# inadvertently hide error output.
if len(last_lines) == ERROR_OUTPUT_MAX_LINE_COUNT:
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from setuptools import find_packages, setup

VERSION = '1.3.13'
VERSION = '1.3.14'


setup(
Expand Down
14 changes: 12 additions & 2 deletions tests/integration/test_execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,16 @@ def test_execute_and_log_output_logs_each_line_separately():
module.execute_and_log_output(['echo', 'there'], output_log_level=logging.INFO, shell=False)


def test_execute_and_log_output_with_borg_warning_does_not_raise():
flexmock(module.logger).should_receive('log')

# Borg's exit code 1 is a warning, not an error.
module.execute_and_log_output(['false'], output_log_level=logging.INFO, shell=False)


def test_execute_and_log_output_includes_borg_error_output_in_exception():
flexmock(module.logger).should_receive('log')

with pytest.raises(subprocess.CalledProcessError) as error:
module.execute_and_log_output(['grep'], output_log_level=logging.INFO, shell=False)

Expand All @@ -25,6 +34,7 @@ def test_execute_and_log_output_includes_borg_error_output_in_exception():

def test_execute_and_log_output_truncates_long_borg_error_output():
flexmock(module).ERROR_OUTPUT_MAX_LINE_COUNT = 0
flexmock(module.logger).should_receive('log')

with pytest.raises(subprocess.CalledProcessError) as error:
module.execute_and_log_output(['grep'], output_log_level=logging.INFO, shell=False)
Expand All @@ -40,7 +50,7 @@ def test_execute_and_log_output_with_no_output_logs_nothing():


def test_execute_and_log_output_with_error_exit_status_raises():
flexmock(module.logger).should_receive('log').never()
flexmock(module.logger).should_receive('log')

with pytest.raises(subprocess.CalledProcessError):
module.execute_and_log_output(['false'], output_log_level=logging.INFO, shell=False)
module.execute_and_log_output(['grep'], output_log_level=logging.INFO, shell=False)
19 changes: 19 additions & 0 deletions tests/unit/borg/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,25 @@ def test_initialize_repository_calls_borg_with_parameters():
module.initialize_repository(repository='repo', encryption_mode='repokey')


def test_initialize_repository_does_not_raise_for_borg_init_warning():
insert_info_command_not_found_mock()
flexmock(module.subprocess).should_receive('check_call').and_raise(
module.subprocess.CalledProcessError(1, 'borg init')
)

module.initialize_repository(repository='repo', encryption_mode='repokey')


def test_initialize_repository_raises_for_borg_init_error():
insert_info_command_not_found_mock()
flexmock(module.subprocess).should_receive('check_call').and_raise(
module.subprocess.CalledProcessError(2, 'borg init')
)

with pytest.raises(subprocess.CalledProcessError):
module.initialize_repository(repository='repo', encryption_mode='repokey')


def test_initialize_repository_skips_initialization_when_repository_already_exists():
insert_info_command_found_mock()
flexmock(module.subprocess).should_receive('check_call').never()
Expand Down

0 comments on commit ccbd0b6

Please sign in to comment.