diff options
author | sroet <sanderroet@hotmail.com> | 2021-09-15 11:55:17 +0200 |
---|---|---|
committer | Sebastian Thiel <sebastian.thiel@icloud.com> | 2021-09-18 09:26:28 +0800 |
commit | aa5076626ca9f2ff1279c6b8e67408be9d0fa690 (patch) | |
tree | ff103d77b0f1aa5a254726a7ff2abfdde0ed6e7f | |
parent | 893ddabd312535bfd906822e42f0223c40655163 (diff) | |
download | gitpython-aa5076626ca9f2ff1279c6b8e67408be9d0fa690.tar.gz |
Add a way to force status codes inside AutoInterrupt._terminate, and let tests use it
-rw-r--r-- | git/cmd.py | 19 | ||||
-rw-r--r-- | test/test_remote.py | 14 |
2 files changed, 22 insertions, 11 deletions
@@ -409,6 +409,10 @@ class Git(LazyMixin): __slots__ = ("proc", "args", "status") + # If this is non-zero it will override any status code during + # _terminate, used to prevent race conditions in testing + _status_code_if_terminate: int = 0 + def __init__(self, proc: Union[None, subprocess.Popen], args: Any) -> None: self.proc = proc self.args = args @@ -427,11 +431,10 @@ class Git(LazyMixin): proc.stdout.close() if proc.stderr: proc.stderr.close() - # did the process finish already so we have a return code ? try: if proc.poll() is not None: - self.status = proc.poll() + self.status = self._status_code_if_terminate or proc.poll() return None except OSError as ex: log.info("Ignored error after process had died: %r", ex) @@ -443,7 +446,9 @@ class Git(LazyMixin): # try to kill it try: proc.terminate() - self.status = proc.wait() # ensure process goes away + status = proc.wait() # ensure process goes away + + self.status = self._status_code_if_terminate or status except OSError as ex: log.info("Ignored error after process had died: %r", ex) except AttributeError: @@ -849,7 +854,7 @@ class Git(LazyMixin): if is_win: cmd_not_found_exception = OSError - if kill_after_timeout: + if kill_after_timeout is not None: raise GitCommandError(redacted_command, '"kill_after_timeout" feature is not supported on Windows.') else: cmd_not_found_exception = FileNotFoundError # NOQA # exists, flake8 unknown @UndefinedVariable @@ -916,7 +921,7 @@ class Git(LazyMixin): return # end - if kill_after_timeout: + if kill_after_timeout is not None: kill_check = threading.Event() watchdog = threading.Timer(kill_after_timeout, _kill_process, args=(proc.pid,)) @@ -927,10 +932,10 @@ class Git(LazyMixin): newline = "\n" if universal_newlines else b"\n" try: if output_stream is None: - if kill_after_timeout: + if kill_after_timeout is not None: watchdog.start() stdout_value, stderr_value = proc.communicate() - if kill_after_timeout: + if kill_after_timeout is not None: watchdog.cancel() if kill_check.is_set(): stderr_value = ('Timeout: the command "%s" did not complete in %d ' diff --git a/test/test_remote.py b/test/test_remote.py index 4c1d02c8..088fdad5 100644 --- a/test/test_remote.py +++ b/test/test_remote.py @@ -658,10 +658,16 @@ class TestRemote(TestBase): class TestTimeouts(TestBase): @with_rw_repo('HEAD', bare=False) def test_timeout_funcs(self, repo): - for function in ["pull"]: # can't get fetch and push to reliably timeout + # Force error code to prevent a race condition if the python thread is + # slow + default = Git.AutoInterrupt._status_code_if_terminate + Git.AutoInterrupt._status_code_if_terminate = -15 + for function in ["pull", "fetch"]: # can't get push to timeout f = getattr(repo.remotes.origin, function) assert f is not None # Make sure these functions exist - _ = f() # Make sure the function runs + _ = f() # Make sure the function runs with pytest.raises(GitCommandError, - match="kill_after_timeout=0.001 s"): - f(kill_after_timeout=0.001) + match="kill_after_timeout=0 s"): + f(kill_after_timeout=0) + + Git.AutoInterrupt._status_code_if_terminate = default |