Subject: Re: Doesn't disambiguate between 'external command failed' and 'command not found'

From: Michael Schubert <[email-masked]>
Date: Wed, 06 Jul 2011 13:47:33 +0200

> So if you are going to follow this strategy, you are probably better to
> just skip the entry (or give it a high levenshtein distance) in the main
> loop where we calculate candidates.

Yes.

> But I wonder if we can do even better than just omitting it from the
> candidates list. I mentioned searching the PATH above; but that is
> exactly what load_command_list does to create this candidate list. So I
> think the only way we can have an exact match is one of:
> 
>   1. There is a race condition. We tried to exec the command, and it was
>      missing; meanwhile, another process created the command.
> 
>   2. Exec'ing the command returned ENOENT because of a bad interpreter.
> 
> Option (1) seems fairly unlikely; so maybe we should give the user some
> advice about (2)?

Like this? I've replaced "Check the #!-line of the git-%s script." with
"Maybe git-%s is broken?" to be less technical and specific..

-- >8 --

Subject: [PATCH] help_unknown_cmd: do not propose an "unknown" cmd

When executing an external shell script like `git foo` with the following
shebang "#!/usr/bin/not/existing", execvp returns 127 (ENOENT). Since
help_unknown_cmd proposes the use of all external commands similar to
the name of the "unknown" command, it suggests the just failed command
again. Stop it and give some advice to the user.

Helped-by: Jeff King <[email-masked]>
Signed-off-by: Michael Schubert <[email-masked]>
---
 help.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/help.c b/help.c
index 7654f1b..a5a0613 100644
--- a/help.c
+++ b/help.c
@@ -302,6 +302,10 @@ static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
 #define SIMILARITY_FLOOR 7
 #define SIMILAR_ENOUGH(x) ((x) < SIMILARITY_FLOOR)
 
+static const char bad_interpreter_advice[] =
+	"'%s' appears to be a git command, but we were not\n"
+	"able to execute it. Maybe git-%s is broken?";
+
 const char *help_unknown_cmd(const char *cmd)
 {
 	int i, n, best_similarity = 0;
@@ -326,6 +330,14 @@ const char *help_unknown_cmd(const char *cmd)
 		int cmp = 0; /* avoid compiler stupidity */
 		const char *candidate = main_cmds.names[i]->name;
 
+		/*
+		 * An exact match means we have the command, but
+		 * for some reason exec'ing it gave us ENOENT; probably
+		 * it's a bad interpreter in the #! line.
+		 */
+		if (!strcmp(candidate, cmd))
+			die(bad_interpreter_advice, cmd, cmd);
+
 		/* Does the candidate appear in common_cmds list? */
 		while (n < ARRAY_SIZE(common_cmds) &&
 		       (cmp = strcmp(common_cmds[n].name, candidate)) < 0)
-- 
1.7.6.132.g91c244