Skip to content

Commit 33bc620

Browse files
committed
Merge branch 'ab/config-based-hooks-base' into seen
Restructuring of (a subset of) Emily's config-based-hooks series, to demonstrate that a series can be presented as a more logical and focused progression. * ab/config-based-hooks-base: (30 commits) hook-list.h: add a generated list of hooks, like config-list.h hooks: fix a TOCTOU in "did we run a hook?" heuristic receive-pack: convert receive hooks to hook.h post-update: use hook.h library receive-pack: convert 'update' hook to hook.h hooks: allow callers to capture output run-command: allow capturing of collated output reference-transaction: use hook.h to run hooks transport: convert pre-push hook to use config hook: convert 'post-rewrite' hook in sequencer.c to hook.h hook: provide stdin by string_list or callback run-command: add stdin callback for parallelization am: convert 'post-rewrite' hook to hook.h hook: support passing stdin to hooks run-command: allow stdin for run_processes_parallel run-command: remove old run_hook_{le,ve}() hook API receive-pack: convert push-to-checkout hook to hook.h read-cache: convert post-index-change hook to use config commit: use hook.h to execute hooks git-p4: use 'git hook' to run hooks ...
2 parents ba070a3 + d4102be commit 33bc620

39 files changed

+1246
-555
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
/git-grep
7979
/git-hash-object
8080
/git-help
81+
/git-hook
8182
/git-http-backend
8283
/git-http-fetch
8384
/git-http-push
@@ -191,6 +192,7 @@
191192
/gitweb/static/gitweb.min.*
192193
/config-list.h
193194
/command-list.h
195+
/hook-list.h
194196
*.tar.gz
195197
*.dsc
196198
*.deb

Documentation/git-hook.txt

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
git-hook(1)
2+
===========
3+
4+
NAME
5+
----
6+
git-hook - run git hooks
7+
8+
SYNOPSIS
9+
--------
10+
[verse]
11+
'git hook' run [--to-stdin=<path>] [--ignore-missing] <hook-name> [-- <hook-args>]
12+
13+
DESCRIPTION
14+
-----------
15+
16+
This command is an interface to git hooks (see linkgit:githooks[5]).
17+
Currently it only provides a convenience wrapper for running hooks for
18+
use by git itself. In the future it might gain other functionality.
19+
20+
SUBCOMMANDS
21+
-----------
22+
23+
run::
24+
25+
Run the `<hook-name>` hook. Any positional arguments to the
26+
hook should be passed after an optional "--" (or
27+
"--end-of-options"). See "OPTIONS" below for the arguments
28+
this accepts.
29+
30+
OPTIONS
31+
-------
32+
33+
--to-stdin::
34+
For "run"; Specify a file which will be streamed into the
35+
hook's stdin. The hook will receive the entire file from
36+
beginning to EOF.
37+
38+
--ignore-missing::
39+
Ignore any missing hook by quietly returning zero. Used for
40+
tools that want to do a blind one-shot run of a hook that may
41+
or may not be present.
42+
43+
SEE ALSO
44+
--------
45+
linkgit:githooks[5]
46+
47+
GIT
48+
---
49+
Part of the linkgit:git[1] suite

Documentation/githooks.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,10 @@ and "0" meaning they were not.
699699
Only one parameter should be set to "1" when the hook runs. The hook
700700
running passing "1", "1" should not be possible.
701701

702+
SEE ALSO
703+
--------
704+
linkgit:git-hook[1]
705+
702706
GIT
703707
---
704708
Part of the linkgit:git[1] suite

Makefile

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,7 @@ XDIFF_LIB = xdiff/lib.a
830830

831831
GENERATED_H += command-list.h
832832
GENERATED_H += config-list.h
833+
GENERATED_H += hook-list.h
833834

834835
LIB_H := $(sort $(patsubst ./%,%,$(shell git ls-files '*.h' ':!t/' ':!Documentation/' 2>/dev/null || \
835836
$(FIND) . \
@@ -915,6 +916,7 @@ LIB_OBJS += hash-lookup.o
915916
LIB_OBJS += hashmap.o
916917
LIB_OBJS += help.o
917918
LIB_OBJS += hex.o
919+
LIB_OBJS += hook.o
918920
LIB_OBJS += ident.o
919921
LIB_OBJS += json-writer.o
920922
LIB_OBJS += kwset.o
@@ -1116,6 +1118,7 @@ BUILTIN_OBJS += builtin/get-tar-commit-id.o
11161118
BUILTIN_OBJS += builtin/grep.o
11171119
BUILTIN_OBJS += builtin/hash-object.o
11181120
BUILTIN_OBJS += builtin/help.o
1121+
BUILTIN_OBJS += builtin/hook.o
11191122
BUILTIN_OBJS += builtin/index-pack.o
11201123
BUILTIN_OBJS += builtin/init-db.o
11211124
BUILTIN_OBJS += builtin/interpret-trailers.o
@@ -2230,7 +2233,9 @@ git$X: git.o GIT-LDFLAGS $(BUILTIN_OBJS) $(GITLIBS)
22302233

22312234
help.sp help.s help.o: command-list.h
22322235

2233-
builtin/help.sp builtin/help.s builtin/help.o: config-list.h GIT-PREFIX
2236+
hook.sp hook.s hook.o: hook-list.h
2237+
2238+
builtin/help.sp builtin/help.s builtin/help.o: config-list.h hook-list.h GIT-PREFIX
22342239
builtin/help.sp builtin/help.s builtin/help.o: EXTRA_CPPFLAGS = \
22352240
'-DGIT_HTML_PATH="$(htmldir_relative_SQ)"' \
22362241
'-DGIT_MAN_PATH="$(mandir_relative_SQ)"' \
@@ -2263,6 +2268,11 @@ command-list.h: $(wildcard Documentation/git*.txt)
22632268
$(patsubst %,--exclude-program %,$(EXCLUDED_PROGRAMS)) \
22642269
command-list.txt >$@+ && mv $@+ $@
22652270

2271+
hook-list.h: generate-hooklist.sh
2272+
hook-list.h: Documentation/githooks.txt
2273+
$(QUIET_GEN)$(SHELL_PATH) ./generate-hooklist.sh \
2274+
>$@+ && mv $@+ $@
2275+
22662276
SCRIPT_DEFINES = $(SHELL_PATH_SQ):$(DIFF_SQ):$(GIT_VERSION):\
22672277
$(localedir_SQ):$(NO_CURL):$(USE_GETTEXT_SCHEME):$(SANE_TOOL_PATH_SQ):\
22682278
$(gitwebdir_SQ):$(PERL_PATH_SQ):$(SANE_TEXT_GREP):$(PAGER_ENV):\
@@ -2919,7 +2929,7 @@ $(SP_OBJ): %.sp: %.c GIT-CFLAGS FORCE
29192929
.PHONY: sparse $(SP_OBJ)
29202930
sparse: $(SP_OBJ)
29212931

2922-
EXCEPT_HDRS := command-list.h config-list.h unicode-width.h compat/% xdiff/%
2932+
EXCEPT_HDRS := command-list.h config-list.h hook-list.h unicode-width.h compat/% xdiff/%
29232933
ifndef GCRYPT_SHA256
29242934
EXCEPT_HDRS += sha256/gcrypt.h
29252935
endif
@@ -2941,7 +2951,7 @@ hdr-check: $(HCO)
29412951
style:
29422952
git clang-format --style file --diff --extensions c,h
29432953

2944-
check: config-list.h command-list.h
2954+
check: config-list.h command-list.h hook-list.h
29452955
@if sparse; \
29462956
then \
29472957
echo >&2 "Use 'make sparse' instead"; \

builtin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix);
165165
int cmd_grep(int argc, const char **argv, const char *prefix);
166166
int cmd_hash_object(int argc, const char **argv, const char *prefix);
167167
int cmd_help(int argc, const char **argv, const char *prefix);
168+
int cmd_hook(int argc, const char **argv, const char *prefix);
168169
int cmd_index_pack(int argc, const char **argv, const char *prefix);
169170
int cmd_init_db(int argc, const char **argv, const char *prefix);
170171
int cmd_interpret_trailers(int argc, const char **argv, const char *prefix);

builtin/am.c

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "parse-options.h"
1212
#include "dir.h"
1313
#include "run-command.h"
14+
#include "hook.h"
1415
#include "quote.h"
1516
#include "tempfile.h"
1617
#include "lockfile.h"
@@ -444,9 +445,12 @@ static void am_destroy(const struct am_state *state)
444445
static int run_applypatch_msg_hook(struct am_state *state)
445446
{
446447
int ret;
448+
struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
447449

448450
assert(state->msg);
449-
ret = run_hook_le(NULL, "applypatch-msg", am_path(state, "final-commit"), NULL);
451+
strvec_push(&opt.args, am_path(state, "final-commit"));
452+
ret = run_hooks("applypatch-msg", &opt);
453+
run_hooks_opt_clear(&opt);
450454

451455
if (!ret) {
452456
FREE_AND_NULL(state->msg);
@@ -463,23 +467,15 @@ static int run_applypatch_msg_hook(struct am_state *state)
463467
*/
464468
static int run_post_rewrite_hook(const struct am_state *state)
465469
{
466-
struct child_process cp = CHILD_PROCESS_INIT;
467-
const char *hook = find_hook("post-rewrite");
470+
struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
468471
int ret;
469472

470-
if (!hook)
471-
return 0;
472-
473-
strvec_push(&cp.args, hook);
474-
strvec_push(&cp.args, "rebase");
473+
strvec_push(&opt.args, "rebase");
474+
opt.path_to_stdin = am_path(state, "rewritten");
475475

476-
cp.in = xopen(am_path(state, "rewritten"), O_RDONLY);
477-
cp.stdout_to_stderr = 1;
478-
cp.trace2_hook_name = "post-rewrite";
476+
ret = run_hooks("post-rewrite", &opt);
479477

480-
ret = run_command(&cp);
481-
482-
close(cp.in);
478+
run_hooks_opt_clear(&opt);
483479
return ret;
484480
}
485481

@@ -1606,9 +1602,13 @@ static void do_commit(const struct am_state *state)
16061602
struct commit_list *parents = NULL;
16071603
const char *reflog_msg, *author, *committer = NULL;
16081604
struct strbuf sb = STRBUF_INIT;
1605+
struct run_hooks_opt hook_opt_pre = RUN_HOOKS_OPT_INIT;
1606+
struct run_hooks_opt hook_opt_post = RUN_HOOKS_OPT_INIT;
16091607

1610-
if (run_hook_le(NULL, "pre-applypatch", NULL))
1608+
if (run_hooks("pre-applypatch", &hook_opt_pre)) {
1609+
run_hooks_opt_clear(&hook_opt_pre);
16111610
exit(1);
1611+
}
16121612

16131613
if (write_cache_as_tree(&tree, 0, NULL))
16141614
die(_("git write-tree failed to write a tree"));
@@ -1659,8 +1659,10 @@ static void do_commit(const struct am_state *state)
16591659
fclose(fp);
16601660
}
16611661

1662-
run_hook_le(NULL, "post-applypatch", NULL);
1662+
run_hooks("post-applypatch", &hook_opt_post);
16631663

1664+
run_hooks_opt_clear(&hook_opt_pre);
1665+
run_hooks_opt_clear(&hook_opt_post);
16641666
strbuf_release(&sb);
16651667
}
16661668

builtin/bugreport.c

Lines changed: 9 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
#include "strbuf.h"
44
#include "help.h"
55
#include "compat/compiler.h"
6-
#include "run-command.h"
6+
#include "hook.h"
7+
#include "hook-list.h"
78

89

910
static void get_system_info(struct strbuf *sys_info)
@@ -41,49 +42,20 @@ static void get_system_info(struct strbuf *sys_info)
4142

4243
static void get_populated_hooks(struct strbuf *hook_info, int nongit)
4344
{
44-
/*
45-
* NEEDSWORK: Doesn't look like there is a list of all possible hooks;
46-
* so below is a transcription of `git help hooks`. Later, this should
47-
* be replaced with some programmatically generated list (generated from
48-
* doc or else taken from some library which tells us about all the
49-
* hooks)
50-
*/
51-
static const char *hook[] = {
52-
"applypatch-msg",
53-
"pre-applypatch",
54-
"post-applypatch",
55-
"pre-commit",
56-
"pre-merge-commit",
57-
"prepare-commit-msg",
58-
"commit-msg",
59-
"post-commit",
60-
"pre-rebase",
61-
"post-checkout",
62-
"post-merge",
63-
"pre-push",
64-
"pre-receive",
65-
"update",
66-
"post-receive",
67-
"post-update",
68-
"push-to-checkout",
69-
"pre-auto-gc",
70-
"post-rewrite",
71-
"sendemail-validate",
72-
"fsmonitor-watchman",
73-
"p4-pre-submit",
74-
"post-index-change",
75-
};
76-
int i;
45+
const char **p;
7746

7847
if (nongit) {
7948
strbuf_addstr(hook_info,
8049
_("not run from a git repository - no hooks to show\n"));
8150
return;
8251
}
8352

84-
for (i = 0; i < ARRAY_SIZE(hook); i++)
85-
if (find_hook(hook[i]))
86-
strbuf_addf(hook_info, "%s\n", hook[i]);
53+
for (p = hook_name_list; *p; p++) {
54+
const char *hook = *p;
55+
56+
if (hook_exists(hook))
57+
strbuf_addf(hook_info, "%s\n", hook);
58+
}
8759
}
8860

8961
static const char * const bugreport_usage[] = {

builtin/checkout.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "config.h"
1010
#include "diff.h"
1111
#include "dir.h"
12+
#include "hook.h"
1213
#include "ll-merge.h"
1314
#include "lockfile.h"
1415
#include "merge-recursive.h"
@@ -106,13 +107,19 @@ struct branch_info {
106107
static int post_checkout_hook(struct commit *old_commit, struct commit *new_commit,
107108
int changed)
108109
{
109-
return run_hook_le(NULL, "post-checkout",
110-
oid_to_hex(old_commit ? &old_commit->object.oid : null_oid()),
111-
oid_to_hex(new_commit ? &new_commit->object.oid : null_oid()),
112-
changed ? "1" : "0", NULL);
110+
struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
111+
int rc;
112+
113113
/* "new_commit" can be NULL when checking out from the index before
114114
a commit exists. */
115-
115+
strvec_pushl(&opt.args,
116+
oid_to_hex(old_commit ? &old_commit->object.oid : null_oid()),
117+
oid_to_hex(new_commit ? &new_commit->object.oid : null_oid()),
118+
changed ? "1" : "0",
119+
NULL);
120+
rc = run_hooks("post-checkout", &opt);
121+
run_hooks_opt_clear(&opt);
122+
return rc;
116123
}
117124

118125
static int update_some(const struct object_id *oid, struct strbuf *base,

builtin/clone.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "connected.h"
3333
#include "packfile.h"
3434
#include "list-objects-filter-options.h"
35+
#include "hook.h"
3536

3637
/*
3738
* Overall FIXMEs:
@@ -775,6 +776,7 @@ static int checkout(int submodule_progress)
775776
struct tree *tree;
776777
struct tree_desc t;
777778
int err = 0;
779+
struct run_hooks_opt hook_opt = RUN_HOOKS_OPT_INIT;
778780

779781
if (option_no_checkout)
780782
return 0;
@@ -820,8 +822,9 @@ static int checkout(int submodule_progress)
820822
if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
821823
die(_("unable to write new index file"));
822824

823-
err |= run_hook_le(NULL, "post-checkout", oid_to_hex(null_oid()),
824-
oid_to_hex(&oid), "1", NULL);
825+
strvec_pushl(&hook_opt.args, oid_to_hex(null_oid()), oid_to_hex(&oid), "1", NULL);
826+
err |= run_hooks("post-checkout", &hook_opt);
827+
run_hooks_opt_clear(&hook_opt);
825828

826829
if (!err && (option_recurse_submodules.nr > 0)) {
827830
struct strvec args = STRVEC_INIT;

0 commit comments

Comments
 (0)