diff --git a/commitizen/cmd.py b/commitizen/cmd.py index fe70da9c9..4a2cd9735 100644 --- a/commitizen/cmd.py +++ b/commitizen/cmd.py @@ -36,6 +36,15 @@ def _try_decode(bytes_: bytes) -> str: def run(cmd: str, env: Mapping[str, str] | None = None) -> Command: + """Run a command in a subprocess and capture stdout and stderr + + Args: + cmd: The command to run + env: Extra environment variables to define in the subprocess. Defaults to None. + + Returns: + Command: _description_ + """ if env is not None: env = {**os.environ, **env} process = subprocess.Popen( @@ -55,3 +64,18 @@ def run(cmd: str, env: Mapping[str, str] | None = None) -> Command: stderr, return_code, ) + + +def run_interactive(cmd: str, env: Mapping[str, str] | None = None) -> int: + """Run a command in a subprocess without redirecting stdin, stdout, or stderr + + Args: + cmd: The command to run + env: Extra environment variables to define in the subprocess. Defaults to None. + + Returns: + subprocess returncode + """ + if env is not None: + env = {**os.environ, **env} + return subprocess.run(cmd, shell=True, env=env).returncode diff --git a/commitizen/hooks.py b/commitizen/hooks.py index 10560d5ea..cf9fe01d2 100644 --- a/commitizen/hooks.py +++ b/commitizen/hooks.py @@ -17,14 +17,9 @@ def run(hooks: str | list[str], _env_prefix: str = "CZ_", **env: object) -> None for hook in hooks: out.info(f"Running hook '{hook}'") - c = cmd.run(hook, env=_format_env(_env_prefix, env)) + return_code = cmd.run_interactive(hook, env=_format_env(_env_prefix, env)) - if c.out: - out.write(c.out) - if c.err: - out.error(c.err) - - if c.return_code != 0: + if return_code != 0: raise RunHookError(f"Running hook '{hook}' failed") diff --git a/tests/test_bump_hooks.py b/tests/test_bump_hooks.py index 739d1ce6a..79fe88ddc 100644 --- a/tests/test_bump_hooks.py +++ b/tests/test_bump_hooks.py @@ -12,8 +12,8 @@ def test_run(mocker: MockFixture): bump_hooks = ["pre_bump_hook", "pre_bump_hook_1"] cmd_run_mock = mocker.Mock() - cmd_run_mock.return_value.return_code = 0 - mocker.patch.object(cmd, "run", cmd_run_mock) + cmd_run_mock.return_value = 0 + mocker.patch.object(cmd, "run_interactive", cmd_run_mock) hooks.run(bump_hooks) @@ -29,8 +29,8 @@ def test_run_error(mocker: MockFixture): bump_hooks = ["pre_bump_hook", "pre_bump_hook_1"] cmd_run_mock = mocker.Mock() - cmd_run_mock.return_value.return_code = 1 - mocker.patch.object(cmd, "run", cmd_run_mock) + cmd_run_mock.return_value = 1 + mocker.patch.object(cmd, "run_interactive", cmd_run_mock) with pytest.raises(RunHookError): hooks.run(bump_hooks)