mirror of
https://github.com/pre-commit/pre-commit.git
synced 2026-02-17 08:14:42 +04:00
Don't crash when an executable is not found
This commit is contained in:
parent
da7e85c851
commit
5a6b6e81e9
5 changed files with 37 additions and 13 deletions
|
|
@ -12,6 +12,10 @@ from pre_commit import five
|
||||||
printable = frozenset(string.printable)
|
printable = frozenset(string.printable)
|
||||||
|
|
||||||
|
|
||||||
|
class ExecutableNotFoundError(OSError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def parse_bytesio(bytesio):
|
def parse_bytesio(bytesio):
|
||||||
"""Parse the shebang from a file opened for reading binary."""
|
"""Parse the shebang from a file opened for reading binary."""
|
||||||
if bytesio.read(2) != b'#!':
|
if bytesio.read(2) != b'#!':
|
||||||
|
|
@ -70,7 +74,9 @@ def normexe(orig_exe):
|
||||||
if os.sep not in orig_exe:
|
if os.sep not in orig_exe:
|
||||||
exe = find_executable(orig_exe)
|
exe = find_executable(orig_exe)
|
||||||
if exe is None:
|
if exe is None:
|
||||||
raise OSError('Executable {0} not found'.format(orig_exe))
|
raise ExecutableNotFoundError(
|
||||||
|
'Executable `{0}` not found'.format(orig_exe),
|
||||||
|
)
|
||||||
return exe
|
return exe
|
||||||
else:
|
else:
|
||||||
return orig_exe
|
return orig_exe
|
||||||
|
|
|
||||||
|
|
@ -181,23 +181,26 @@ def cmd_output(*cmd, **kwargs):
|
||||||
for key, value in kwargs.pop('env', {}).items()
|
for key, value in kwargs.pop('env', {}).items()
|
||||||
) or None
|
) or None
|
||||||
|
|
||||||
cmd = parse_shebang.normalize_cmd(cmd)
|
try:
|
||||||
|
cmd = parse_shebang.normalize_cmd(cmd)
|
||||||
popen_kwargs.update(kwargs)
|
except parse_shebang.ExecutableNotFoundError as e:
|
||||||
proc = __popen(cmd, **popen_kwargs)
|
returncode, stdout, stderr = (-1, e.args[0].encode('UTF-8'), b'')
|
||||||
stdout, stderr = proc.communicate()
|
else:
|
||||||
if encoding is not None and stdout is not None:
|
popen_kwargs.update(kwargs)
|
||||||
stdout = stdout.decode(encoding)
|
proc = __popen(cmd, **popen_kwargs)
|
||||||
if encoding is not None and stderr is not None:
|
stdout, stderr = proc.communicate()
|
||||||
stderr = stderr.decode(encoding)
|
if encoding is not None and stdout is not None:
|
||||||
returncode = proc.returncode
|
stdout = stdout.decode(encoding)
|
||||||
|
if encoding is not None and stderr is not None:
|
||||||
|
stderr = stderr.decode(encoding)
|
||||||
|
returncode = proc.returncode
|
||||||
|
|
||||||
if retcode is not None and retcode != returncode:
|
if retcode is not None and retcode != returncode:
|
||||||
raise CalledProcessError(
|
raise CalledProcessError(
|
||||||
returncode, cmd, retcode, output=(stdout, stderr),
|
returncode, cmd, retcode, output=(stdout, stderr),
|
||||||
)
|
)
|
||||||
|
|
||||||
return proc.returncode, stdout, stderr
|
return returncode, stdout, stderr
|
||||||
|
|
||||||
|
|
||||||
def rmtree(path):
|
def rmtree(path):
|
||||||
|
|
|
||||||
5
testing/resources/not_found_exe/hooks.yaml
Normal file
5
testing/resources/not_found_exe/hooks.yaml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
- id: not-found-exe
|
||||||
|
name: Not found exe
|
||||||
|
entry: i-dont-exist-lol
|
||||||
|
language: system
|
||||||
|
files: ''
|
||||||
|
|
@ -108,7 +108,7 @@ def test_find_executable_path_ext(in_tmpdir):
|
||||||
def test_normexe_does_not_exist():
|
def test_normexe_does_not_exist():
|
||||||
with pytest.raises(OSError) as excinfo:
|
with pytest.raises(OSError) as excinfo:
|
||||||
parse_shebang.normexe('i-dont-exist-lol')
|
parse_shebang.normexe('i-dont-exist-lol')
|
||||||
assert excinfo.value.args == ('Executable i-dont-exist-lol not found',)
|
assert excinfo.value.args == ('Executable `i-dont-exist-lol` not found',)
|
||||||
|
|
||||||
|
|
||||||
def test_normexe_already_full_path():
|
def test_normexe_already_full_path():
|
||||||
|
|
|
||||||
|
|
@ -164,6 +164,16 @@ def test_system_hook_with_spaces(tempdir_factory, store):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.integration
|
||||||
|
def test_missing_executable(tempdir_factory, store):
|
||||||
|
_test_hook_repo(
|
||||||
|
tempdir_factory, store, 'not_found_exe',
|
||||||
|
'not-found-exe', ['/dev/null'],
|
||||||
|
b'Executable `i-dont-exist-lol` not found',
|
||||||
|
expected_return_code=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.integration
|
@pytest.mark.integration
|
||||||
def test_run_a_script_hook(tempdir_factory, store):
|
def test_run_a_script_hook(tempdir_factory, store):
|
||||||
_test_hook_repo(
|
_test_hook_repo(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue