Skip to content

Commit 2faf37f

Browse files
nasamuffingitster
authored andcommitted
receive-pack: convert receive hooks to hook.h
Signed-off-by: Emily Shaffer <[email protected]> Signed-off-by: Ævar Arnfjörð Bjarmason <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ce76c3b commit 2faf37f

File tree

1 file changed

+90
-107
lines changed

1 file changed

+90
-107
lines changed

builtin/receive-pack.c

Lines changed: 90 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -748,7 +748,7 @@ static int check_cert_push_options(const struct string_list *push_options)
748748
return retval;
749749
}
750750

751-
static void prepare_push_cert_sha1(struct child_process *proc)
751+
static void prepare_push_cert_sha1(struct run_hooks_opt *opt)
752752
{
753753
static int already_done;
754754

@@ -772,110 +772,42 @@ static void prepare_push_cert_sha1(struct child_process *proc)
772772
nonce_status = check_nonce(push_cert.buf, bogs);
773773
}
774774
if (!is_null_oid(&push_cert_oid)) {
775-
strvec_pushf(&proc->env_array, "GIT_PUSH_CERT=%s",
775+
strvec_pushf(&opt->env, "GIT_PUSH_CERT=%s",
776776
oid_to_hex(&push_cert_oid));
777-
strvec_pushf(&proc->env_array, "GIT_PUSH_CERT_SIGNER=%s",
777+
strvec_pushf(&opt->env, "GIT_PUSH_CERT_SIGNER=%s",
778778
sigcheck.signer ? sigcheck.signer : "");
779-
strvec_pushf(&proc->env_array, "GIT_PUSH_CERT_KEY=%s",
779+
strvec_pushf(&opt->env, "GIT_PUSH_CERT_KEY=%s",
780780
sigcheck.key ? sigcheck.key : "");
781-
strvec_pushf(&proc->env_array, "GIT_PUSH_CERT_STATUS=%c",
781+
strvec_pushf(&opt->env, "GIT_PUSH_CERT_STATUS=%c",
782782
sigcheck.result);
783783
if (push_cert_nonce) {
784-
strvec_pushf(&proc->env_array,
784+
strvec_pushf(&opt->env,
785785
"GIT_PUSH_CERT_NONCE=%s",
786786
push_cert_nonce);
787-
strvec_pushf(&proc->env_array,
787+
strvec_pushf(&opt->env,
788788
"GIT_PUSH_CERT_NONCE_STATUS=%s",
789789
nonce_status);
790790
if (nonce_status == NONCE_SLOP)
791-
strvec_pushf(&proc->env_array,
791+
strvec_pushf(&opt->env,
792792
"GIT_PUSH_CERT_NONCE_SLOP=%ld",
793793
nonce_stamp_slop);
794794
}
795795
}
796796
}
797797

798+
struct receive_hook_feed_context {
799+
struct command *cmd;
800+
int skip_broken;
801+
};
802+
798803
struct receive_hook_feed_state {
799804
struct command *cmd;
800805
struct ref_push_report *report;
801806
int skip_broken;
802807
struct strbuf buf;
803-
const struct string_list *push_options;
804808
};
805809

806-
typedef int (*feed_fn)(void *, const char **, size_t *);
807-
static int run_and_feed_hook(const char *hook_name, feed_fn feed,
808-
struct receive_hook_feed_state *feed_state)
809-
{
810-
struct child_process proc = CHILD_PROCESS_INIT;
811-
struct async muxer;
812-
const char *argv[2];
813-
int code;
814-
815-
argv[0] = find_hook(hook_name);
816-
if (!argv[0])
817-
return 0;
818-
819-
argv[1] = NULL;
820-
821-
proc.argv = argv;
822-
proc.in = -1;
823-
proc.stdout_to_stderr = 1;
824-
proc.trace2_hook_name = hook_name;
825-
826-
if (feed_state->push_options) {
827-
int i;
828-
for (i = 0; i < feed_state->push_options->nr; i++)
829-
strvec_pushf(&proc.env_array,
830-
"GIT_PUSH_OPTION_%d=%s", i,
831-
feed_state->push_options->items[i].string);
832-
strvec_pushf(&proc.env_array, "GIT_PUSH_OPTION_COUNT=%d",
833-
feed_state->push_options->nr);
834-
} else
835-
strvec_pushf(&proc.env_array, "GIT_PUSH_OPTION_COUNT");
836-
837-
if (tmp_objdir)
838-
strvec_pushv(&proc.env_array, tmp_objdir_env(tmp_objdir));
839-
840-
if (use_sideband) {
841-
memset(&muxer, 0, sizeof(muxer));
842-
muxer.proc = copy_to_sideband;
843-
muxer.in = -1;
844-
code = start_async(&muxer);
845-
if (code)
846-
return code;
847-
proc.err = muxer.in;
848-
}
849-
850-
prepare_push_cert_sha1(&proc);
851-
852-
code = start_command(&proc);
853-
if (code) {
854-
if (use_sideband)
855-
finish_async(&muxer);
856-
return code;
857-
}
858-
859-
sigchain_push(SIGPIPE, SIG_IGN);
860-
861-
while (1) {
862-
const char *buf;
863-
size_t n;
864-
if (feed(feed_state, &buf, &n))
865-
break;
866-
if (write_in_full(proc.in, buf, n) < 0)
867-
break;
868-
}
869-
close(proc.in);
870-
if (use_sideband)
871-
finish_async(&muxer);
872-
873-
sigchain_pop(SIGPIPE);
874-
875-
return finish_command(&proc);
876-
}
877-
878-
static int feed_receive_hook(void *state_, const char **bufp, size_t *sizep)
810+
static int feed_receive_hook(void *state_)
879811
{
880812
struct receive_hook_feed_state *state = state_;
881813
struct command *cmd = state->cmd;
@@ -884,9 +816,7 @@ static int feed_receive_hook(void *state_, const char **bufp, size_t *sizep)
884816
state->skip_broken && (cmd->error_string || cmd->did_not_exist))
885817
cmd = cmd->next;
886818
if (!cmd)
887-
return -1; /* EOF */
888-
if (!bufp)
889-
return 0; /* OK, can feed something. */
819+
return 1; /* EOF - close the pipe*/
890820
strbuf_reset(&state->buf);
891821
if (!state->report)
892822
state->report = cmd->report;
@@ -910,32 +840,36 @@ static int feed_receive_hook(void *state_, const char **bufp, size_t *sizep)
910840
cmd->ref_name);
911841
state->cmd = cmd->next;
912842
}
913-
if (bufp) {
914-
*bufp = state->buf.buf;
915-
*sizep = state->buf.len;
916-
}
917843
return 0;
918844
}
919845

920-
static int run_receive_hook(struct command *commands,
921-
const char *hook_name,
922-
int skip_broken,
923-
const struct string_list *push_options)
846+
static int feed_receive_hook_cb(struct strbuf *pipe, void *pp_cb, void *pp_task_cb)
924847
{
925-
struct receive_hook_feed_state state;
926-
int status;
927-
928-
strbuf_init(&state.buf, 0);
929-
state.cmd = commands;
930-
state.skip_broken = skip_broken;
931-
state.report = NULL;
932-
if (feed_receive_hook(&state, NULL, NULL))
933-
return 0;
934-
state.cmd = commands;
935-
state.push_options = push_options;
936-
status = run_and_feed_hook(hook_name, feed_receive_hook, &state);
937-
strbuf_release(&state.buf);
938-
return status;
848+
struct hook *hook = pp_task_cb;
849+
struct receive_hook_feed_state *feed_state = hook->feed_pipe_cb_data;
850+
int rc;
851+
852+
/* first-time setup */
853+
if (!feed_state) {
854+
struct hook_cb_data *hook_cb = pp_cb;
855+
struct run_hooks_opt *opt = hook_cb->options;
856+
struct receive_hook_feed_context *ctx = opt->feed_pipe_ctx;
857+
if (!ctx)
858+
BUG("run_hooks_opt.feed_pipe_ctx required for receive hook");
859+
860+
feed_state = xmalloc(sizeof(struct receive_hook_feed_state));
861+
strbuf_init(&feed_state->buf, 0);
862+
feed_state->cmd = ctx->cmd;
863+
feed_state->skip_broken = ctx->skip_broken;
864+
feed_state->report = NULL;
865+
866+
hook->feed_pipe_cb_data = feed_state;
867+
}
868+
869+
rc = feed_receive_hook(feed_state);
870+
if (!rc)
871+
strbuf_addbuf(pipe, &feed_state->buf);
872+
return rc;
939873
}
940874

941875
static void hook_output_to_sideband(struct strbuf *output, void *cb_data)
@@ -971,6 +905,55 @@ static void hook_output_to_sideband(struct strbuf *output, void *cb_data)
971905
send_sideband(1, 2, output->buf, output->len, use_sideband);
972906
}
973907

908+
static int run_receive_hook(struct command *commands,
909+
const char *hook_name,
910+
int skip_broken,
911+
const struct string_list *push_options)
912+
{
913+
struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
914+
struct receive_hook_feed_context ctx;
915+
int rc;
916+
struct command *iter = commands;
917+
918+
/* if there are no valid commands, don't invoke the hook at all. */
919+
while (iter && skip_broken && (iter->error_string || iter->did_not_exist))
920+
iter = iter->next;
921+
if (!iter)
922+
return 0;
923+
924+
/* pre-receive hooks should run in series as the hook updates refs */
925+
if (!strcmp(hook_name, "pre-receive"))
926+
opt.jobs = 1;
927+
928+
if (push_options) {
929+
int i;
930+
for (i = 0; i < push_options->nr; i++)
931+
strvec_pushf(&opt.env, "GIT_PUSH_OPTION_%d=%s", i,
932+
push_options->items[i].string);
933+
strvec_pushf(&opt.env, "GIT_PUSH_OPTION_COUNT=%d", push_options->nr);
934+
} else
935+
strvec_push(&opt.env, "GIT_PUSH_OPTION_COUNT");
936+
937+
if (tmp_objdir)
938+
strvec_pushv(&opt.env, tmp_objdir_env(tmp_objdir));
939+
940+
prepare_push_cert_sha1(&opt);
941+
942+
/* set up sideband printer */
943+
if (use_sideband)
944+
opt.consume_sideband = hook_output_to_sideband;
945+
946+
/* set up stdin callback */
947+
ctx.cmd = commands;
948+
ctx.skip_broken = skip_broken;
949+
opt.feed_pipe = feed_receive_hook_cb;
950+
opt.feed_pipe_ctx = &ctx;
951+
952+
rc = run_hooks(hook_name, &opt);
953+
run_hooks_opt_clear(&opt);
954+
return rc;
955+
}
956+
974957
static int run_update_hook(struct command *cmd)
975958
{
976959
struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;

0 commit comments

Comments
 (0)