Merge pull request #509 from pawamoy/patch-1
Fix parsing of git output with unusual characters
diff --git a/pre_commit_hooks/check_executables_have_shebangs.py b/pre_commit_hooks/check_executables_have_shebangs.py
index 1c50ea0..a02d2a9 100644
--- a/pre_commit_hooks/check_executables_have_shebangs.py
+++ b/pre_commit_hooks/check_executables_have_shebangs.py
@@ -12,6 +12,14 @@
EXECUTABLE_VALUES = frozenset(('1', '3', '5', '7'))
+def zsplit(s: str) -> List[str]:
+ s = s.strip('\0')
+ if s:
+ return s.split('\0')
+ else:
+ return []
+
+
def check_executables(paths: List[str]) -> int:
if sys.platform == 'win32': # pragma: win32 cover
return _check_git_filemode(paths)
@@ -26,9 +34,9 @@
def _check_git_filemode(paths: Sequence[str]) -> int:
- outs = cmd_output('git', 'ls-files', '--stage', '--', *paths)
+ outs = cmd_output('git', 'ls-files', '-z', '--stage', '--', *paths)
seen: Set[str] = set()
- for out in outs.splitlines():
+ for out in zsplit(outs):
metadata, path = out.split('\t')
tagmode = metadata.split(' ', 1)[0]
diff --git a/tests/check_executables_have_shebangs_test.py b/tests/check_executables_have_shebangs_test.py
index 5895a2a..7046081 100644
--- a/tests/check_executables_have_shebangs_test.py
+++ b/tests/check_executables_have_shebangs_test.py
@@ -73,6 +73,21 @@
assert check_executables_have_shebangs._check_git_filemode(files) == 0
+def test_check_git_filemode_passing_unusual_characters(tmpdir):
+ with tmpdir.as_cwd():
+ cmd_output('git', 'init', '.')
+
+ f = tmpdir.join('mañana.txt')
+ f.write('#!/usr/bin/env bash')
+ f_path = str(f)
+ cmd_output('chmod', '+x', f_path)
+ cmd_output('git', 'add', f_path)
+ cmd_output('git', 'update-index', '--chmod=+x', f_path)
+
+ files = (f_path,)
+ assert check_executables_have_shebangs._check_git_filemode(files) == 0
+
+
def test_check_git_filemode_failing(tmpdir):
with tmpdir.as_cwd():
cmd_output('git', 'init', '.')
@@ -87,6 +102,16 @@
assert check_executables_have_shebangs._check_git_filemode(files) == 1
+@pytest.mark.parametrize('out', ('\0f1\0f2\0', '\0f1\0f2', 'f1\0f2\0'))
+def test_check_zsplits_correctly(out):
+ assert check_executables_have_shebangs.zsplit(out) == ['f1', 'f2']
+
+
+@pytest.mark.parametrize('out', ('\0\0', '\0', ''))
+def test_check_zsplit_returns_empty(out):
+ assert check_executables_have_shebangs.zsplit(out) == []
+
+
@pytest.mark.parametrize(
('content', 'mode', 'expected'),
(