Repository: pre-commit/pre-commit

Issue:
include version information in error log
would be useful to include things like:

- pre-commit version
- sys.version
- sys.executable


Discussion:

Resolving patch:
diff --git a/pre_commit/error_handler.py b/pre_commit/error_handler.py
--- a/pre_commit/error_handler.py
+++ b/pre_commit/error_handler.py
@@ -4,10 +4,12 @@
 
 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)
 
 


Test patch:
diff --git a/tests/error_handler_test.py b/tests/error_handler_test.py
--- 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
--- 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):