Subject: [PATCH v6 00/11] Convert remaining hooks to hook.h

From: Adrian Ratiu <[email-masked]>
Date: Fri, 26 Dec 2025 14:23:23 +0200

Hello everyone,

This series finishes the hook.[ch] conversion for the remaining hooks in
preparation for adding config-based hooks and enabling parallel hook
execution where possible (that will be a separate series from this one).

v6 is minor refresh for some last nits. Details + range-diff below.

It is based on the latest master branch. There are no conflicts with
next and seen branches, the code is available on GitHub [1] and a
successful CI run [2] is also provided.

1: https://github.com/10ne1/git/tree/dev/aratiu/hooks-conversion-v6
2: https://github.com/10ne1/git/actions/runs/20436908624

Changes in v6:
* Last commit cb state is new allocated on the stack (Patrick)
* Small loop variable and brace fixes (Patrick)

Range-diff v5 -> v6:
 1:  8c16f1bcbf =  1:  8c16f1bcbf run-command: add first helper for pp child states
 2:  5e6e05ba92 =  2:  5e6e05ba92 run-command: add stdin callback for parallelization
 3:  3669acfe6a =  3:  3669acfe6a hook: provide stdin via callback
 4:  bf9d8680e4 =  4:  bf9d8680e4 hook: convert 'post-rewrite' hook in sequencer.c to hook API
 5:  bdcc1cff34 =  5:  bdcc1cff34 transport: convert pre-push to hook API
 6:  9c1d5e8726 =  6:  9c1d5e8726 reference-transaction: use hook API instead of run-command
 7:  0b986bf0fb =  7:  0b986bf0fb hook: allow overriding the ungroup option
 8:  5f07d07acc =  8:  5f07d07acc run-command: allow capturing of collated output
 9:  c4ff1e2270 =  9:  c4ff1e2270 hooks: allow callers to capture output
10:  15c831ca15 = 10:  15c831ca15 receive-pack: convert update hooks to new API
11:  4bd2c2974a ! 11:  432dc14871 receive-pack: convert receive hooks to hook API
    @@ builtin/receive-pack.c: struct receive_hook_feed_state {
     -		finish_async(&muxer);
      
     -	sigchain_pop(SIGPIPE);
    --
    --	return finish_command(&proc);
    --}
     +	state->cmd = cmd;
      
    +-	return finish_command(&proc);
    +-}
    +-
     -static int feed_receive_hook(void *state_, const char **bufp, size_t *sizep)
     -{
     -	struct receive_hook_feed_state *state = state_;
    @@ builtin/receive-pack.c: static int run_receive_hook(struct command *commands,
     -	if (feed_receive_hook(&state, NULL, NULL))
     +	struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
     +	struct command *iter = commands;
    -+	struct receive_hook_feed_state *feed_state;
    ++	struct receive_hook_feed_state feed_state;
     +	int ret;
     +
     +	/* if there are no valid commands, don't invoke the hook at all. */
    @@ builtin/receive-pack.c: static int run_receive_hook(struct command *commands,
     -	return status;
     +
     +	if (push_options) {
    -+		int i;
    -+		for (i = 0; i < push_options->nr; i++)
    ++		for (int i = 0; i < push_options->nr; i++)
     +			strvec_pushf(&opt.env, "GIT_PUSH_OPTION_%d=%s", i,
     +				     push_options->items[i].string);
     +		strvec_pushf(&opt.env, "GIT_PUSH_OPTION_COUNT=%"PRIuMAX"",
     +					     (uintmax_t)push_options->nr);
    -+	} else
    ++	} else {
     +		strvec_push(&opt.env, "GIT_PUSH_OPTION_COUNT");
    ++	}
     +
     +	if (tmp_objdir)
     +		strvec_pushv(&opt.env, tmp_objdir_env(tmp_objdir));
    @@ builtin/receive-pack.c: static int run_receive_hook(struct command *commands,
     +		opt.consume_output = hook_output_to_sideband;
     +
     +	/* set up stdin callback */
    -+	feed_state = xmalloc(sizeof(struct receive_hook_feed_state));
    -+	feed_state->cmd = commands;
    -+	feed_state->skip_broken = skip_broken;
    -+	feed_state->report = NULL;
    -+	strbuf_init(&feed_state->buf, 0);
    -+	opt.feed_pipe_cb_data = feed_state;
    ++	feed_state.cmd = commands;
    ++	feed_state.skip_broken = skip_broken;
    ++	feed_state.report = NULL;
    ++	strbuf_init(&feed_state.buf, 0);
    ++	opt.feed_pipe_cb_data = &feed_state;
     +	opt.feed_pipe = feed_receive_hook_cb;
     +
     +	ret = run_hooks_opt(the_repository, hook_name, &opt);
     +
    -+	strbuf_release(&feed_state->buf);
    -+	FREE_AND_NULL(opt.feed_pipe_cb_data);
    ++	strbuf_release(&feed_state.buf);
     +
     +	return ret;
      }

Adrian Ratiu (3):
  run-command: add first helper for pp child states
  reference-transaction: use hook API instead of run-command
  hook: allow overriding the ungroup option

Emily Shaffer (8):
  run-command: add stdin callback for parallelization
  hook: provide stdin via callback
  hook: convert 'post-rewrite' hook in sequencer.c to hook API
  transport: convert pre-push to hook API
  run-command: allow capturing of collated output
  hooks: allow callers to capture output
  receive-pack: convert update hooks to new API
  receive-pack: convert receive hooks to hook API

 builtin/hook.c              |   6 +
 builtin/receive-pack.c      | 270 +++++++++++++++---------------------
 commit.c                    |   3 +
 hook.c                      |  29 +++-
 hook.h                      |  51 +++++++
 refs.c                      | 100 ++++++-------
 run-command.c               | 142 +++++++++++++++----
 run-command.h               |  38 +++++
 sequencer.c                 |  42 +++---
 t/helper/test-run-command.c |  67 ++++++++-
 t/t0061-run-command.sh      |  38 +++++
 transport.c                 |  89 ++++++------
 12 files changed, 583 insertions(+), 292 deletions(-)

-- 
2.51.2