@matheusbsbs / matheus-bagliano / commits / 6d525d389f
Fork 0

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