[PATCHv2 4/4] git: use run_command to execute dashed externals

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 <peff@xxxxxxxx>
---
Incorporates negated status fix from JSixt.

This version also differentiates in the exit code and stderr output
whether we simply failed to exec the command versus passing along its
status code.

 git.c |   17 +++++++++++++----
 1 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/git.c b/git.c
index 45e493d..b02b05b 100644
--- a/git.c
+++ b/git.c
@@ -2,6 +2,7 @@
 #include "exec_cmd.h"
 #include "cache.h"
 #include "quote.h"
+#include "run-command.h"
 
 const char git_usage_string[] =
 	"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)
 {
 	struct strbuf cmd = STRBUF_INIT;
 	const char *tmp;
+	int status;
 
 	strbuf_addf(&cmd, "git-%s", argv[0]);
 
@@ -406,10 +408,17 @@ static void execv_dashed_external(const char **argv)
 
 	trace_argv_printf(argv, "trace: exec:");
 
-	/* execvp() can only ever return if it fails */
-	execvp(cmd.buf, (char **)argv);
-
-	trace_printf("trace: exec failed: %s\n", strerror(errno));
+	/*
+	 * if we fail because the command is not found, it is
+	 * OK to return. Otherwise, we just pass along the status code.
+	 */
+	status = run_command_v_opt(argv, 0);
+	if (status != -ERR_RUN_COMMAND_EXEC) {
+		if (IS_RUN_COMMAND_ERR(status))
+			die("unable to run '%s'", argv[0]);
+		exit(-status);
+	}
+	errno = ENOENT; /* as if we called execvp */
 
 	argv[0] = tmp;
 
-- 
1.6.1.1.367.g30b36
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux