3 #include "run-command.h"
5 const char *find_hook(const char *name)
7 static struct strbuf path = STRBUF_INIT;
10 strbuf_git_path(&path, "hooks/%s", name);
11 if (access(path.buf, X_OK) < 0) {
14 #ifdef STRIP_EXTENSION
15 strbuf_addstr(&path, STRIP_EXTENSION);
16 if (access(path.buf, X_OK) >= 0)
22 if (err == EACCES && advice_ignored_hook) {
23 static struct string_list advise_given = STRING_LIST_INIT_DUP;
25 if (!string_list_lookup(&advise_given, name)) {
26 string_list_insert(&advise_given, name);
27 advise(_("The '%s' hook was ignored because "
28 "it's not set as executable.\n"
29 "You can disable this warning with "
30 "`git config advice.ignoredHook false`."),
39 int hook_exists(const char *name)
41 return !!find_hook(name);
44 void run_hooks_opt_clear(struct run_hooks_opt *o)
46 strvec_clear(&o->env);
47 strvec_clear(&o->args);
50 static int pick_next_hook(struct child_process *cp,
55 struct hook_cb_data *hook_cb = pp_cb;
56 struct hook *run_me = hook_cb->run_me;
59 BUG("did we not return 1 in notify_hook_finished?");
62 cp->env = hook_cb->options->env.v;
63 cp->stdout_to_stderr = 1;
64 cp->trace2_hook_name = hook_cb->hook_name;
65 cp->dir = hook_cb->options->dir;
68 strvec_push(&cp->args, run_me->hook_path);
71 * add passed-in argv, without expanding - let the user get back
72 * exactly what they put in
74 strvec_pushv(&cp->args, hook_cb->options->args.v);
76 /* Provide context for errors if necessary */
82 static int notify_start_failure(struct strbuf *out,
86 struct hook_cb_data *hook_cb = pp_cb;
87 struct hook *attempted = pp_task_cp;
92 strbuf_addf(out, _("Couldn't start hook '%s'\n"),
93 attempted->hook_path);
98 static int notify_hook_finished(int result,
103 struct hook_cb_data *hook_cb = pp_cb;
106 hook_cb->rc |= result;
112 int run_found_hooks(const char *hook_name, const char *hook_path,
113 struct run_hooks_opt *options)
115 struct strbuf abs_path = STRBUF_INIT;
116 struct hook my_hook = {
117 .hook_path = hook_path,
119 struct hook_cb_data cb_data = {
121 .hook_name = hook_name,
124 if (options->absolute_path) {
125 strbuf_add_absolute_path(&abs_path, hook_path);
126 my_hook.hook_path = abs_path.buf;
128 cb_data.run_me = &my_hook;
130 if (options->jobs != 1)
131 BUG("we do not handle %d or any other != 1 job number yet", options->jobs);
133 run_processes_parallel_tr2(options->jobs,
135 notify_start_failure,
136 notify_hook_finished,
140 if (options->absolute_path)
141 strbuf_release(&abs_path);
146 int run_hooks(const char *hook_name, struct run_hooks_opt *options)
148 const char *hook_path;
151 BUG("a struct run_hooks_opt must be provided to run_hooks");
153 hook_path = find_hook(hook_name);
155 /* Care about nonexistence? Use run_found_hooks() */
159 ret = run_found_hooks(hook_name, hook_path, options);