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 <gitster@pobox.com>
Junio C Hamano committed
Sep 8, 2011 at 12:17 UTC
9684e44a07495ad6ff0fa57f1d0cb7479b72e453
1 file changed
+52
-19
builtin/receive-pack.c
+52
-19
@@ -205,21 +205,15 @@ static int copy_to_sideband(int in, int out, void *arg)
205
return 0;
206
}
207
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)
210
{
210
- static char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4];
211
- struct command *cmd;
211
struct child_process proc;
212
struct async muxer;
213
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;
215
222
- if (!have_input || access(hook_name, X_OK) < 0)
216
+ if (access(hook_name, X_OK) < 0)
217
return 0;
218
219
argv[0] = hook_name;
@@ -247,15 +241,13 @@ static int run_receive_hook(struct command *commands, const char *hook_name)
241
return code;
242
}
243
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;
251
}
252
close(proc.in);
253
if (use_sideband)
@@ -263,6 +255,47 @@ static int run_receive_hook(struct command *commands, const char *hook_name)
255
return finish_command(&proc);
256
}
257
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
+
299
static int run_update_hook(struct command *cmd)
300
{
301
static const char update_hook[] = "hooks/update";