run_command: report failure to execute the program, but optionally don't
authorJohannes Sixt <j6t@kdbg.org>
Sat, 4 Jul 2009 19:26:42 +0000 (21:26 +0200)
committerJunio C Hamano <gitster@pobox.com>
Mon, 6 Jul 2009 09:45:50 +0000 (02:45 -0700)
In the case where a program was not found, it was still the task of the
caller to report an error to the user. Usually, this is an interesting case
but only few callers actually reported a specific error (though many call
sites report a generic error message regardless of the cause).

With this change the error is reported by run_command, but since there is
one call site in git.c that does not want that, an option is added to
struct child_process, which is used to turn the error off.

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin-receive-pack.c
git.c
run-command.c
run-command.h
transport.c

index 1dcdb1a514780cc80ae84b5a9f4aa6bc78c0df14..c85507b12291de48b5306bc9949815bf50dd9dcf 100644 (file)
@@ -125,9 +125,7 @@ static const char post_receive_hook[] = "hooks/post-receive";
 
 static int run_status(int code, const char *cmd_name)
 {
-       if (code < 0 && errno == ENOENT)
-               return error("execute of %s failed", cmd_name);
-       else if (code > 0)
+       if (code > 0)
                error("%s exited with error code %d", cmd_name, code);
        return code;
 }
diff --git a/git.c b/git.c
index 03726eee5e186552b3eb11d3c8b357c006caa9f1..18240280e8383a73e575ff0fc519dcfa6bf1db42 100644 (file)
--- a/git.c
+++ b/git.c
@@ -416,7 +416,7 @@ static void execv_dashed_external(const char **argv)
         * 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);
+       status = run_command_v_opt(argv, RUN_SILENT_EXEC_FAILURE);
        if (status >= 0 || errno != ENOENT)
                exit(status);
 
index 30c2b3dd8826acd3b50ab18e8efb4ff473fd7cf2..b613bddc717b98d29ff54a852e99332a2fa6fdc8 100644 (file)
@@ -185,7 +185,7 @@ fail_pipe:
 
        cmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env);
        failed_errno = errno;
-       if (cmd->pid < 0 && errno != ENOENT)
+       if (cmd->pid < 0 && (!cmd->silent_exec_failure || errno != ENOENT))
                error("cannot spawn %s: %s", cmd->argv[0], strerror(errno));
 
        if (cmd->env)
@@ -233,7 +233,7 @@ fail_pipe:
        return 0;
 }
 
-static int wait_or_whine(pid_t pid, const char *argv0)
+static int wait_or_whine(pid_t pid, const char *argv0, int silent_exec_failure)
 {
        int status, code = -1;
        pid_t waiting;
@@ -264,6 +264,9 @@ static int wait_or_whine(pid_t pid, const char *argv0)
                if (code == 127) {
                        code = -1;
                        failed_errno = ENOENT;
+                       if (!silent_exec_failure)
+                               error("cannot run %s: %s", argv0,
+                                       strerror(ENOENT));
                }
        } else {
                error("waitpid is confused (%s)", argv0);
@@ -274,7 +277,7 @@ static int wait_or_whine(pid_t pid, const char *argv0)
 
 int finish_command(struct child_process *cmd)
 {
-       return wait_or_whine(cmd->pid, cmd->argv[0]);
+       return wait_or_whine(cmd->pid, cmd->argv[0], cmd->silent_exec_failure);
 }
 
 int run_command(struct child_process *cmd)
@@ -294,6 +297,7 @@ static void prepare_run_command_v_opt(struct child_process *cmd,
        cmd->no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0;
        cmd->git_cmd = opt & RUN_GIT_CMD ? 1 : 0;
        cmd->stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
+       cmd->silent_exec_failure = opt & RUN_SILENT_EXEC_FAILURE ? 1 : 0;
 }
 
 int run_command_v_opt(const char **argv, int opt)
@@ -358,7 +362,7 @@ int start_async(struct async *async)
 int finish_async(struct async *async)
 {
 #ifndef __MINGW32__
-       int ret = wait_or_whine(async->pid, "child process");
+       int ret = wait_or_whine(async->pid, "child process", 0);
 #else
        DWORD ret = 0;
        if (WaitForSingleObject(async->tid, INFINITE) != WAIT_OBJECT_0)
index ac6c09c8967793586eb3830e544f535a3a01ede5..0c00b25ff2ea8710a1d963619d633a9be1a6f626 100644 (file)
@@ -31,6 +31,7 @@ struct child_process {
        unsigned no_stdout:1;
        unsigned no_stderr:1;
        unsigned git_cmd:1; /* if this is to be git sub-command */
+       unsigned silent_exec_failure:1;
        unsigned stdout_to_stderr:1;
        void (*preexec_cb)(void);
 };
@@ -44,6 +45,7 @@ extern int run_hook(const char *index_file, const char *name, ...);
 #define RUN_COMMAND_NO_STDIN 1
 #define RUN_GIT_CMD         2  /*If this is to be git sub-command */
 #define RUN_COMMAND_STDOUT_TO_STDERR 4
+#define RUN_SILENT_EXEC_FAILURE 8
 int run_command_v_opt(const char **argv, int opt);
 
 /*
index 0885801a0674f44e96f509fb867fab467cc3aacb..802ce7f233116cc52367b965e9e0d97bd8553535 100644 (file)
@@ -396,7 +396,6 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons
 {
        const char **argv;
        int argc;
-       int err;
 
        if (flags & TRANSPORT_PUSH_MIRROR)
                return error("http transport does not support mirror mode");
@@ -416,10 +415,7 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons
        while (refspec_nr--)
                argv[argc++] = *refspec++;
        argv[argc] = NULL;
-       err = run_command_v_opt(argv, RUN_GIT_CMD);
-       if (err < 0 && errno == ENOENT)
-               error("unable to exec %s", argv[0]);
-       return !!err;
+       return !!run_command_v_opt(argv, RUN_GIT_CMD);
 }
 
 static struct ref *get_refs_via_curl(struct transport *transport, int for_push)