Skip to content

Commit 6d525d3

Browse files
spearcegitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 38a81b4 commit 6d525d3

File tree

2 files changed

+70
-17
lines changed

2 files changed

+70
-17
lines changed

builtin-receive-pack.c

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,25 @@ static struct command *commands;
139139
static const char pre_receive_hook[] = "hooks/pre-receive";
140140
static const char post_receive_hook[] = "hooks/post-receive";
141141

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+
142155
static int run_receive_hook(const char *hook_name)
143156
{
144157
static char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4];
145158
struct command *cmd;
146159
struct child_process proc;
160+
struct async muxer;
147161
const char *argv[2];
148162
int have_input = 0, code;
149163

@@ -163,9 +177,23 @@ static int run_receive_hook(const char *hook_name)
163177
proc.in = -1;
164178
proc.stdout_to_stderr = 1;
165179

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+
166190
code = start_command(&proc);
167-
if (code)
191+
if (code) {
192+
if (use_sideband)
193+
finish_async(&muxer);
168194
return code;
195+
}
196+
169197
for (cmd = commands; cmd; cmd = cmd->next) {
170198
if (!cmd->error_string) {
171199
size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n",
@@ -177,13 +205,17 @@ static int run_receive_hook(const char *hook_name)
177205
}
178206
}
179207
close(proc.in);
208+
if (use_sideband)
209+
finish_async(&muxer);
180210
return finish_command(&proc);
181211
}
182212

183213
static int run_update_hook(struct command *cmd)
184214
{
185215
static const char update_hook[] = "hooks/update";
186216
const char *argv[5];
217+
struct child_process proc;
218+
int code;
187219

188220
if (access(update_hook, X_OK) < 0)
189221
return 0;
@@ -194,8 +226,18 @@ static int run_update_hook(struct command *cmd)
194226
argv[3] = sha1_to_hex(cmd->new_sha1);
195227
argv[4] = NULL;
196228

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);
199241
}
200242

201243
static int is_ref_checked_out(const char *ref)
@@ -384,8 +426,9 @@ static char update_post_hook[] = "hooks/post-update";
384426
static void run_update_post_hook(struct command *cmd)
385427
{
386428
struct command *cmd_p;
387-
int argc, status;
429+
int argc;
388430
const char **argv;
431+
struct child_process proc;
389432

390433
for (argc = 0, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
391434
if (cmd_p->error_string)
@@ -407,8 +450,18 @@ static void run_update_post_hook(struct command *cmd)
407450
argc++;
408451
}
409452
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+
}
412465
}
413466

414467
static void execute_commands(const char *unpacker_error)

t/t5401-update-hooks.sh

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -118,19 +118,19 @@ test_expect_success 'send-pack produced no output' '
118118
'
119119

120120
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
131131
EOF
132132
test_expect_success 'send-pack stderr contains hook messages' '
133-
grep ^STD send.err >actual &&
133+
grep ^remote: send.err | sed "s/ *\$//" >actual &&
134134
test_cmp - actual <expect
135135
'
136136

0 commit comments

Comments
 (0)