receive-pack: convert update hooks to new API

Use the new hook sideband API introduced in the previous commit. The hook API avoids creating a custom struct child_process and other internal hook plumbing (e.g. calling find_hook()) and prepares for the specification of hooks via configs or running parallel hooks. Execution is still sequential through the current hook.[ch] via the run_process_parallel_opts.processes=1 arg. Signed-off-by: Emily Shaffer <emilyshaffer@google.com> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Emily Shaffer committed Dec 26, 2025 at 14:23 UTC 0bbaf3653f54f49ac124c623906983839c38b354
1 file changed +25 -39
builtin/receive-pack.c
+25 -39
@@ -918,6 +918,16 @@ static int feed_receive_hook(void *state_, const char **bufp, size_t *sizep)
918 return 0;
919 }
920
921 +static void hook_output_to_sideband(struct strbuf *output, void *cb_data UNUSED)
922 +{
923 + if (!output)
924 + BUG("output must be non-NULL");
925 +
926 + /* buffer might be empty for keepalives */
927 + if (output->len)
928 + send_sideband(1, 2, output->buf, output->len, use_sideband);
929 +}
930 +
931 static int run_receive_hook(struct command *commands,
932 const char *hook_name,
933 int skip_broken,
@@ -941,29 +951,18 @@ static int run_receive_hook(struct command *commands,
951
952 static int run_update_hook(struct command *cmd)
953 {
944 - struct child_process proc = CHILD_PROCESS_INIT;
945 - int code;
946 - const char *hook_path = find_hook(the_repository, "update");
947 -
948 - if (!hook_path)
949 - return 0;
950 -
951 - strvec_push(&proc.args, hook_path);
952 - strvec_push(&proc.args, cmd->ref_name);
953 - strvec_push(&proc.args, oid_to_hex(&cmd->old_oid));
954 - strvec_push(&proc.args, oid_to_hex(&cmd->new_oid));
954 + struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
955
956 - proc.no_stdin = 1;
957 - proc.stdout_to_stderr = 1;
958 - proc.err = use_sideband ? -1 : 0;
959 - proc.trace2_hook_name = "update";
956 + strvec_pushl(&opt.args,
957 + cmd->ref_name,
958 + oid_to_hex(&cmd->old_oid),
959 + oid_to_hex(&cmd->new_oid),
960 + NULL);
961
961 - code = start_command(&proc);
962 - if (code)
963 - return code;
962 if (use_sideband)
965 - copy_to_sideband(proc.err, -1, NULL);
966 - return finish_command(&proc);
963 + opt.consume_output = hook_output_to_sideband;
964 +
965 + return run_hooks_opt(the_repository, "update", &opt);
966 }
967
968 static struct command *find_command_by_refname(struct command *list,
@@ -1640,33 +1639,20 @@ out:
1639 static void run_update_post_hook(struct command *commands)
1640 {
1641 struct command *cmd;
1643 - struct child_process proc = CHILD_PROCESS_INIT;
1644 - const char *hook;
1645 -
1646 - hook = find_hook(the_repository, "post-update");
1647 - if (!hook)
1648 - return;
1642 + struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
1643
1644 for (cmd = commands; cmd; cmd = cmd->next) {
1645 if (cmd->error_string || cmd->did_not_exist)
1646 continue;
1653 - if (!proc.args.nr)
1654 - strvec_push(&proc.args, hook);
1655 - strvec_push(&proc.args, cmd->ref_name);
1647 + strvec_push(&opt.args, cmd->ref_name);
1648 }
1657 - if (!proc.args.nr)
1649 + if (!opt.args.nr)
1650 return;
1651
1660 - proc.no_stdin = 1;
1661 - proc.stdout_to_stderr = 1;
1662 - proc.err = use_sideband ? -1 : 0;
1663 - proc.trace2_hook_name = "post-update";
1652 + if (use_sideband)
1653 + opt.consume_output = hook_output_to_sideband;
1654
1665 - if (!start_command(&proc)) {
1666 - if (use_sideband)
1667 - copy_to_sideband(proc.err, -1, NULL);
1668 - finish_command(&proc);
1669 - }
1655 + run_hooks_opt(the_repository, "post-update", &opt);
1656 }
1657
1658 static void check_aliased_update_internal(struct command *cmd,