Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/hook.c
diff options
context:
space:
mode:
Diffstat (limited to 'hook.c')
-rw-r--r--hook.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/hook.c b/hook.c
index 55e1145a4b..a0917cf877 100644
--- a/hook.c
+++ b/hook.c
@@ -1,6 +1,7 @@
#include "cache.h"
#include "hook.h"
#include "run-command.h"
+#include "config.h"
const char *find_hook(const char *name)
{
@@ -40,3 +41,104 @@ int hook_exists(const char *name)
{
return !!find_hook(name);
}
+
+static int pick_next_hook(struct child_process *cp,
+ struct strbuf *out,
+ void *pp_cb,
+ void **pp_task_cb)
+{
+ struct hook_cb_data *hook_cb = pp_cb;
+ const char *hook_path = hook_cb->hook_path;
+
+ if (!hook_path)
+ return 0;
+
+ cp->no_stdin = 1;
+ strvec_pushv(&cp->env_array, hook_cb->options->env.v);
+ cp->stdout_to_stderr = 1;
+ cp->trace2_hook_name = hook_cb->hook_name;
+
+ strvec_push(&cp->args, hook_path);
+ strvec_pushv(&cp->args, hook_cb->options->args.v);
+
+ /* Provide context for errors if necessary */
+ *pp_task_cb = (char *)hook_path;
+
+ /*
+ * This pick_next_hook() will be called again, we're only
+ * running one hook, so indicate that no more work will be
+ * done.
+ */
+ hook_cb->hook_path = NULL;
+
+ return 1;
+}
+
+static int notify_start_failure(struct strbuf *out,
+ void *pp_cb,
+ void *pp_task_cp)
+{
+ struct hook_cb_data *hook_cb = pp_cb;
+ const char *hook_path = pp_task_cp;
+
+ hook_cb->rc |= 1;
+
+ strbuf_addf(out, _("Couldn't start hook '%s'\n"),
+ hook_path);
+
+ return 1;
+}
+
+static int notify_hook_finished(int result,
+ struct strbuf *out,
+ void *pp_cb,
+ void *pp_task_cb)
+{
+ struct hook_cb_data *hook_cb = pp_cb;
+
+ hook_cb->rc |= result;
+
+ return 0;
+}
+
+static void run_hooks_opt_clear(struct run_hooks_opt *options)
+{
+ strvec_clear(&options->env);
+ strvec_clear(&options->args);
+}
+
+int run_hooks_opt(const char *hook_name, struct run_hooks_opt *options)
+{
+ struct hook_cb_data cb_data = {
+ .rc = 0,
+ .hook_name = hook_name,
+ .options = options,
+ };
+ const char *const hook_path = find_hook(hook_name);
+ int jobs = 1;
+ int ret = 0;
+
+ if (!options)
+ BUG("a struct run_hooks_opt must be provided to run_hooks");
+
+ if (!hook_path && !options->error_if_missing)
+ goto cleanup;
+
+ if (!hook_path) {
+ ret = error("cannot find a hook named %s", hook_name);
+ goto cleanup;
+ }
+
+ cb_data.hook_path = hook_path;
+ run_processes_parallel_tr2(jobs,
+ pick_next_hook,
+ notify_start_failure,
+ notify_hook_finished,
+ &cb_data,
+ "hook",
+ hook_name);
+ ret = cb_data.rc;
+cleanup:
+ run_hooks_opt_clear(options);
+ return ret;
+}