aboutsummaryrefslogtreecommitdiff
path: root/hook.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2026-02-04 09:22:21 -0800
committerJunio C Hamano <gitster@pobox.com>2026-02-04 09:22:21 -0800
commit468b5f75c3e277d84e2d739e642fbad27ccdb666 (patch)
treebc9d89124c0313cf4023ca2ed8af47fbb0acb4de /hook.c
parentb2826b52eb7caff9f4ed6e85ec45e338bf02ad09 (diff)
parentb5e9ad508c2f340bd2d2547d7370ae7ac6a0d65d (diff)
downloadgit-468b5f75c3e277d84e2d739e642fbad27ccdb666.tar.xz
Merge branch 'ar/run-command-hook-take-2' into ar/config-hooks
* ar/run-command-hook-take-2: 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;