diff --git a/pre_commit/error_handler.py b/pre_commit/error_handler.py index 946f134c..5b09a017 100644 --- a/pre_commit/error_handler.py +++ b/pre_commit/error_handler.py @@ -4,10 +4,12 @@ from __future__ import unicode_literals import contextlib import os.path +import sys import traceback import six +import pre_commit.constants as C from pre_commit import five from pre_commit import output from pre_commit.store import Store @@ -34,9 +36,36 @@ def _log_and_exit(msg, exc, formatted): store = Store() log_path = os.path.join(store.directory, 'pre-commit.log') output.write_line('Check the log at {}'.format(log_path)) + with open(log_path, 'wb') as log: + output.write_line( + '### version information\n```', stream=log, + ) + output.write_line( + 'pre-commit.version: {}'.format(C.VERSION), stream=log, + ) + output.write_line( + 'sys.version:\n{}'.format( + '\n'.join( + [ + ' {}'.format(line) + for line in sys.version.splitlines() + ], + ), + ), + stream=log, + ) + output.write_line( + 'sys.executable: {}'.format(sys.executable), stream=log, + ) + output.write_line('os.name: {}'.format(os.name), stream=log) + output.write_line( + 'sys.platform: {}\n```'.format(sys.platform), stream=log, + ) + output.write_line('### error information\n```', stream=log) output.write(error_msg, stream=log) output.write_line(formatted, stream=log) + output.write('\n```\n', stream=log) raise SystemExit(1) diff --git a/tests/error_handler_test.py b/tests/error_handler_test.py index 1b222f90..e94b3206 100644 --- a/tests/error_handler_test.py +++ b/tests/error_handler_test.py @@ -105,16 +105,29 @@ def test_log_and_exit(cap_out, mock_store_dir): printed = cap_out.get() log_file = os.path.join(mock_store_dir, 'pre-commit.log') assert printed == ( - 'msg: FatalError: hai\n' - 'Check the log at {}\n'.format(log_file) + 'msg: FatalError: hai\n' 'Check the log at {}\n'.format(log_file) ) assert os.path.exists(log_file) with io.open(log_file) as f: - assert f.read() == ( - 'msg: FatalError: hai\n' - "I'm a stacktrace\n" + logged = f.read() + expected = ( + r'^### version information\n' + r'```\n' + r'pre-commit.version: \d+\.\d+\.\d+\n' + r'sys.version:\n( .*\n)*' + r'sys.executable: .*\n' + r'os.name: .*\n' + r'sys.platform: .*\n' + r'```\n' + r'### error information\n' + r'```\n' + r'msg: FatalError: hai\n' + r"I'm a stacktrace\n" + r'\n' + r'```\n' ) + assert re.match(expected, logged) def test_error_handler_non_ascii_exception(mock_store_dir): @@ -126,7 +139,8 @@ def test_error_handler_non_ascii_exception(mock_store_dir): def test_error_handler_no_tty(tempdir_factory): pre_commit_home = tempdir_factory.get() output = cmd_output_mocked_pre_commit_home( - sys.executable, '-c', + sys.executable, + '-c', 'from __future__ import unicode_literals\n' 'from pre_commit.error_handler import error_handler\n' 'with error_handler():\n' @@ -136,7 +150,8 @@ def test_error_handler_no_tty(tempdir_factory): pre_commit_home=pre_commit_home, ) log_file = os.path.join(pre_commit_home, 'pre-commit.log') - assert output[1].replace('\r', '') == ( - 'An unexpected error has occurred: ValueError: ☃\n' - 'Check the log at {}\n'.format(log_file) + output_lines = output[1].replace('\r', '').splitlines() + assert ( + output_lines[-2] == 'An unexpected error has occurred: ValueError: ☃' ) + assert output_lines[-1] == 'Check the log at {}'.format(log_file) diff --git a/tests/main_test.py b/tests/main_test.py index 75fd5600..aad9c4b9 100644 --- a/tests/main_test.py +++ b/tests/main_test.py @@ -164,11 +164,13 @@ def test_expected_fatal_error_no_git_repo(in_tmpdir, cap_out, mock_store_dir): with pytest.raises(SystemExit): main.main([]) log_file = os.path.join(mock_store_dir, 'pre-commit.log') - assert cap_out.get() == ( + cap_out_lines = cap_out.get().splitlines() + assert ( + cap_out_lines[-2] == 'An error has occurred: FatalError: git failed. ' - 'Is it installed, and are you in a Git repository directory?\n' - 'Check the log at {}\n'.format(log_file) + 'Is it installed, and are you in a Git repository directory?' ) + assert cap_out_lines[-1] == 'Check the log at {}'.format(log_file) def test_warning_on_tags_only(mock_commands, cap_out, mock_store_dir):