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?");
61 /* reopen the file for stdin; run_command closes it. */
62 if (hook_cb->options->path_to_stdin) {
64 cp->in = xopen(hook_cb->options->path_to_stdin, O_RDONLY);
68 cp->env = hook_cb->options->env.v;
69 cp->stdout_to_stderr = 1;
70 cp->trace2_hook_name = hook_cb->hook_name;
71 cp->dir = hook_cb->options->dir;
74 strvec_push(&cp->args, run_me->hook_path);
77 * add passed-in argv, without expanding - let the user get back
78 * exactly what they put in
80 strvec_pushv(&cp->args, hook_cb->options->args.v);
82 /* Provide context for errors if necessary */
88 static int notify_start_failure(struct strbuf *out,
92 struct hook_cb_data *hook_cb = pp_cb;
93 struct hook *attempted = pp_task_cp;
98 strbuf_addf(out, _("Couldn't start hook '%s'\n"),
99 attempted->hook_path);
104 static int notify_hook_finished(int result,
109 struct hook_cb_data *hook_cb = pp_cb;
112 hook_cb->rc |= result;
118 int run_found_hooks(const char *hook_name, const char *hook_path,
119 struct run_hooks_opt *options)
121 struct strbuf abs_path = STRBUF_INIT;
122 struct hook my_hook = {
123 .hook_path = hook_path,
125 struct hook_cb_data cb_data = {
127 .hook_name = hook_name,
130 if (options->absolute_path) {
131 strbuf_add_absolute_path(&abs_path, hook_path);
132 my_hook.hook_path = abs_path.buf;
134 cb_data.run_me = &my_hook;
136 if (options->jobs != 1)
137 BUG("we do not handle %d or any other != 1 job number yet", options->jobs);
139 run_processes_parallel_tr2(options->jobs,
141 notify_start_failure,
143 notify_hook_finished,
147 if (options->absolute_path)
148 strbuf_release(&abs_path);
153 int run_hooks(const char *hook_name, struct run_hooks_opt *options)
155 const char *hook_path;
158 BUG("a struct run_hooks_opt must be provided to run_hooks");
160 hook_path = find_hook(hook_name);
162 /* Care about nonexistence? Use run_found_hooks() */
166 ret = run_found_hooks(hook_name, hook_path, options);