aboutsummaryrefslogtreecommitdiff
path: root/hook.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2026-03-09 14:36:55 -0700
committerJunio C Hamano <gitster@pobox.com>2026-03-09 14:36:55 -0700
commit5c56c725f104ce278fe1ec0ea0fce0ccfb245aea (patch)
tree148a090bbe73c7bfb8b823bcc642e01c40929250 /hook.c
parent4aa72ea1f64e8ddcd1865c76b24591c0916c0b5d (diff)
parent005f3fbe07a20dd5f7dea57f6f46cd797387e56a (diff)
downloadgit-5c56c725f104ce278fe1ec0ea0fce0ccfb245aea.tar.xz
Merge branch 'ar/run-command-hook-take-2'
Use the hook API to replace ad-hoc invocation of hook scripts via the run_command() API. * ar/run-command-hook-take-2: builtin/receive-pack: avoid spinning no-op sideband async threads receive-pack: convert receive hooks to hook API receive-pack: convert update hooks to new API run-command: poll child input in addition to output hook: add jobs option reference-transaction: use hook API instead of run-command transport: convert pre-push to hook API hook: allow separate std[out|err] streams hook: convert 'post-rewrite' hook in sequencer.c to hook API hook: provide stdin via callback run-command: add stdin callback for parallelization run-command: add helper for pp child states t1800: add hook output stream tests
Diffstat (limited to 'hook.c')
-rw-r--r--hook.c32
1 files changed, 28 insertions, 4 deletions
diff --git a/hook.c b/hook.c
index b3de1048bf..cde7198412 100644
--- a/hook.c
+++ b/hook.c
@@ -55,7 +55,7 @@ int hook_exists(struct repository *r, const char *name)
static int pick_next_hook(struct child_process *cp,
struct strbuf *out UNUSED,
void *pp_cb,
- void **pp_task_cb UNUSED)
+ void **pp_task_cb)
{
struct hook_cb_data *hook_cb = pp_cb;
const char *hook_path = hook_cb->hook_path;
@@ -65,12 +65,23 @@ static int pick_next_hook(struct child_process *cp,
cp->no_stdin = 1;
strvec_pushv(&cp->env, hook_cb->options->env.v);
+
+ if (hook_cb->options->path_to_stdin && hook_cb->options->feed_pipe)
+ BUG("options path_to_stdin and feed_pipe are mutually exclusive");
+
/* reopen the file for stdin; run_command closes it. */
if (hook_cb->options->path_to_stdin) {
cp->no_stdin = 0;
cp->in = xopen(hook_cb->options->path_to_stdin, O_RDONLY);
}
- cp->stdout_to_stderr = 1;
+
+ if (hook_cb->options->feed_pipe) {
+ cp->no_stdin = 0;
+ /* start_command() will allocate a pipe / stdin fd for us */
+ cp->in = -1;
+ }
+
+ cp->stdout_to_stderr = hook_cb->options->stdout_to_stderr;
cp->trace2_hook_name = hook_cb->hook_name;
cp->dir = hook_cb->options->dir;
@@ -78,6 +89,12 @@ static int pick_next_hook(struct child_process *cp,
strvec_pushv(&cp->args, hook_cb->options->args.v);
/*
+ * Provide per-hook internal state via task_cb for easy access, so
+ * hook callbacks don't have to go through hook_cb->options.
+ */
+ *pp_task_cb = hook_cb->options->feed_pipe_cb_data;
+
+ /*
* This pick_next_hook() will be called again, we're only
* running one hook, so indicate that no more work will be
* done.
@@ -135,11 +152,12 @@ int run_hooks_opt(struct repository *r, const char *hook_name,
.tr2_category = "hook",
.tr2_label = hook_name,
- .processes = 1,
- .ungroup = 1,
+ .processes = options->jobs,
+ .ungroup = options->jobs == 1,
.get_next_task = pick_next_hook,
.start_failure = notify_start_failure,
+ .feed_pipe = options->feed_pipe,
.task_finished = notify_hook_finished,
.data = &cb_data,
@@ -148,6 +166,12 @@ int run_hooks_opt(struct repository *r, const char *hook_name,
if (!options)
BUG("a struct run_hooks_opt must be provided to run_hooks");
+ if (options->path_to_stdin && options->feed_pipe)
+ BUG("options path_to_stdin and feed_pipe are mutually exclusive");
+
+ if (!options->jobs)
+ BUG("run_hooks_opt must be called with options.jobs >= 1");
+
if (options->invoked_hook)
*options->invoked_hook = 0;