Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: no error on database backups without source dirs #56

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions borgmatic/borg/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ def collect_special_file_paths(
capture_stderr=True,
working_directory=working_directory,
extra_environment=borg_environment,
raise_on_exit_code_one=False,
witten marked this conversation as resolved.
Show resolved Hide resolved
)

paths = tuple(
Expand Down
32 changes: 23 additions & 9 deletions borgmatic/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,28 +213,42 @@ def execute_command(


def execute_command_and_capture_output(
full_command, capture_stderr=False, shell=False, extra_environment=None, working_directory=None,
full_command,
capture_stderr=False,
shell=False,
extra_environment=None,
working_directory=None,
raise_on_exit_code_one=True,
):
'''
Execute the given command (a sequence of command/argument strings), capturing and returning its
output (stdout). If capture stderr is True, then capture and return stderr in addition to
stdout. 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.
If raise on exit code one is False, then treat exit code 1 as a warning instead of an error.
diivi marked this conversation as resolved.
Show resolved Hide resolved

Raise subprocesses.CalledProcessError if an error occurs while running the command.
Raise subprocesses.CalledProcessError if an error occurs while running the command, or if the
command exits with a non-zero exit code and raise on exit code one is True.
diivi marked this conversation as resolved.
Show resolved Hide resolved
'''
log_command(full_command)
environment = {**os.environ, **extra_environment} if extra_environment else None
command = ' '.join(full_command) if shell else full_command

output = subprocess.check_output(
command,
stderr=subprocess.STDOUT if capture_stderr else None,
shell=shell,
env=environment,
cwd=working_directory,
)
try:
output = subprocess.check_output(
command,
stderr=subprocess.STDOUT if capture_stderr else None,
shell=shell,
env=environment,
cwd=working_directory,
)
logger.warning('Command output: {}'.format(output))
except subprocess.CalledProcessError as e:
witten marked this conversation as resolved.
Show resolved Hide resolved
if raise_on_exit_code_one or e.returncode != 1:
raise
diivi marked this conversation as resolved.
Show resolved Hide resolved
output = e.output
logger.warning('Command output: {}'.format(output))

return output.decode() if output is not None else None

Expand Down
26 changes: 26 additions & 0 deletions tests/unit/test_execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,32 @@ def test_execute_command_and_capture_output_with_capture_stderr_returns_stderr()
assert output == expected_output


def test_execute_command_and_capture_output_returns_output_with_raise_on_exit_code_one_false():
full_command = ['foo', 'bar']
expected_output = '[]'
err_output = b'[]'
flexmock(module.os, environ={'a': 'b'})
flexmock(module.subprocess).should_receive('check_output').with_args(
full_command, stderr=None, shell=False, env=None, cwd=None
).and_raise(subprocess.CalledProcessError(1, full_command, err_output)).once()

output = module.execute_command_and_capture_output(full_command, raise_on_exit_code_one=False)

assert output == expected_output


def test_execute_command_and_capture_output_returns_output_with_raise_on_exit_code_one_false_and_exit_code_not_one():
full_command = ['foo', 'bar']
expected_output = '[]'
flexmock(module.os, environ={'a': 'b'})
flexmock(module.subprocess).should_receive('check_output').with_args(
full_command, stderr=None, shell=False, env=None, cwd=None
).and_raise(subprocess.CalledProcessError(2, full_command, expected_output)).once()

with pytest.raises(subprocess.CalledProcessError):
module.execute_command_and_capture_output(full_command, raise_on_exit_code_one=False)


def test_execute_command_and_capture_output_returns_output_with_shell():
full_command = ['foo', 'bar']
expected_output = '[]'
Expand Down