aboutsummaryrefslogtreecommitdiff
path: root/refs.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 /refs.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 'refs.c')
-rw-r--r--refs.c102
1 files changed, 52 insertions, 50 deletions
diff --git a/refs.c b/refs.c
index 627b7f8698..1e2ac90018 100644
--- a/refs.c
+++ b/refs.c
@@ -15,7 +15,6 @@
#include "iterator.h"
#include "refs.h"
#include "refs/refs-internal.h"
-#include "run-command.h"
#include "hook.h"
#include "object-name.h"
#include "odb.h"
@@ -26,7 +25,6 @@
#include "strvec.h"
#include "repo-settings.h"
#include "setup.h"
-#include "sigchain.h"
#include "date.h"
#include "commit.h"
#include "wildmatch.h"
@@ -2465,68 +2463,72 @@ static int ref_update_reject_duplicates(struct string_list *refnames,
return 0;
}
-static int run_transaction_hook(struct ref_transaction *transaction,
- const char *state)
+struct transaction_feed_cb_data {
+ size_t index;
+ struct strbuf buf;
+};
+
+static int transaction_hook_feed_stdin(int hook_stdin_fd, void *pp_cb, void *pp_task_cb)
{
- struct child_process proc = CHILD_PROCESS_INIT;
- struct strbuf buf = STRBUF_INIT;
- const char *hook;
- int ret = 0;
+ struct hook_cb_data *hook_cb = pp_cb;
+ struct ref_transaction *transaction = hook_cb->options->feed_pipe_ctx;
+ struct transaction_feed_cb_data *feed_cb_data = pp_task_cb;
+ struct strbuf *buf = &feed_cb_data->buf;
+ struct ref_update *update;
+ size_t i = feed_cb_data->index++;
+ int ret;
- hook = find_hook(transaction->ref_store->repo, "reference-transaction");
- if (!hook)
- return ret;
+ if (i >= transaction->nr)
+ return 1; /* No more refs to process */
- strvec_pushl(&proc.args, hook, state, NULL);
- proc.in = -1;
- proc.stdout_to_stderr = 1;
- proc.trace2_hook_name = "reference-transaction";
+ update = transaction->updates[i];
- ret = start_command(&proc);
- if (ret)
- return ret;
+ if (update->flags & REF_LOG_ONLY)
+ return 0;
- sigchain_push(SIGPIPE, SIG_IGN);
+ strbuf_reset(buf);
- for (size_t i = 0; i < transaction->nr; i++) {
- struct ref_update *update = transaction->updates[i];
+ if (!(update->flags & REF_HAVE_OLD))
+ strbuf_addf(buf, "%s ", oid_to_hex(null_oid(the_hash_algo)));
+ else if (update->old_target)
+ strbuf_addf(buf, "ref:%s ", update->old_target);
+ else
+ strbuf_addf(buf, "%s ", oid_to_hex(&update->old_oid));
- if (update->flags & REF_LOG_ONLY)
- continue;
+ if (!(update->flags & REF_HAVE_NEW))
+ strbuf_addf(buf, "%s ", oid_to_hex(null_oid(the_hash_algo)));
+ else if (update->new_target)
+ strbuf_addf(buf, "ref:%s ", update->new_target);
+ else
+ strbuf_addf(buf, "%s ", oid_to_hex(&update->new_oid));
- strbuf_reset(&buf);
+ strbuf_addf(buf, "%s\n", update->refname);
- if (!(update->flags & REF_HAVE_OLD))
- strbuf_addf(&buf, "%s ", oid_to_hex(null_oid(the_hash_algo)));
- else if (update->old_target)
- strbuf_addf(&buf, "ref:%s ", update->old_target);
- else
- strbuf_addf(&buf, "%s ", oid_to_hex(&update->old_oid));
+ ret = write_in_full(hook_stdin_fd, buf->buf, buf->len);
+ if (ret < 0 && errno != EPIPE)
+ return ret;
- if (!(update->flags & REF_HAVE_NEW))
- strbuf_addf(&buf, "%s ", oid_to_hex(null_oid(the_hash_algo)));
- else if (update->new_target)
- strbuf_addf(&buf, "ref:%s ", update->new_target);
- else
- strbuf_addf(&buf, "%s ", oid_to_hex(&update->new_oid));
+ return 0; /* no more input to feed */
+}
+
+static int run_transaction_hook(struct ref_transaction *transaction,
+ const char *state)
+{
+ struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
+ struct transaction_feed_cb_data feed_ctx = { 0 };
+ int ret = 0;
- strbuf_addf(&buf, "%s\n", update->refname);
+ strvec_push(&opt.args, state);
- if (write_in_full(proc.in, buf.buf, buf.len) < 0) {
- if (errno != EPIPE) {
- /* Don't leak errno outside this API */
- errno = 0;
- ret = -1;
- }
- break;
- }
- }
+ opt.feed_pipe = transaction_hook_feed_stdin;
+ opt.feed_pipe_ctx = transaction;
+ opt.feed_pipe_cb_data = &feed_ctx;
- close(proc.in);
- sigchain_pop(SIGPIPE);
- strbuf_release(&buf);
+ strbuf_init(&feed_ctx.buf, 0);
+
+ ret = run_hooks_opt(transaction->ref_store->repo, "reference-transaction", &opt);
- ret |= finish_command(&proc);
+ strbuf_release(&feed_ctx.buf);
return ret;
}