Skip to content

Commit 9684e44

Browse files
committed
refactor run_receive_hook()
Running a hook has to make complex set-up to establish web of communication between child process and multiplexer, which is common regardless of what kind of data is fed to the hook. Refactor the parts that is specific to the data fed to the particular set of hooks from the part that runs the hook, so that the code can be reused to drive hooks that take different kind of data. Signed-off-by: Junio C Hamano <[email protected]>
1 parent 50963ba commit 9684e44

File tree

1 file changed

+52
-19
lines changed

1 file changed

+52
-19
lines changed

builtin/receive-pack.c

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -205,21 +205,15 @@ static int copy_to_sideband(int in, int out, void *arg)
205205
return 0;
206206
}
207207

208-
static int run_receive_hook(struct command *commands, const char *hook_name)
208+
typedef int (*feed_fn)(void *, const char **, size_t *);
209+
static int run_and_feed_hook(const char *hook_name, feed_fn feed, void *feed_state)
209210
{
210-
static char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4];
211-
struct command *cmd;
212211
struct child_process proc;
213212
struct async muxer;
214213
const char *argv[2];
215-
int have_input = 0, code;
216-
217-
for (cmd = commands; !have_input && cmd; cmd = cmd->next) {
218-
if (!cmd->error_string)
219-
have_input = 1;
220-
}
214+
int code;
221215

222-
if (!have_input || access(hook_name, X_OK) < 0)
216+
if (access(hook_name, X_OK) < 0)
223217
return 0;
224218

225219
argv[0] = hook_name;
@@ -247,22 +241,61 @@ static int run_receive_hook(struct command *commands, const char *hook_name)
247241
return code;
248242
}
249243

250-
for (cmd = commands; cmd; cmd = cmd->next) {
251-
if (!cmd->error_string) {
252-
size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n",
253-
sha1_to_hex(cmd->old_sha1),
254-
sha1_to_hex(cmd->new_sha1),
255-
cmd->ref_name);
256-
if (write_in_full(proc.in, buf, n) != n)
257-
break;
258-
}
244+
while (1) {
245+
const char *buf;
246+
size_t n;
247+
if (feed(feed_state, &buf, &n))
248+
break;
249+
if (write_in_full(proc.in, buf, n) != n)
250+
break;
259251
}
260252
close(proc.in);
261253
if (use_sideband)
262254
finish_async(&muxer);
263255
return finish_command(&proc);
264256
}
265257

258+
struct receive_hook_feed_state {
259+
struct command *cmd;
260+
struct strbuf buf;
261+
};
262+
263+
static int feed_receive_hook(void *state_, const char **bufp, size_t *sizep)
264+
{
265+
struct receive_hook_feed_state *state = state_;
266+
struct command *cmd = state->cmd;
267+
268+
while (cmd && cmd->error_string)
269+
cmd = cmd->next;
270+
if (!cmd)
271+
return -1; /* EOF */
272+
strbuf_reset(&state->buf);
273+
strbuf_addf(&state->buf, "%s %s %s\n",
274+
sha1_to_hex(cmd->old_sha1), sha1_to_hex(cmd->new_sha1),
275+
cmd->ref_name);
276+
state->cmd = cmd->next;
277+
if (bufp) {
278+
*bufp = state->buf.buf;
279+
*sizep = state->buf.len;
280+
}
281+
return 0;
282+
}
283+
284+
static int run_receive_hook(struct command *commands, const char *hook_name)
285+
{
286+
struct receive_hook_feed_state state;
287+
int status;
288+
289+
strbuf_init(&state.buf, 0);
290+
state.cmd = commands;
291+
if (feed_receive_hook(&state, NULL, NULL))
292+
return 0;
293+
state.cmd = commands;
294+
status = run_and_feed_hook(hook_name, feed_receive_hook, &state);
295+
strbuf_release(&state.buf);
296+
return status;
297+
}
298+
266299
static int run_update_hook(struct command *cmd)
267300
{
268301
static const char update_hook[] = "hooks/update";

0 commit comments

Comments
 (0)