Skip to content

Commit d8e96fd

Browse files
peffgitster
authored andcommitted
git: use run_command() to execute dashed externals
We used to simply try calling execvp(); if it succeeded, then we were done and the new program was running. If it didn't, then we knew that it wasn't a valid command. Unfortunately, this interacted badly with the new pager handling. Now that git remains the parent process and the pager is spawned, git has to hang around until the pager is finished. We install an atexit handler to do this, but that handler never gets called if we successfully run execvp. You could see this behavior by running any dashed external using a pager (e.g., "git -p stash list"). The command finishes running, but the pager is still going. In the case of less, it then gets an error reading from the terminal and exits, potentially leaving the terminal in a broken state (and not showing the output). This patch just uses run_command() to try running the dashed external. The parent git process then waits for the external process to complete and then handles the pager cleanup as it would for an internal command. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 1d64f21 commit d8e96fd

File tree

1 file changed

+13
-4
lines changed

1 file changed

+13
-4
lines changed

git.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "exec_cmd.h"
33
#include "cache.h"
44
#include "quote.h"
5+
#include "run-command.h"
56

67
const char git_usage_string[] =
78
"git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]";
@@ -392,6 +393,7 @@ static void execv_dashed_external(const char **argv)
392393
{
393394
struct strbuf cmd = STRBUF_INIT;
394395
const char *tmp;
396+
int status;
395397

396398
strbuf_addf(&cmd, "git-%s", argv[0]);
397399

@@ -406,10 +408,17 @@ static void execv_dashed_external(const char **argv)
406408

407409
trace_argv_printf(argv, "trace: exec:");
408410

409-
/* execvp() can only ever return if it fails */
410-
execvp(cmd.buf, (char **)argv);
411-
412-
trace_printf("trace: exec failed: %s\n", strerror(errno));
411+
/*
412+
* if we fail because the command is not found, it is
413+
* OK to return. Otherwise, we just pass along the status code.
414+
*/
415+
status = run_command_v_opt(argv, 0);
416+
if (status != -ERR_RUN_COMMAND_EXEC) {
417+
if (IS_RUN_COMMAND_ERR(status))
418+
die("unable to run '%s'", argv[0]);
419+
exit(-status);
420+
}
421+
errno = ENOENT; /* as if we called execvp */
413422

414423
argv[0] = tmp;
415424

0 commit comments

Comments
 (0)