support 'diff-only' hooks by passing diff via stdin (#1279)

This commit is contained in:
Ofer Koren 2020-01-12 21:18:56 +02:00
parent b2faf339ce
commit 4b7f832122
4 changed files with 20 additions and 5 deletions

View file

@ -67,6 +67,7 @@ MANIFEST_HOOK_DICT = cfgv.Map(
cfgv.Optional('args', cfgv.check_array(cfgv.check_string), []),
cfgv.Optional('always_run', cfgv.check_bool, False),
cfgv.Optional('pass_filenames', cfgv.check_bool, True),
cfgv.Optional('pass_diff', cfgv.check_bool, False),
cfgv.Optional('description', cfgv.check_string, ''),
cfgv.Optional('language_version', cfgv.check_string, C.DEFAULT),
cfgv.Optional('log_file', cfgv.check_string, ''),

View file

@ -139,10 +139,14 @@ def _run_single_hook(
diff_cmd = ('git', 'diff', '--no-ext-diff')
diff_before = cmd_output_b(*diff_cmd, retcode=None)
if not hook.pass_filenames:
filenames = ()
if hook.pass_diff:
inputs = (diff_before[1],)
elif hook.pass_filenames:
inputs = filenames
else:
inputs = ()
time_before = time.time()
retcode, out = hook.run(filenames, use_color)
retcode, out = hook.run(inputs, use_color)
duration = round(time.time() - time_before, 2) or 0
diff_after = cmd_output_b(*diff_cmd, retcode=None)

View file

@ -106,4 +106,8 @@ def run_xargs(
# but do it deterministically in case a hook cares about ordering.
file_args = _shuffled(file_args)
kwargs['target_concurrency'] = target_concurrency(hook)
if hook.pass_diff:
input_data, = file_args
kwargs['input_data'] = input_data
file_args = ()
return xargs(cmd, file_args, **kwargs)

View file

@ -138,6 +138,7 @@ def cmd_output_b(
**kwargs: Any,
) -> Tuple[int, bytes, Optional[bytes]]:
retcode = kwargs.pop('retcode', 0)
input_data = kwargs.pop('input_data', None)
cmd, kwargs = _cmd_kwargs(*cmd, **kwargs)
try:
@ -146,7 +147,7 @@ def cmd_output_b(
returncode, stdout_b, stderr_b = e.to_output()
else:
proc = subprocess.Popen(cmd, **kwargs)
stdout_b, stderr_b = proc.communicate()
stdout_b, stderr_b = proc.communicate(input_data)
returncode = proc.returncode
if retcode is not None and retcode != returncode:
@ -207,6 +208,7 @@ if os.name != 'nt': # pragma: windows no cover
) -> Tuple[int, bytes, Optional[bytes]]:
assert kwargs.pop('retcode') is None
assert kwargs['stderr'] == subprocess.STDOUT, kwargs['stderr']
input_data = kwargs.pop('input_data', None)
cmd, kwargs = _cmd_kwargs(*cmd, **kwargs)
try:
@ -216,8 +218,12 @@ if os.name != 'nt': # pragma: windows no cover
with open(os.devnull) as devnull, Pty() as pty:
assert pty.r is not None
kwargs.update({'stdin': devnull, 'stdout': pty.w, 'stderr': pty.w})
stdin = subprocess.PIPE if input_data else devnull
kwargs.update({'stdin': stdin, 'stdout': pty.w, 'stderr': pty.w})
proc = subprocess.Popen(cmd, **kwargs)
if input_data:
proc.stdin.write(input_data)
proc.stdin.close()
pty.close_w()
buf = b''