From b05cc4077e621cec637b22d6ad2b80ee84749f97 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Thu, 18 Aug 2016 07:25:55 -0700 Subject: [PATCH] Fix staged-files-only with a non-utf8-trailing-whitespace diff. Resolves #397 --- pre_commit/staged_files_only.py | 4 ++-- tests/staged_files_only_test.py | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/pre_commit/staged_files_only.py b/pre_commit/staged_files_only.py index a2978b99..c8ee9c29 100644 --- a/pre_commit/staged_files_only.py +++ b/pre_commit/staged_files_only.py @@ -45,7 +45,7 @@ def staged_files_only(cmd_runner): finally: # Try to apply the patch we saved try: - cmd_runner.run(['git', 'apply', patch_filename]) + cmd_runner.run(('git', 'apply', patch_filename), encoding=None) except CalledProcessError: logger.warning( 'Stashed changes conflicted with hook auto-fixes... ' @@ -55,7 +55,7 @@ def staged_files_only(cmd_runner): # by hooks. # Roll back the changes made by hooks. cmd_runner.run(['git', 'checkout', '--', '.']) - cmd_runner.run(['git', 'apply', patch_filename]) + cmd_runner.run(('git', 'apply', patch_filename), encoding=None) logger.info('Restored changes from {0}.'.format(patch_filename)) else: # There weren't any staged files so we don't need to do anything diff --git a/tests/staged_files_only_test.py b/tests/staged_files_only_test.py index 00f4cca9..993d33d5 100644 --- a/tests/staged_files_only_test.py +++ b/tests/staged_files_only_test.py @@ -280,3 +280,28 @@ def test_stage_non_utf8_changes(foo_staged, cmd_runner): with staged_files_only(cmd_runner): _test_foo_state(foo_staged) _test_foo_state(foo_staged, contents, 'AM', encoding='latin-1') + + +def test_non_utf8_conflicting_diff(foo_staged, cmd_runner): + """Regression test for #397""" + # The trailing whitespace is important here, this triggers git to produce + # an error message which looks like: + # + # ...patch1471530032:14: trailing whitespace. + # [[unprintable character]][[space character]] + # error: patch failed: foo:1 + # error: foo: patch does not apply + # + # Previously, the error message (though discarded immediately) was being + # decoded with the UTF-8 codec (causing a crash) + contents = 'รบ \n' + with io.open('foo', 'w', encoding='latin-1') as foo_file: + foo_file.write(contents) + + _test_foo_state(foo_staged, contents, 'AM', encoding='latin-1') + with staged_files_only(cmd_runner): + _test_foo_state(foo_staged) + # Create a conflicting diff that will need to be rolled back + with io.open('foo', 'w') as foo_file: + foo_file.write('') + _test_foo_state(foo_staged, contents, 'AM', encoding='latin-1')