瀏覽代碼

fix: no error on database backups without source dirs

Divyansh Singh 2 年之前
父節點
當前提交
09183464cd
共有 3 個文件被更改,包括 50 次插入9 次删除
  1. 1 0
      borgmatic/borg/create.py
  2. 23 9
      borgmatic/execute.py
  3. 26 0
      tests/unit/test_execute.py

+ 1 - 0
borgmatic/borg/create.py

@@ -291,6 +291,7 @@ def collect_special_file_paths(
         capture_stderr=True,
         capture_stderr=True,
         working_directory=working_directory,
         working_directory=working_directory,
         extra_environment=borg_environment,
         extra_environment=borg_environment,
+        raise_on_exit_code_one=False,
     )
     )
 
 
     paths = tuple(
     paths = tuple(

+ 23 - 9
borgmatic/execute.py

@@ -213,7 +213,12 @@ def execute_command(
 
 
 
 
 def execute_command_and_capture_output(
 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
     Execute the given command (a sequence of command/argument strings), capturing and returning its
@@ -221,20 +226,29 @@ def execute_command_and_capture_output(
     stdout. If shell is True, execute the command within a shell. If an extra environment dict is
     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
     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.
     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.
 
 
-    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.
     '''
     '''
     log_command(full_command)
     log_command(full_command)
     environment = {**os.environ, **extra_environment} if extra_environment else None
     environment = {**os.environ, **extra_environment} if extra_environment else None
     command = ' '.join(full_command) if shell else full_command
     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:
+        if raise_on_exit_code_one or e.returncode != 1:
+            raise
+        output = e.output
+        logger.warning('Command output: {}'.format(output))
 
 
     return output.decode() if output is not None else None
     return output.decode() if output is not None else None
 
 

+ 26 - 0
tests/unit/test_execute.py

@@ -239,6 +239,32 @@ def test_execute_command_and_capture_output_with_capture_stderr_returns_stderr()
     assert output == expected_output
     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():
 def test_execute_command_and_capture_output_returns_output_with_shell():
     full_command = ['foo', 'bar']
     full_command = ['foo', 'bar']
     expected_output = '[]'
     expected_output = '[]'