git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* Doesn't disambiguate between 'external command failed' and 'command not found'
@ 2011-07-05 16:49 Alex Vandiver
  2011-07-05 20:41 ` Michael Schubert
  0 siblings, 1 reply; 13+ messages in thread
From: Alex Vandiver @ 2011-07-05 16:49 UTC (permalink / raw)
  To: git

An external git-whatever command which fails to run gets reported as not
having been found, and suggests ... exactly what you just ran.  If you
miss the first line of the output, this can be extremely confusing --
and "is not a git command" is somewhat misleading:

        umgah ~ $ cat bin/git-bogus
        #!/usr/bin/env nonexistant
        echo "yay"
        
        umgah ~ $ git bogus
        /usr/bin/env: nonexistant: No such file or directory
        git: 'bogus' is not a git command. See 'git --help'.
        
        Did you mean this?
        	bogus

I've no patch right now, but I thought I'd report the frustration, in
case someone else wanted to get to it first.
 - Alex

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Doesn't disambiguate between 'external command failed' and 'command not found'
  2011-07-05 16:49 Doesn't disambiguate between 'external command failed' and 'command not found' Alex Vandiver
@ 2011-07-05 20:41 ` Michael Schubert
  2011-07-05 23:16   ` Jeff King
  0 siblings, 1 reply; 13+ messages in thread
From: Michael Schubert @ 2011-07-05 20:41 UTC (permalink / raw)
  To: git, Alex Vandiver

Hi,

here is a tiny patch; maybe there is a cleaner way doing this.?

-- >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.

Signed-off-by: Michael Schubert <mschub@elegosoft.com>
---
 help.c |   16 ++++++++++++++--
 1 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/help.c b/help.c
index 7654f1b..10b98ba 100644
--- a/help.c
+++ b/help.c
@@ -383,12 +383,24 @@ const char *help_unknown_cmd(const char *cmd)
 
 	fprintf(stderr, "git: '%s' is not a git command. See 'git --help'.\n", cmd);
 
-	if (SIMILAR_ENOUGH(best_similarity)) {
+	if (n==1 && !strcmp(cmd, main_cmds.names[0]->name))
+		;
+		/*
+		 * This avoids proposing the use of a command
+		 * which apparently just didn't work, e.g.
+		 * when executing a shell script git-foo with
+		 * the following shebang:
+		 *
+		 * 	#!/usr/bin/not/here
+		 *
+		 */
+	else if (SIMILAR_ENOUGH(best_similarity)) {
 		fprintf(stderr, "\nDid you mean %s?\n",
 			n < 2 ? "this": "one of these");
 
 		for (i = 0; i < n; i++)
-			fprintf(stderr, "\t%s\n", main_cmds.names[i]->name);
+			if (strcmp(cmd, main_cmds.names[i]->name))
+				fprintf(stderr, "\t%s\n", main_cmds.names[i]->name);
 	}
 
 	exit(1);
-- 
1.7.6.132.gdca5

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: Doesn't disambiguate between 'external command failed' and 'command not found'
  2011-07-05 20:41 ` Michael Schubert
@ 2011-07-05 23:16   ` Jeff King
  2011-07-05 23:22     ` Jeff King
                       ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Jeff King @ 2011-07-05 23:16 UTC (permalink / raw)
  To: Michael Schubert; +Cc: git, Alex Vandiver

On Tue, Jul 05, 2011 at 10:41:37PM +0200, Michael Schubert wrote:

> 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.

Yeah, I don't think we can distinguish "not there" versus "bad
interpreter" just from the exec return. We would have to then search the
PATH to see if the file actually exists.

> -	if (SIMILAR_ENOUGH(best_similarity)) {
> +	if (n==1 && !strcmp(cmd, main_cmds.names[0]->name))
> +		;
> +		/*
> +		 * This avoids proposing the use of a command
> +		 * which apparently just didn't work, e.g.
> +		 * when executing a shell script git-foo with
> +		 * the following shebang:
> +		 *
> +		 * 	#!/usr/bin/not/here
> +		 *
> +		 */
> +	else if (SIMILAR_ENOUGH(best_similarity)) {

This misses the "autocorrect" case just above, which should not
autocorrect a command to itself (and I didn't try, but I assume it makes
more a really slow infinite loop).

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.

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)?

Something like:

diff --git a/help.c b/help.c
index e925ca1..522b2ba 100644
--- a/help.c
+++ b/help.c
@@ -305,6 +305,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 able to\n"
+"execute it. Check the #!-line of the git-%s script.";
+
 const char *help_unknown_cmd(const char *cmd)
 {
 	int i, n, best_similarity = 0;
@@ -329,6 +333,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)

I'm not all that happy with the advice, though. It's pretty technical
and specific. I'm not sure whether it would be helpful to most users or
not.

-Peff

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: Doesn't disambiguate between 'external command failed' and 'command not found'
  2011-07-05 23:16   ` Jeff King
@ 2011-07-05 23:22     ` Jeff King
  2011-07-06 11:24       ` Sverre Rabbelier
  2011-07-06 11:47     ` Michael Schubert
  2011-07-06 17:24     ` Junio C Hamano
  2 siblings, 1 reply; 13+ messages in thread
From: Jeff King @ 2011-07-05 23:22 UTC (permalink / raw)
  To: Michael Schubert; +Cc: git, Alex Vandiver

On Tue, Jul 05, 2011 at 07:16:05PM -0400, Jeff King wrote:

> 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.

And here's what that would look like.

diff --git a/help.c b/help.c
index e925ca1..15e6f0b 100644
--- a/help.c
+++ b/help.c
@@ -329,6 +329,11 @@ const char *help_unknown_cmd(const char *cmd)
 		int cmp = 0; /* avoid compiler stupidity */
 		const char *candidate = main_cmds.names[i]->name;
 
+		if (!strcmp(candidate, cmd)) {
+			main_cmds.names[i]->len = SIMILARITY_FLOOR + 1;
+			continue;
+		}
+
 		/* Does the candidate appear in common_cmds list? */
 		while (n < ARRAY_SIZE(common_cmds) &&
 		       (cmp = strcmp(common_cmds[n].name, candidate)) < 0)

I suspect it can create its own brand of confusion, though:

  $ cat `which git-broken`
  #!/bin/bogus
  $ git broken
  git: 'broken' is not a git command. See 'git --help'.

At which point I search through my PATH and confirm that indeed,
"git-broken" _is_ a git command. And I'm left on my own to figure out
that it's a broken #!-line.

So I think I prefer giving some more specific advice. Even if we don't
mention "#!" lines explicitly, saying "This exists, but exec didn't
work" is probably more helpful than pretending it's not there. It gives
clueful people an idea of where to start looking for the problem.

-Peff

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: Doesn't disambiguate between 'external command failed' and 'command not found'
  2011-07-05 23:22     ` Jeff King
@ 2011-07-06 11:24       ` Sverre Rabbelier
  0 siblings, 0 replies; 13+ messages in thread
From: Sverre Rabbelier @ 2011-07-06 11:24 UTC (permalink / raw)
  To: Jeff King; +Cc: Michael Schubert, git, Alex Vandiver

Heya,

On Wed, Jul 6, 2011 at 01:22, Jeff King <peff@peff.net> wrote:
> So I think I prefer giving some more specific advice. Even if we don't
> mention "#!" lines explicitly, saying "This exists, but exec didn't
> work" is probably more helpful than pretending it's not there. It gives
> clueful people an idea of where to start looking for the problem.

Seconded. We should at least give the user enough information to
figure out next steps. I like the advice from bad_interpreter_advice,
although it might be phrased more as a suggestion "Try looking at
..."?

-- 
Cheers,

Sverre Rabbelier

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Doesn't disambiguate between 'external command failed' and 'command not found'
  2011-07-05 23:16   ` Jeff King
  2011-07-05 23:22     ` Jeff King
@ 2011-07-06 11:47     ` Michael Schubert
  2011-07-06 17:58       ` Jeff King
  2011-07-06 17:24     ` Junio C Hamano
  2 siblings, 1 reply; 13+ messages in thread
From: Michael Schubert @ 2011-07-06 11:47 UTC (permalink / raw)
  To: Jeff King, git, Alex Vandiver, Sverre Rabbelier


> 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 <peff@peff.net>
Signed-off-by: Michael Schubert <mschub@elegosoft.com>
---
 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

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: Doesn't disambiguate between 'external command failed' and 'command not found'
  2011-07-05 23:16   ` Jeff King
  2011-07-05 23:22     ` Jeff King
  2011-07-06 11:47     ` Michael Schubert
@ 2011-07-06 17:24     ` Junio C Hamano
  2011-07-06 17:56       ` Jeff King
  2 siblings, 1 reply; 13+ messages in thread
From: Junio C Hamano @ 2011-07-06 17:24 UTC (permalink / raw)
  To: Jeff King; +Cc: Michael Schubert, git, Alex Vandiver

Jeff King <peff@peff.net> writes:

> I'm not all that happy with the advice, though. It's pretty technical
> and specific. I'm not sure whether it would be helpful to most users or
> not.

Yeah, Michael's rewording makes it fuzzier by saying "exists, unable to
execute, maybe git-%s is broken?".

I notice that we do not give the path to the file that implements the
command. Perhaps we should walk the $PATH after we see this failure to
pinpoint which one is to be inspected (I vaguely recall a weatherbaloon
patch to a similar effect)?

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Doesn't disambiguate between 'external command failed' and 'command not found'
  2011-07-06 17:24     ` Junio C Hamano
@ 2011-07-06 17:56       ` Jeff King
  0 siblings, 0 replies; 13+ messages in thread
From: Jeff King @ 2011-07-06 17:56 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Michael Schubert, git, Alex Vandiver

On Wed, Jul 06, 2011 at 10:24:57AM -0700, Junio C Hamano wrote:

> Jeff King <peff@peff.net> writes:
> 
> > I'm not all that happy with the advice, though. It's pretty technical
> > and specific. I'm not sure whether it would be helpful to most users or
> > not.
> 
> Yeah, Michael's rewording makes it fuzzier by saying "exists, unable to
> execute, maybe git-%s is broken?".

Yeah, I like his better.

> I notice that we do not give the path to the file that implements the
> command. Perhaps we should walk the $PATH after we see this failure to
> pinpoint which one is to be inspected (I vaguely recall a weatherbaloon
> patch to a similar effect)?

That would be better still. But I don't know how much effort this is
really worth. It is about catching one specific uncommon
misconfiguration. If it were part of a more general exec wrapper that
gave better output (which I think is the weatherballoon you mean, that
you did a month or three ago), I think it might be more worthwhile.

But even then, I seem to remember the discussion fizzling out to "is
this really that common a problem?"

So I'm happy with just taking Michael's patch.

-Peff

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Doesn't disambiguate between 'external command failed' and 'command not found'
  2011-07-06 11:47     ` Michael Schubert
@ 2011-07-06 17:58       ` Jeff King
  2011-07-06 18:00         ` Jeff King
  0 siblings, 1 reply; 13+ messages in thread
From: Jeff King @ 2011-07-06 17:58 UTC (permalink / raw)
  To: Michael Schubert; +Cc: git, Alex Vandiver, Sverre Rabbelier

On Wed, Jul 06, 2011 at 01:47:33PM +0200, Michael Schubert wrote:

> 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..

Yeah, looks good to me (unless somebody wants to do something more
elaborate to catch other exec problems, but I personally don't think
it's worth the effort).

-Peff

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Doesn't disambiguate between 'external command failed' and 'command not found'
  2011-07-06 17:58       ` Jeff King
@ 2011-07-06 18:00         ` Jeff King
  2011-07-06 23:25           ` Junio C Hamano
  0 siblings, 1 reply; 13+ messages in thread
From: Jeff King @ 2011-07-06 18:00 UTC (permalink / raw)
  To: Michael Schubert; +Cc: git, Alex Vandiver, Sverre Rabbelier

On Wed, Jul 06, 2011 at 01:58:03PM -0400, Jeff King wrote:

> > 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..
> 
> Yeah, looks good to me (unless somebody wants to do something more
> elaborate to catch other exec problems, but I personally don't think
> it's worth the effort).

One minor nit, though. I haven't been paying attention to the progress
of the gettext topics, but should this message:

> +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?";

Actually be inside _() for gettext?

-Peff

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Doesn't disambiguate between 'external command failed' and 'command not found'
  2011-07-06 18:00         ` Jeff King
@ 2011-07-06 23:25           ` Junio C Hamano
  2011-07-08 10:08             ` Michael Schubert
  0 siblings, 1 reply; 13+ messages in thread
From: Junio C Hamano @ 2011-07-06 23:25 UTC (permalink / raw)
  To: Jeff King; +Cc: Michael Schubert, git, Alex Vandiver, Sverre Rabbelier

Jeff King <peff@peff.net> writes:

> On Wed, Jul 06, 2011 at 01:58:03PM -0400, Jeff King wrote:
>
>> > 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..
>> 
>> Yeah, looks good to me (unless somebody wants to do something more
>> elaborate to catch other exec problems, but I personally don't think
>> it's worth the effort).
>
> One minor nit, though. I haven't been paying attention to the progress
> of the gettext topics, but should this message:
>
>> +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?";
>
> Actually be inside _() for gettext?

I would mark it with N_() and then the calling site inside die() with _()
if I were doing this.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Doesn't disambiguate between 'external command failed' and 'command not found'
  2011-07-06 23:25           ` Junio C Hamano
@ 2011-07-08 10:08             ` Michael Schubert
  2011-07-08 16:52               ` Junio C Hamano
  0 siblings, 1 reply; 13+ messages in thread
From: Michael Schubert @ 2011-07-08 10:08 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Alex Vandiver, Sverre Rabbelier, Jeff King

On 07/07/2011 01:25 AM, Junio C Hamano wrote:
> Jeff King <peff@peff.net> writes:
>> One minor nit, though. I haven't been paying attention to the progress
>> of the gettext topics, but should this message:
>>
>>> +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?";
>>
>> Actually be inside _() for gettext?
> 
> I would mark it with N_() and then the calling site inside die() with _()
> if I were doing this.

Sorry for the delay.

-- >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 <peff@peff.net>
Signed-off-by: Michael Schubert <mschub@elegosoft.com>
---
 help.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/help.c b/help.c
index 7654f1b..4219355 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[] =
+	N_("'%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.dirty

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: Doesn't disambiguate between 'external command failed' and 'command not found'
  2011-07-08 10:08             ` Michael Schubert
@ 2011-07-08 16:52               ` Junio C Hamano
  0 siblings, 0 replies; 13+ messages in thread
From: Junio C Hamano @ 2011-07-08 16:52 UTC (permalink / raw)
  To: Michael Schubert; +Cc: git, Alex Vandiver, Sverre Rabbelier, Jeff King

Michael Schubert <mschub@elegosoft.com> writes:

> Sorry for the delay.

Thanks.

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2011-07-11 20:08 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-05 16:49 Doesn't disambiguate between 'external command failed' and 'command not found' Alex Vandiver
2011-07-05 20:41 ` Michael Schubert
2011-07-05 23:16   ` Jeff King
2011-07-05 23:22     ` Jeff King
2011-07-06 11:24       ` Sverre Rabbelier
2011-07-06 11:47     ` Michael Schubert
2011-07-06 17:58       ` Jeff King
2011-07-06 18:00         ` Jeff King
2011-07-06 23:25           ` Junio C Hamano
2011-07-08 10:08             ` Michael Schubert
2011-07-08 16:52               ` Junio C Hamano
2011-07-06 17:24     ` Junio C Hamano
2011-07-06 17:56       ` Jeff King

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).