reference-transaction: use hook API instead of run-command
Convert the reference-transaction hook to the new hook API, so it doesn't need to set up a struct child_process, call find_hook or toggle the pipe signals. The stdin feed callback is processing one ref update per call. I haven't noticed any performance degradation due to this, however we can batch as many we want in each call, to ensure a good pipe throughtput (i.e. the child does not wait after stdin). Helped-by: Emily Shaffer <nasamuffin@google.com> 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>
Adrian Ratiu committed
Jan 28, 2026 at 23:39 UTC
b7b2157d0d23f6ed98da6fce548d614c5198713d
1 file changed
+52
-50
refs.c
+52
-50
@@ -15,7 +15,6 @@
15
#include "iterator.h"
16
#include "refs.h"
17
#include "refs/refs-internal.h"
18
-#include "run-command.h"
18
#include "hook.h"
19
#include "object-name.h"
20
#include "odb.h"
@@ -26,7 +25,6 @@
25
#include "strvec.h"
26
#include "repo-settings.h"
27
#include "setup.h"
29
-#include "sigchain.h"
28
#include "date.h"
29
#include "commit.h"
30
#include "wildmatch.h"
@@ -2422,68 +2420,72 @@ static int ref_update_reject_duplicates(struct string_list *refnames,
2420
return 0;
2421
}
2422
2425
-static int run_transaction_hook(struct ref_transaction *transaction,
2426
- const char *state)
2423
+struct transaction_feed_cb_data {
2424
+ size_t index;
2425
+ struct strbuf buf;
2426
+};
2427
+
2428
+static int transaction_hook_feed_stdin(int hook_stdin_fd, void *pp_cb, void *pp_task_cb)
2429
{
2428
- struct child_process proc = CHILD_PROCESS_INIT;
2429
- struct strbuf buf = STRBUF_INIT;
2430
- const char *hook;
2431
- int ret = 0;
2430
+ struct hook_cb_data *hook_cb = pp_cb;
2431
+ struct ref_transaction *transaction = hook_cb->options->feed_pipe_ctx;
2432
+ struct transaction_feed_cb_data *feed_cb_data = pp_task_cb;
2433
+ struct strbuf *buf = &feed_cb_data->buf;
2434
+ struct ref_update *update;
2435
+ size_t i = feed_cb_data->index++;
2436
+ int ret;
2437
2433
- hook = find_hook(transaction->ref_store->repo, "reference-transaction");
2434
- if (!hook)
2435
- return ret;
2438
+ if (i >= transaction->nr)
2439
+ return 1; /* No more refs to process */
2440
2437
- strvec_pushl(&proc.args, hook, state, NULL);
2438
- proc.in = -1;
2439
- proc.stdout_to_stderr = 1;
2440
- proc.trace2_hook_name = "reference-transaction";
2441
+ update = transaction->updates[i];
2442
2442
- ret = start_command(&proc);
2443
- if (ret)
2444
- return ret;
2443
+ if (update->flags & REF_LOG_ONLY)
2444
+ return 0;
2445
2446
- sigchain_push(SIGPIPE, SIG_IGN);
2446
+ strbuf_reset(buf);
2447
2448
- for (size_t i = 0; i < transaction->nr; i++) {
2449
- struct ref_update *update = transaction->updates[i];
2448
+ if (!(update->flags & REF_HAVE_OLD))
2449
+ strbuf_addf(buf, "%s ", oid_to_hex(null_oid(the_hash_algo)));
2450
+ else if (update->old_target)
2451
+ strbuf_addf(buf, "ref:%s ", update->old_target);
2452
+ else
2453
+ strbuf_addf(buf, "%s ", oid_to_hex(&update->old_oid));
2454
2451
- if (update->flags & REF_LOG_ONLY)
2452
- continue;
2455
+ if (!(update->flags & REF_HAVE_NEW))
2456
+ strbuf_addf(buf, "%s ", oid_to_hex(null_oid(the_hash_algo)));
2457
+ else if (update->new_target)
2458
+ strbuf_addf(buf, "ref:%s ", update->new_target);
2459
+ else
2460
+ strbuf_addf(buf, "%s ", oid_to_hex(&update->new_oid));
2461
2454
- strbuf_reset(&buf);
2462
+ strbuf_addf(buf, "%s\n", update->refname);
2463
2456
- if (!(update->flags & REF_HAVE_OLD))
2457
- strbuf_addf(&buf, "%s ", oid_to_hex(null_oid(the_hash_algo)));
2458
- else if (update->old_target)
2459
- strbuf_addf(&buf, "ref:%s ", update->old_target);
2460
- else
2461
- strbuf_addf(&buf, "%s ", oid_to_hex(&update->old_oid));
2464
+ ret = write_in_full(hook_stdin_fd, buf->buf, buf->len);
2465
+ if (ret < 0 && errno != EPIPE)
2466
+ return ret;
2467
2463
- if (!(update->flags & REF_HAVE_NEW))
2464
- strbuf_addf(&buf, "%s ", oid_to_hex(null_oid(the_hash_algo)));
2465
- else if (update->new_target)
2466
- strbuf_addf(&buf, "ref:%s ", update->new_target);
2467
- else
2468
- strbuf_addf(&buf, "%s ", oid_to_hex(&update->new_oid));
2468
+ return 0; /* no more input to feed */
2469
+}
2470
+
2471
+static int run_transaction_hook(struct ref_transaction *transaction,
2472
+ const char *state)
2473
+{
2474
+ struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
2475
+ struct transaction_feed_cb_data feed_ctx = { 0 };
2476
+ int ret = 0;
2477
2470
- strbuf_addf(&buf, "%s\n", update->refname);
2478
+ strvec_push(&opt.args, state);
2479
2472
- if (write_in_full(proc.in, buf.buf, buf.len) < 0) {
2473
- if (errno != EPIPE) {
2474
- /* Don't leak errno outside this API */
2475
- errno = 0;
2476
- ret = -1;
2477
- }
2478
- break;
2479
- }
2480
- }
2480
+ opt.feed_pipe = transaction_hook_feed_stdin;
2481
+ opt.feed_pipe_ctx = transaction;
2482
+ opt.feed_pipe_cb_data = &feed_ctx;
2483
2482
- close(proc.in);
2483
- sigchain_pop(SIGPIPE);
2484
- strbuf_release(&buf);
2484
+ strbuf_init(&feed_ctx.buf, 0);
2485
+
2486
+ ret = run_hooks_opt(transaction->ref_store->repo, "reference-transaction", &opt);
2487
2486
- ret |= finish_command(&proc);
2488
+ strbuf_release(&feed_ctx.buf);
2489
return ret;
2490
}
2491