Skip to content

Commit

Permalink
Redirect update hook stdout to stderr.
Browse files Browse the repository at this point in the history
If an update hook outputs to stdout then that output will be sent
back over the wire to the push client as though it were part of
the git protocol.  This tends to cause protocol errors on the
client end of the connection, as the hook output is not expected
in that context.  Most hook developers work around this by making
sure their hook outputs everything to stderr.

But hooks shouldn't need to perform such special behavior.  Instead
we can just dup stderr to stdout prior to invoking the update hook.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
  • Loading branch information
Shawn O. Pearce authored and Junio C Hamano committed Dec 31, 2006
1 parent 9b0b509 commit cd83c74
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 7 deletions.
3 changes: 2 additions & 1 deletion receive-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ static int run_update_hook(const char *refname,

if (access(update_hook, X_OK) < 0)
return 0;
code = run_command(update_hook, refname, old_hex, new_hex, NULL);
code = run_command_opt(RUN_COMMAND_STDOUT_TO_STDERR,
update_hook, refname, old_hex, new_hex, NULL);
switch (code) {
case 0:
return 0;
Expand Down
32 changes: 26 additions & 6 deletions run-command.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ int run_command_v_opt(const char **argv, int flags)
dup2(fd, 0);
dup2(fd, 1);
close(fd);
}
} else if (flags & RUN_COMMAND_STDOUT_TO_STDERR)
dup2(2, 1);
if (flags & RUN_GIT_CMD) {
execv_git_cmd(argv);
} else {
Expand Down Expand Up @@ -51,23 +52,42 @@ int run_command_v(const char **argv)
return run_command_v_opt(argv, 0);
}

int run_command(const char *cmd, ...)
static int run_command_va_opt(int opt, const char *cmd, va_list param)
{
int argc;
const char *argv[MAX_RUN_COMMAND_ARGS];
const char *arg;
va_list param;

va_start(param, cmd);
argv[0] = (char*) cmd;
argc = 1;
while (argc < MAX_RUN_COMMAND_ARGS) {
arg = argv[argc++] = va_arg(param, char *);
if (!arg)
break;
}
va_end(param);
if (MAX_RUN_COMMAND_ARGS <= argc)
return error("too many args to run %s", cmd);
return run_command_v_opt(argv, 0);
return run_command_v_opt(argv, opt);
}

int run_command_opt(int opt, const char *cmd, ...)
{
va_list params;
int r;

va_start(params, cmd);
r = run_command_va_opt(opt, cmd, params);
va_end(params);
return r;
}

int run_command(const char *cmd, ...)
{
va_list params;
int r;

va_start(params, cmd);
r = run_command_va_opt(0, cmd, params);
va_end(params);
return r;
}
2 changes: 2 additions & 0 deletions run-command.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ enum {

#define RUN_COMMAND_NO_STDIO 1
#define RUN_GIT_CMD 2 /*If this is to be git sub-command */
#define RUN_COMMAND_STDOUT_TO_STDERR 4
int run_command_v_opt(const char **argv, int opt);
int run_command_v(const char **argv);
int run_command_opt(int opt, const char *cmd, ...);
int run_command(const char *cmd, ...);

#endif

0 comments on commit cd83c74

Please sign in to comment.