Add fail-fast argument for run command

This commit is contained in:
JulianMaurin 2025-08-25 23:20:07 +02:00 committed by anthony sottile
parent e70b313c80
commit c78f248c60
5 changed files with 22 additions and 1 deletions

View file

@ -106,6 +106,7 @@ def _ns(
hook=None, hook=None,
verbose=False, verbose=False,
show_diff_on_failure=False, show_diff_on_failure=False,
fail_fast=False,
) )

View file

@ -298,7 +298,8 @@ def _run_hooks(
verbose=args.verbose, use_color=args.color, verbose=args.verbose, use_color=args.color,
) )
retval |= current_retval retval |= current_retval
if current_retval and (config['fail_fast'] or hook.fail_fast): fail_fast = (config['fail_fast'] or hook.fail_fast or args.fail_fast)
if current_retval and fail_fast:
break break
if retval and args.show_diff_on_failure and prior_diff: if retval and args.show_diff_on_failure and prior_diff:
if args.all_files: if args.all_files:

View file

@ -76,6 +76,10 @@ def _add_run_options(parser: argparse.ArgumentParser) -> None:
'--show-diff-on-failure', action='store_true', '--show-diff-on-failure', action='store_true',
help='When hooks fail, run `git diff` directly afterward.', help='When hooks fail, run `git diff` directly afterward.',
) )
parser.add_argument(
'--fail-fast', action='store_true',
help='Stop after the first failing hook.',
)
parser.add_argument( parser.add_argument(
'--hook-stage', '--hook-stage',
choices=clientlib.STAGES, choices=clientlib.STAGES,

View file

@ -40,6 +40,7 @@ def run_opts(
color=False, color=False,
verbose=False, verbose=False,
hook=None, hook=None,
fail_fast=False,
remote_branch='', remote_branch='',
local_branch='', local_branch='',
from_ref='', from_ref='',
@ -65,6 +66,7 @@ def run_opts(
color=color, color=color,
verbose=verbose, verbose=verbose,
hook=hook, hook=hook,
fail_fast=fail_fast,
remote_branch=remote_branch, remote_branch=remote_branch,
local_branch=local_branch, local_branch=local_branch,
from_ref=from_ref, from_ref=from_ref,

View file

@ -1104,6 +1104,19 @@ def test_fail_fast_not_prev_failures(cap_out, store, repo_with_failing_hook):
assert printed.count(b'run me!') == 1 assert printed.count(b'run me!') == 1
def test_fail_fast_run_arg(cap_out, store, repo_with_failing_hook):
with modify_config() as config:
# More than one hook to demonstrate early exit
config['repos'][0]['hooks'] *= 2
stage_a_file()
ret, printed = _do_run(
cap_out, store, repo_with_failing_hook, run_opts(fail_fast=True),
)
# it should have only run one hook due to the CLI flag
assert printed.count(b'Failing hook') == 1
def test_classifier_removes_dne(): def test_classifier_removes_dne():
classifier = Classifier(('this_file_does_not_exist',)) classifier = Classifier(('this_file_does_not_exist',))
assert classifier.filenames == [] assert classifier.filenames == []