Call Githooks as standalone scripts
This will be officially supported with Git 2.36 (Q2 2022):
git hook run [--ignore-missing] <hook-name> [-- <hook-args>]
See commit 95ba86a, commit 306f445, commit dbb1c61, commit f443246, commit 0c8ac06, commit a755530, commit 1a3017d, commit 72ddf34, commit 67ad630, commit 432a50b, commit 25d4e02, commit 593ffdd, commit bad62a8, commit 96e7225 (22 Dec 2021) by Emily Shaffer (nasamuffin
).
See commit 0d3979c, commit ab81cf2, commit 474c119 (22 Dec 2021) by Ævar Arnfjörð Bjarmason (avar
).
(Merged by Junio C Hamano -- gitster
-- in commit c70bc33, 09 Feb 2022)
hook
: add 'run' subcommand
Signed-off-by: Emily Shaffer
Signed-off-by: Ævar Arnfjörð Bjarmason
Acked-by: Emily Shaffer
In order to enable hooks to be run as an external process, by a standalone Git command, or by tools which wrap Git, provide an external means to run all configured hook commands for a given hook event.
Most of our hooks require more complex functionality than this, but let's start with the bare minimum required to support our simplest hooks.
In terms of implementation the usage_with_options()
and "goto usage" pattern here mirrors that of builtin/{commit-graph,multi-pack-index}.c
.
Some of the implementation here, such as a function being named run_hooks_opt()
when it's tasked with running one hook, to using the run_processes_parallel_tr2()
API to run with jobs=1 is somewhere between a bit odd and and an overkill for the current features of this "hook run
" command and the hook.[ch]
API.
This code will eventually be able to run multiple hooks declared in config in parallel, by starting out with these names and APIs we reduce the later churn of renaming functions, switching from the run_command()
to run_processes_parallel_tr2()
API etc.
git hook
now includes in its man page:
git-hook(1)
NAME
git-hook - Run git hooks
SYNOPSIS
[verse]
'git hook' run <hook-name> [-- <hook-args>]
DESCRIPTION
A command interface to running git hooks (see linkgit:githooks[5]),
for use by other scripted git commands.
SUBCOMMANDS
run
Run the <hook-name>
hook.
Any positional arguments to the hook should be passed after a
mandatory --
(or --end-of-options
).
And:
git hook run
: add an --ignore-missing flag
Signed-off-by: Ævar Arnfjörð Bjarmason
Reviewed-by: Emily Shaffer
For certain one-shot hooks we'd like to optimistically run them, and not complain if they don't exist.
This was already supported by the underlying hook.c
library, but had not been exposed via "git hook
"(man) run".
The command version of this will be used by send-email in a subsequent commit.
git hook
now includes in its man page:
'git hook' run [--ignore-missing] <hook-name> [-- <hook-args>]
git hook
now includes in its man page:
OPTIONS
--ignore-missing
Ignore any missing hook by quietly returning zero.
Used for
tools that want to do a blind one-shot run of a hook that may
or may not be present.
Warning: in Git 2.36 we revamped the way how hooks are invoked.
One change that is end-user visible is that the output of a hook is no longer directly connected to the standard output of "git
" that spawns the hook, which was noticed post release.
This is getting corrected with Git 2.37 (Q3 2022).
See commit a082345, commit fd3aaf5 (07 Jun 2022) by Ævar Arnfjörð Bjarmason (avar
).
(Merged by Junio C Hamano -- gitster
-- in commit 1a7f6be, 13 Jun 2022)
hook API
: fix v2.36.0 regression: hooks should be connected to a TTY
Reported-by: Anthony Sottile
Signed-off-by: Ævar Arnfjörð Bjarmason
Fix a regression reported against f443246 (commit
: convert {pre-commit, 2021-12-22, Git v2.36.0-rc0 -- merge listed in batch #2) (commit: convert {pre-commit,prepare-commit-msg} hook to hook.h
, 2021-12-22): Due to using the run_process_parallel()
API in the earlier 96e7225 ("hook
: add 'run' subcommand", 2021-12-22, Git v2.36.0-rc0 -- merge listed in batch #2) we'd capture the hook's stderr and stdout, and thus lose the connection to the TTY in the case of e.g. the "pre-commit" hook.
As a preceding commit notes GNU parallel's similar --ungroup
option also has it emit output faster.
While we're unlikely to have hooks that emit truly massive amounts of output (or where the performance thereof matters) it's still informative to measure the overhead.
In a similar "seq" test we're now ~30% faster:
$ cat .git/hooks/seq-hook; git hyperfine -L rev origin/master,HEAD~0 -s 'make CFLAGS=-O3' './git hook run seq-hook'
#!/bin/sh
seq 100000000
Benchmark 1: ./git hook run seq-hook' in 'origin/master
Time (mean ± σ): 787.1 ms ± 13.6 ms [User: 701.6 ms, System: 534.4 ms]
Range (min … max): 773.2 ms … 806.3 ms 10 runs
Benchmark 2: ./git hook run seq-hook' in 'HEAD~0
Time (mean ± σ): 603.4 ms ± 1.6 ms [User: 573.1 ms, System: 30.3 ms]
Range (min … max): 601.0 ms … 606.2 ms 10 runs
Summary
'./git hook run seq-hook' in 'HEAD~0' ran
1.30 ± 0.02 times faster than './git hook run seq-hook' in 'origin/master'
Git 2.37.3 (Q3 2022) adds a follow-up fix to a fix for a regression in 2.36.
See commit 99ddc24 (05 Aug 2022) by Ævar Arnfjörð Bjarmason (avar
).
(Merged by Junio C Hamano -- gitster
-- in commit d86ac14, 14 Aug 2022)
hook API
: don't segfault on strbuf_addf()
to NULL "out"
Reported-by: Ilya K
Signed-off-by: Ævar Arnfjörð Bjarmason
Reviewed-by: Emily Shaffer
Reviewed-by: Đoàn Trần Công Danh
Fix a logic error in a082345 ("hook API: fix v2.36.0 regression: hooks should be connected to a TTY", 2022-06-07, Git v2.37.0-rc0 -- merge).
When it started using the "ungroup" API added in fd3aaf5 (run-command
: add an , 2022-06-07, Git v2.37.0-rc0 -- merge) (run-command: add an "ungroup" option to run_process_parallel()
, 2022-06-07) it should have made the same sort of change that fd3aaf5 itself made in "t/helper/test-run-command.c
".
The correct way to emit this "Couldn't start
" output with "ungroup
" would be:
fprintf(stderr, _("Couldn't start hook '%s'\n"), hook_path);
But we should instead remove the emitting of this output.
The "cannot run" output here is emitted by run-command.c
's child_err_spew()
.
So the addition of the "Couldn't start hook
" output here in 96e7225 ("hook
: add 'run' subcommand", 2021-12-22, Git v2.36.0-rc0 -- merge listed in batch #2) was always redundant.
For the pre-commit hook we'll now emit exactly the same output as we did before f443246 (commit
: convert {pre-commit, 2021-12-22, Git v2.36.0-rc0 -- merge listed in batch #2) (commit: convert {pre-commit,prepare-commit-msg} hook to hook.h
, 2021-12-22) (and likewise for others).