mirror of
https://github.com/git/git.git
synced 2026-01-11 13:23:12 +09:00
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>
This commit is contained in:
parent
3e2836a742
commit
7a7717427e
110
refs.c
110
refs.c
@ -2405,68 +2405,72 @@ static int ref_update_reject_duplicates(struct string_list *refnames,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 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;
|
||||||
|
|
||||||
|
if (i >= transaction->nr)
|
||||||
|
return 1; /* No more refs to process */
|
||||||
|
|
||||||
|
update = transaction->updates[i];
|
||||||
|
|
||||||
|
if (update->flags & REF_LOG_ONLY)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
strbuf_reset(buf);
|
||||||
|
|
||||||
|
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_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_addf(buf, "%s\n", update->refname);
|
||||||
|
|
||||||
|
ret = write_in_full(hook_stdin_fd, buf->buf, buf->len);
|
||||||
|
if (ret < 0 && errno != EPIPE)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return 0; /* no more input to feed */
|
||||||
|
}
|
||||||
|
|
||||||
static int run_transaction_hook(struct ref_transaction *transaction,
|
static int run_transaction_hook(struct ref_transaction *transaction,
|
||||||
const char *state)
|
const char *state)
|
||||||
{
|
{
|
||||||
struct child_process proc = CHILD_PROCESS_INIT;
|
struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
|
||||||
struct strbuf buf = STRBUF_INIT;
|
struct transaction_feed_cb_data feed_ctx = { 0 };
|
||||||
const char *hook;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
hook = find_hook(transaction->ref_store->repo, "reference-transaction");
|
strvec_push(&opt.args, state);
|
||||||
if (!hook)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
strvec_pushl(&proc.args, hook, state, NULL);
|
opt.feed_pipe = transaction_hook_feed_stdin;
|
||||||
proc.in = -1;
|
opt.feed_pipe_ctx = transaction;
|
||||||
proc.stdout_to_stderr = 1;
|
opt.feed_pipe_cb_data = &feed_ctx;
|
||||||
proc.trace2_hook_name = "reference-transaction";
|
|
||||||
|
|
||||||
ret = start_command(&proc);
|
strbuf_init(&feed_ctx.buf, 0);
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
sigchain_push(SIGPIPE, SIG_IGN);
|
ret = run_hooks_opt(transaction->ref_store->repo, "reference-transaction", &opt);
|
||||||
|
|
||||||
for (size_t i = 0; i < transaction->nr; i++) {
|
strbuf_release(&feed_ctx.buf);
|
||||||
struct ref_update *update = transaction->updates[i];
|
|
||||||
|
|
||||||
if (update->flags & REF_LOG_ONLY)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
strbuf_reset(&buf);
|
|
||||||
|
|
||||||
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_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_addf(&buf, "%s\n", update->refname);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
close(proc.in);
|
|
||||||
sigchain_pop(SIGPIPE);
|
|
||||||
strbuf_release(&buf);
|
|
||||||
|
|
||||||
ret |= finish_command(&proc);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user