receive-pack: Send hook output over side band #2
If the client requests to enable side-band-64k capability we can safely send any hook stdout or stderr data down side band #2, so the client can present it to the user. If side-band-64k isn't enabled, hooks continue to inherit stderr from the parent receive-pack process. When the side band channel is being used the push client will wind up prefixing all server messages with "remote: ", just like fetch does, so our test vector has to be updated with the new expected output. Signed-off-by: Shawn O. Pearce <spearce@spearce.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Shawn O. Pearce committed
Feb 5, 2010 at 12:57 UTC
6d525d389fbef814b11e41f196e6656f2e95f412
2 files changed
+70
-17
builtin-receive-pack.c
+59
-6
@@ -139,11 +139,25 @@ static struct command *commands;
139
static const char pre_receive_hook[] = "hooks/pre-receive";
140
static const char post_receive_hook[] = "hooks/post-receive";
141
142
+static int copy_to_sideband(int in, int out, void *arg)
143
+{
144
+ char data[128];
145
+ while (1) {
146
+ ssize_t sz = xread(in, data, sizeof(data));
147
+ if (sz <= 0)
148
+ break;
149
+ send_sideband(1, 2, data, sz, use_sideband);
150
+ }
151
+ close(in);
152
+ return 0;
153
+}
154
+
155
static int run_receive_hook(const char *hook_name)
156
{
157
static char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4];
158
struct command *cmd;
159
struct child_process proc;
160
+ struct async muxer;
161
const char *argv[2];
162
int have_input = 0, code;
163
@@ -163,9 +177,23 @@ static int run_receive_hook(const char *hook_name)
177
proc.in = -1;
178
proc.stdout_to_stderr = 1;
179
180
+ if (use_sideband) {
181
+ memset(&muxer, 0, sizeof(muxer));
182
+ muxer.proc = copy_to_sideband;
183
+ muxer.in = -1;
184
+ code = start_async(&muxer);
185
+ if (code)
186
+ return code;
187
+ proc.err = muxer.in;
188
+ }
189
+
190
code = start_command(&proc);
167
- if (code)
191
+ if (code) {
192
+ if (use_sideband)
193
+ finish_async(&muxer);
194
return code;
195
+ }
196
+
197
for (cmd = commands; cmd; cmd = cmd->next) {
198
if (!cmd->error_string) {
199
size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n",
@@ -177,6 +205,8 @@ static int run_receive_hook(const char *hook_name)
205
}
206
}
207
close(proc.in);
208
+ if (use_sideband)
209
+ finish_async(&muxer);
210
return finish_command(&proc);
211
}
212
@@ -184,6 +214,8 @@ static int run_update_hook(struct command *cmd)
214
{
215
static const char update_hook[] = "hooks/update";
216
const char *argv[5];
217
+ struct child_process proc;
218
+ int code;
219
220
if (access(update_hook, X_OK) < 0)
221
return 0;
@@ -194,8 +226,18 @@ static int run_update_hook(struct command *cmd)
226
argv[3] = sha1_to_hex(cmd->new_sha1);
227
argv[4] = NULL;
228
197
- return run_command_v_opt(argv, RUN_COMMAND_NO_STDIN |
198
- RUN_COMMAND_STDOUT_TO_STDERR);
229
+ memset(&proc, 0, sizeof(proc));
230
+ proc.no_stdin = 1;
231
+ proc.stdout_to_stderr = 1;
232
+ proc.err = use_sideband ? -1 : 0;
233
+ proc.argv = argv;
234
+
235
+ code = start_command(&proc);
236
+ if (code)
237
+ return code;
238
+ if (use_sideband)
239
+ copy_to_sideband(proc.err, -1, NULL);
240
+ return finish_command(&proc);
241
}
242
243
static int is_ref_checked_out(const char *ref)
@@ -384,8 +426,9 @@ static char update_post_hook[] = "hooks/post-update";
426
static void run_update_post_hook(struct command *cmd)
427
{
428
struct command *cmd_p;
387
- int argc, status;
429
+ int argc;
430
const char **argv;
431
+ struct child_process proc;
432
433
for (argc = 0, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
434
if (cmd_p->error_string)
@@ -407,8 +450,18 @@ static void run_update_post_hook(struct command *cmd)
450
argc++;
451
}
452
argv[argc] = NULL;
410
- status = run_command_v_opt(argv, RUN_COMMAND_NO_STDIN
411
- | RUN_COMMAND_STDOUT_TO_STDERR);
453
+
454
+ memset(&proc, 0, sizeof(proc));
455
+ proc.no_stdin = 1;
456
+ proc.stdout_to_stderr = 1;
457
+ proc.err = use_sideband ? -1 : 0;
458
+ proc.argv = argv;
459
+
460
+ if (!start_command(&proc)) {
461
+ if (use_sideband)
462
+ copy_to_sideband(proc.err, -1, NULL);
463
+ finish_command(&proc);
464
+ }
465
}
466
467
static void execute_commands(const char *unpacker_error)
t/t5401-update-hooks.sh
+11
-11
@@ -118,19 +118,19 @@ test_expect_success 'send-pack produced no output' '
118
'
119
120
cat <<EOF >expect
121
-STDOUT pre-receive
122
-STDERR pre-receive
123
-STDOUT update refs/heads/master
124
-STDERR update refs/heads/master
125
-STDOUT update refs/heads/tofail
126
-STDERR update refs/heads/tofail
127
-STDOUT post-receive
128
-STDERR post-receive
129
-STDOUT post-update
130
-STDERR post-update
121
+remote: STDOUT pre-receive
122
+remote: STDERR pre-receive
123
+remote: STDOUT update refs/heads/master
124
+remote: STDERR update refs/heads/master
125
+remote: STDOUT update refs/heads/tofail
126
+remote: STDERR update refs/heads/tofail
127
+remote: STDOUT post-receive
128
+remote: STDERR post-receive
129
+remote: STDOUT post-update
130
+remote: STDERR post-update
131
EOF
132
test_expect_success 'send-pack stderr contains hook messages' '
133
- grep ^STD send.err >actual &&
133
+ grep ^remote: send.err | sed "s/ *\$//" >actual &&
134
test_cmp - actual <expect
135
'
136