diff options
-rw-r--r-- | builtin/receive-pack.c | 71 |
1 files changed, 52 insertions, 19 deletions
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 9b56be3cc6..c1c5bac79e 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -212,21 +212,15 @@ static int copy_to_sideband(int in, int out, void *arg) return 0; } -static int run_receive_hook(struct command *commands, const char *hook_name) +typedef int (*feed_fn)(void *, const char **, size_t *); +static int run_and_feed_hook(const char *hook_name, feed_fn feed, void *feed_state) { - static char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4]; - struct command *cmd; struct child_process proc; struct async muxer; const char *argv[2]; - int have_input = 0, code; - - for (cmd = commands; !have_input && cmd; cmd = cmd->next) { - if (!cmd->error_string) - have_input = 1; - } + int code; - if (!have_input || access(hook_name, X_OK) < 0) + if (access(hook_name, X_OK) < 0) return 0; argv[0] = hook_name; @@ -254,15 +248,13 @@ static int run_receive_hook(struct command *commands, const char *hook_name) return code; } - for (cmd = commands; cmd; cmd = cmd->next) { - if (!cmd->error_string) { - size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n", - sha1_to_hex(cmd->old_sha1), - sha1_to_hex(cmd->new_sha1), - cmd->ref_name); - if (write_in_full(proc.in, buf, n) != n) - break; - } + while (1) { + const char *buf; + size_t n; + if (feed(feed_state, &buf, &n)) + break; + if (write_in_full(proc.in, buf, n) != n) + break; } close(proc.in); if (use_sideband) @@ -270,6 +262,47 @@ static int run_receive_hook(struct command *commands, const char *hook_name) return finish_command(&proc); } +struct receive_hook_feed_state { + struct command *cmd; + struct strbuf buf; +}; + +static int feed_receive_hook(void *state_, const char **bufp, size_t *sizep) +{ + struct receive_hook_feed_state *state = state_; + struct command *cmd = state->cmd; + + while (cmd && cmd->error_string) + cmd = cmd->next; + if (!cmd) + return -1; /* EOF */ + strbuf_reset(&state->buf); + strbuf_addf(&state->buf, "%s %s %s\n", + sha1_to_hex(cmd->old_sha1), sha1_to_hex(cmd->new_sha1), + cmd->ref_name); + state->cmd = cmd->next; + if (bufp) { + *bufp = state->buf.buf; + *sizep = state->buf.len; + } + return 0; +} + +static int run_receive_hook(struct command *commands, const char *hook_name) +{ + struct receive_hook_feed_state state; + int status; + + strbuf_init(&state.buf, 0); + state.cmd = commands; + if (feed_receive_hook(&state, NULL, NULL)) + return 0; + state.cmd = commands; + status = run_and_feed_hook(hook_name, feed_receive_hook, &state); + strbuf_release(&state.buf); + return status; +} + static int run_update_hook(struct command *cmd) { static const char update_hook[] = "hooks/update"; |