Merge pull request #1601 from int3l/distinct_exit_codes

Distinct exit codes for the various error cases
This commit is contained in:
Anthony Sottile 2020-10-28 11:59:22 -07:00 committed by GitHub
commit a0c0870b87
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 12 deletions

View file

@ -12,7 +12,12 @@ from pre_commit.store import Store
from pre_commit.util import force_bytes from pre_commit.util import force_bytes
def _log_and_exit(msg: str, exc: BaseException, formatted: str) -> None: def _log_and_exit(
msg: str,
ret_code: int,
exc: BaseException,
formatted: str,
) -> None:
error_msg = f'{msg}: {type(exc).__name__}: '.encode() + force_bytes(exc) error_msg = f'{msg}: {type(exc).__name__}: '.encode() + force_bytes(exc)
output.write_line_b(error_msg) output.write_line_b(error_msg)
@ -51,7 +56,7 @@ def _log_and_exit(msg: str, exc: BaseException, formatted: str) -> None:
_log_line('```') _log_line('```')
_log_line(formatted.rstrip()) _log_line(formatted.rstrip())
_log_line('```') _log_line('```')
raise SystemExit(1) raise SystemExit(ret_code)
@contextlib.contextmanager @contextlib.contextmanager
@ -60,9 +65,9 @@ def error_handler() -> Generator[None, None, None]:
yield yield
except (Exception, KeyboardInterrupt) as e: except (Exception, KeyboardInterrupt) as e:
if isinstance(e, FatalError): if isinstance(e, FatalError):
msg = 'An error has occurred' msg, ret_code = 'An error has occurred', 1
elif isinstance(e, KeyboardInterrupt): elif isinstance(e, KeyboardInterrupt):
msg = 'Interrupted (^C)' msg, ret_code = 'Interrupted (^C)', 130
else: else:
msg = 'An unexpected error has occurred' msg, ret_code = 'An unexpected error has occurred', 3
_log_and_exit(msg, e, traceback.format_exc()) _log_and_exit(msg, ret_code, e, traceback.format_exc())

View file

@ -33,6 +33,7 @@ def test_error_handler_fatal_error(mocked_log_and_exit):
mocked_log_and_exit.assert_called_once_with( mocked_log_and_exit.assert_called_once_with(
'An error has occurred', 'An error has occurred',
1,
exc, exc,
# Tested below # Tested below
mock.ANY, mock.ANY,
@ -47,7 +48,7 @@ def test_error_handler_fatal_error(mocked_log_and_exit):
r' raise exc\n' r' raise exc\n'
r'(pre_commit\.errors\.)?FatalError: just a test\n', r'(pre_commit\.errors\.)?FatalError: just a test\n',
) )
pattern.assert_matches(mocked_log_and_exit.call_args[0][2]) pattern.assert_matches(mocked_log_and_exit.call_args[0][3])
def test_error_handler_uncaught_error(mocked_log_and_exit): def test_error_handler_uncaught_error(mocked_log_and_exit):
@ -57,6 +58,7 @@ def test_error_handler_uncaught_error(mocked_log_and_exit):
mocked_log_and_exit.assert_called_once_with( mocked_log_and_exit.assert_called_once_with(
'An unexpected error has occurred', 'An unexpected error has occurred',
3,
exc, exc,
# Tested below # Tested below
mock.ANY, mock.ANY,
@ -70,7 +72,7 @@ def test_error_handler_uncaught_error(mocked_log_and_exit):
r' raise exc\n' r' raise exc\n'
r'ValueError: another test\n', r'ValueError: another test\n',
) )
pattern.assert_matches(mocked_log_and_exit.call_args[0][2]) pattern.assert_matches(mocked_log_and_exit.call_args[0][3])
def test_error_handler_keyboardinterrupt(mocked_log_and_exit): def test_error_handler_keyboardinterrupt(mocked_log_and_exit):
@ -80,6 +82,7 @@ def test_error_handler_keyboardinterrupt(mocked_log_and_exit):
mocked_log_and_exit.assert_called_once_with( mocked_log_and_exit.assert_called_once_with(
'Interrupted (^C)', 'Interrupted (^C)',
130,
exc, exc,
# Tested below # Tested below
mock.ANY, mock.ANY,
@ -93,7 +96,7 @@ def test_error_handler_keyboardinterrupt(mocked_log_and_exit):
r' raise exc\n' r' raise exc\n'
r'KeyboardInterrupt\n', r'KeyboardInterrupt\n',
) )
pattern.assert_matches(mocked_log_and_exit.call_args[0][2]) pattern.assert_matches(mocked_log_and_exit.call_args[0][3])
def test_log_and_exit(cap_out, mock_store_dir): def test_log_and_exit(cap_out, mock_store_dir):
@ -103,8 +106,9 @@ def test_log_and_exit(cap_out, mock_store_dir):
'pre_commit.errors.FatalError: hai\n' 'pre_commit.errors.FatalError: hai\n'
) )
with pytest.raises(SystemExit): with pytest.raises(SystemExit) as excinfo:
error_handler._log_and_exit('msg', FatalError('hai'), tb) error_handler._log_and_exit('msg', 1, FatalError('hai'), tb)
assert excinfo.value.code == 1
printed = cap_out.get() printed = cap_out.get()
log_file = os.path.join(mock_store_dir, 'pre-commit.log') log_file = os.path.join(mock_store_dir, 'pre-commit.log')
@ -170,7 +174,7 @@ def test_error_handler_no_tty(tempdir_factory):
'from pre_commit.error_handler import error_handler\n' 'from pre_commit.error_handler import error_handler\n'
'with error_handler():\n' 'with error_handler():\n'
' raise ValueError("\\u2603")\n', ' raise ValueError("\\u2603")\n',
retcode=1, retcode=3,
tempdir_factory=tempdir_factory, tempdir_factory=tempdir_factory,
pre_commit_home=pre_commit_home, pre_commit_home=pre_commit_home,
) )