{"thread":{"id":"16984","subject":"[PATCH] git.c: make autocorrected aliases work","startedAt":"2009-01-04T17:08:19Z","lastAt":"2009-01-06T08:19:09Z","messageCount":6,"participants":["Adeodato Simó","Alexander Potashev","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"99310","messageId":"1231088899-11943-1-git-send-email-dato@net.com.org.es","threadId":"16984","inReplyTo":null,"subject":"[PATCH] git.c: make autocorrected aliases work","fromName":"Adeodato Simó","fromEmail":"dato@net.com.org.es","sentAt":"2009-01-04T17:08:19Z","receivedAt":"2009-01-04T17:08:19Z","isPatch":true,"sender":{"key":"dato@net.com.org.es","avatar":"https://gravatar.com/avatar/952ec7d5d5663eb8baf631b5c37f9c58480a881920dd5f8a2d3a71f969b72b53?d=mp&s=160"},"body":"help_unknown_cmd() is able to autocorrect a command to an alias, and not\nonly to internal or external commands. However, main() was not passing the\nautocorrected command through handle_alias(), hence it failed if it was an\nalias.\n\nThis commit makes the autocorrected command go through handle_alias, once\nhandle_internal_command() and execv_dashed_external() have been tried. Since\nthis is done twice in main() now, moved that logic to a new run_argv()\nfunction.\n\nSigned-off-by: Adeodato Simó <dato@net.com.org.es>\n---\n git.c |   46 +++++++++++++++++++++++++++-------------------\n 1 files changed, 27 insertions(+), 19 deletions(-)\n\ndiff --git a/git.c b/git.c\nindex e0d9071..f443b4c 100644\n--- a/git.c\n+++ b/git.c\n@@ -416,12 +416,35 @@ static void execv_dashed_external(const char **argv)\n \tstrbuf_release(&cmd);\n }\n \n+static int run_argv(int *argcp, const char ***argv)\n+{\n+\tint done_alias = 0;\n+\n+\twhile (1) {\n+\t\t/* See if it's an internal command */\n+\t\thandle_internal_command(*argcp, *argv);\n+\n+\t\t/* .. then try the external ones */\n+\t\texecv_dashed_external(*argv);\n+\n+\t\t/* It could be an alias -- this works around the insanity\n+\t\t * of overriding \"git log\" with \"git show\" by having\n+\t\t * alias.log = show\n+\t\t */\n+\t\tif (done_alias || !handle_alias(argcp, argv))\n+\t\t\tbreak;\n+\t\tdone_alias = 1;\n+\t}\n+\n+\treturn done_alias;\n+}\n+\n \n int main(int argc, const char **argv)\n {\n \tconst char *cmd = argv[0] && *argv[0] ? argv[0] : \"git-help\";\n \tchar *slash = (char *)cmd + strlen(cmd);\n-\tint done_alias = 0;\n+\tint was_alias = 0;\n \n \t/*\n \t * Take the basename of argv[0] as the command\n@@ -478,32 +501,17 @@ int main(int argc, const char **argv)\n \t */\n \tsetup_path();\n \n-\twhile (1) {\n-\t\t/* See if it's an internal command */\n-\t\thandle_internal_command(argc, argv);\n-\n-\t\t/* .. then try the external ones */\n-\t\texecv_dashed_external(argv);\n-\n-\t\t/* It could be an alias -- this works around the insanity\n-\t\t * of overriding \"git log\" with \"git show\" by having\n-\t\t * alias.log = show\n-\t\t */\n-\t\tif (done_alias || !handle_alias(&argc, &argv))\n-\t\t\tbreak;\n-\t\tdone_alias = 1;\n-\t}\n+\twas_alias = run_argv(&argc, &argv);\n \n \tif (errno == ENOENT) {\n-\t\tif (done_alias) {\n+\t\tif (was_alias) {\n \t\t\tfprintf(stderr, \"Expansion of alias '%s' failed; \"\n \t\t\t\t\"'%s' is not a git-command\\n\",\n \t\t\t\tcmd, argv[0]);\n \t\t\texit(1);\n \t\t}\n \t\targv[0] = help_unknown_cmd(cmd);\n-\t\thandle_internal_command(argc, argv);\n-\t\texecv_dashed_external(argv);\n+\t\trun_argv(&argc, &argv);\n \t}\n \n \tfprintf(stderr, \"Failed to run command '%s': %s\\n\",\n-- \n1.6.1.62.g677ca\n"},{"id":"99311","messageId":"1231089128-12066-1-git-send-email-dato@net.com.org.es","threadId":"16984","inReplyTo":"1231088899-11943-1-git-send-email-dato@net.com.org.es","subject":"[PATCH v2] git.c: make autocorrected aliases work","fromName":"Adeodato Simó","fromEmail":"dato@net.com.org.es","sentAt":"2009-01-04T17:12:08Z","receivedAt":"2009-01-04T17:12:08Z","isPatch":true,"sender":{"key":"dato@net.com.org.es","avatar":"https://gravatar.com/avatar/952ec7d5d5663eb8baf631b5c37f9c58480a881920dd5f8a2d3a71f969b72b53?d=mp&s=160"},"body":"help_unknown_cmd() is able to autocorrect a command to an alias, and not\nonly to internal or external commands. However, main() was not passing the\nautocorrected command through handle_alias(), hence it failed if it was an\nalias.\n\nThis commit makes the autocorrected command go through handle_alias(), once\nhandle_internal_command() and execv_dashed_external() have been tried. Since\nthis is done twice in main() now, moved that logic to a new run_argv()\nfunction.\n\nAlso, print the same \"Expansion of alias 'x' failed\" message when the alias\nwas autocorrected, rather than a generic \"Failed to run command 'x'\".\n\nSigned-off-by: Adeodato Simó <dato@net.com.org.es>\n---\n\nHere's a version of the patch that improves the error reporting, in case\nthis is desired. With the previous patch 'aliasx' -> 'alias' -> 'enoent'\nprinted \"Failed to run command 'aliasx'\", now it correctly prints\n\"Expansion of alias 'alias' failed: 'enoent' is not a git-command\".\n\nThis is the incremental diff:\n\ndiff -u b/git.c b/git.c\n--- b/git.c\n+++ b/git.c\n@@ -444,7 +444,6 @@\n {\n \tconst char *cmd = argv[0] && *argv[0] ? argv[0] : \"git-help\";\n \tchar *slash = (char *)cmd + strlen(cmd);\n-\tint was_alias = 0;\n \n \t/*\n \t * Take the basename of argv[0] as the command\n@@ -501,17 +500,23 @@\n \t */\n \tsetup_path();\n \n-\twas_alias = run_argv(&argc, &argv);\n-\n-\tif (errno == ENOENT) {\n+\twhile (1) {\n+\t\tstatic int done_help = 0;\n+\t\tstatic int was_alias = 0;\n+\t\twas_alias = run_argv(&argc, &argv);\n+\t\tif (errno != ENOENT)\n+\t\t\tbreak;\n \t\tif (was_alias) {\n \t\t\tfprintf(stderr, \"Expansion of alias '%s' failed; \"\n \t\t\t\t\"'%s' is not a git-command\\n\",\n \t\t\t\tcmd, argv[0]);\n \t\t\texit(1);\n \t\t}\n-\t\targv[0] = help_unknown_cmd(cmd);\n-\t\trun_argv(&argc, &argv);\n+\t\tif (!done_help) {\n+\t\t\tcmd = argv[0] = help_unknown_cmd(cmd);\n+\t\t\tdone_help = 1;\n+\t\t} else\n+\t\t\tbreak;\n \t}\n \n \tfprintf(stderr, \"Failed to run command '%s': %s\\n\",\n\n git.c |   53 +++++++++++++++++++++++++++++++++--------------------\n 1 files changed, 33 insertions(+), 20 deletions(-)\n\ndiff --git a/git.c b/git.c\nindex e0d9071..ee331aa 100644\n--- a/git.c\n+++ b/git.c\n@@ -416,12 +416,34 @@ static void execv_dashed_external(const char **argv)\n \tstrbuf_release(&cmd);\n }\n \n+static int run_argv(int *argcp, const char ***argv)\n+{\n+\tint done_alias = 0;\n+\n+\twhile (1) {\n+\t\t/* See if it's an internal command */\n+\t\thandle_internal_command(*argcp, *argv);\n+\n+\t\t/* .. then try the external ones */\n+\t\texecv_dashed_external(*argv);\n+\n+\t\t/* It could be an alias -- this works around the insanity\n+\t\t * of overriding \"git log\" with \"git show\" by having\n+\t\t * alias.log = show\n+\t\t */\n+\t\tif (done_alias || !handle_alias(argcp, argv))\n+\t\t\tbreak;\n+\t\tdone_alias = 1;\n+\t}\n+\n+\treturn done_alias;\n+}\n+\n \n int main(int argc, const char **argv)\n {\n \tconst char *cmd = argv[0] && *argv[0] ? argv[0] : \"git-help\";\n \tchar *slash = (char *)cmd + strlen(cmd);\n-\tint done_alias = 0;\n \n \t/*\n \t * Take the basename of argv[0] as the command\n@@ -479,31 +501,22 @@ int main(int argc, const char **argv)\n \tsetup_path();\n \n \twhile (1) {\n-\t\t/* See if it's an internal command */\n-\t\thandle_internal_command(argc, argv);\n-\n-\t\t/* .. then try the external ones */\n-\t\texecv_dashed_external(argv);\n-\n-\t\t/* It could be an alias -- this works around the insanity\n-\t\t * of overriding \"git log\" with \"git show\" by having\n-\t\t * alias.log = show\n-\t\t */\n-\t\tif (done_alias || !handle_alias(&argc, &argv))\n+\t\tstatic int done_help = 0;\n+\t\tstatic int was_alias = 0;\n+\t\twas_alias = run_argv(&argc, &argv);\n+\t\tif (errno != ENOENT)\n \t\t\tbreak;\n-\t\tdone_alias = 1;\n-\t}\n-\n-\tif (errno == ENOENT) {\n-\t\tif (done_alias) {\n+\t\tif (was_alias) {\n \t\t\tfprintf(stderr, \"Expansion of alias '%s' failed; \"\n \t\t\t\t\"'%s' is not a git-command\\n\",\n \t\t\t\tcmd, argv[0]);\n \t\t\texit(1);\n \t\t}\n-\t\targv[0] = help_unknown_cmd(cmd);\n-\t\thandle_internal_command(argc, argv);\n-\t\texecv_dashed_external(argv);\n+\t\tif (!done_help) {\n+\t\t\tcmd = argv[0] = help_unknown_cmd(cmd);\n+\t\t\tdone_help = 1;\n+\t\t} else\n+\t\t\tbreak;\n \t}\n \n \tfprintf(stderr, \"Failed to run command '%s': %s\\n\",\n-- \n1.6.1.62.g677ca\n"},{"id":"99312","messageId":"1231089361-12619-1-git-send-email-dato@net.com.org.es","threadId":"16984","inReplyTo":"1231089128-12066-1-git-send-email-dato@net.com.org.es","subject":"[PATCH v2 resend] git.c: make autocorrected aliases work","fromName":"Adeodato Simó","fromEmail":"dato@net.com.org.es","sentAt":"2009-01-04T17:16:01Z","receivedAt":"2009-01-04T17:16:01Z","isPatch":true,"sender":{"key":"dato@net.com.org.es","avatar":"https://gravatar.com/avatar/952ec7d5d5663eb8baf631b5c37f9c58480a881920dd5f8a2d3a71f969b72b53?d=mp&s=160"},"body":"help_unknown_cmd() is able to autocorrect a command to an alias, and not\nonly to internal or external commands. However, main() was not passing the\nautocorrected command through handle_alias(), hence it failed if it was an\nalias.\n\nThis commit makes the autocorrected command go through handle_alias(), once\nhandle_internal_command() and execv_dashed_external() have been tried. Since\nthis is done twice in main() now, moved that logic to a new run_argv()\nfunction.\n\nAlso, print the same \"Expansion of alias 'x' failed\" message when the alias\nwas autocorrected, rather than a generic \"Failed to run command 'x'\".\n\nSigned-off-by: Adeodato Simó <dato@net.com.org.es>\n---\n\nMeh, I didn't realize that by attaching an incremental diff, I'd break\n`git am`. Sorry about that.\n\n git.c |   53 +++++++++++++++++++++++++++++++++--------------------\n 1 files changed, 33 insertions(+), 20 deletions(-)\n\ndiff --git a/git.c b/git.c\nindex e0d9071..ee331aa 100644\n--- a/git.c\n+++ b/git.c\n@@ -416,12 +416,34 @@ static void execv_dashed_external(const char **argv)\n \tstrbuf_release(&cmd);\n }\n \n+static int run_argv(int *argcp, const char ***argv)\n+{\n+\tint done_alias = 0;\n+\n+\twhile (1) {\n+\t\t/* See if it's an internal command */\n+\t\thandle_internal_command(*argcp, *argv);\n+\n+\t\t/* .. then try the external ones */\n+\t\texecv_dashed_external(*argv);\n+\n+\t\t/* It could be an alias -- this works around the insanity\n+\t\t * of overriding \"git log\" with \"git show\" by having\n+\t\t * alias.log = show\n+\t\t */\n+\t\tif (done_alias || !handle_alias(argcp, argv))\n+\t\t\tbreak;\n+\t\tdone_alias = 1;\n+\t}\n+\n+\treturn done_alias;\n+}\n+\n \n int main(int argc, const char **argv)\n {\n \tconst char *cmd = argv[0] && *argv[0] ? argv[0] : \"git-help\";\n \tchar *slash = (char *)cmd + strlen(cmd);\n-\tint done_alias = 0;\n \n \t/*\n \t * Take the basename of argv[0] as the command\n@@ -479,31 +501,22 @@ int main(int argc, const char **argv)\n \tsetup_path();\n \n \twhile (1) {\n-\t\t/* See if it's an internal command */\n-\t\thandle_internal_command(argc, argv);\n-\n-\t\t/* .. then try the external ones */\n-\t\texecv_dashed_external(argv);\n-\n-\t\t/* It could be an alias -- this works around the insanity\n-\t\t * of overriding \"git log\" with \"git show\" by having\n-\t\t * alias.log = show\n-\t\t */\n-\t\tif (done_alias || !handle_alias(&argc, &argv))\n+\t\tstatic int done_help = 0;\n+\t\tstatic int was_alias = 0;\n+\t\twas_alias = run_argv(&argc, &argv);\n+\t\tif (errno != ENOENT)\n \t\t\tbreak;\n-\t\tdone_alias = 1;\n-\t}\n-\n-\tif (errno == ENOENT) {\n-\t\tif (done_alias) {\n+\t\tif (was_alias) {\n \t\t\tfprintf(stderr, \"Expansion of alias '%s' failed; \"\n \t\t\t\t\"'%s' is not a git-command\\n\",\n \t\t\t\tcmd, argv[0]);\n \t\t\texit(1);\n \t\t}\n-\t\targv[0] = help_unknown_cmd(cmd);\n-\t\thandle_internal_command(argc, argv);\n-\t\texecv_dashed_external(argv);\n+\t\tif (!done_help) {\n+\t\t\tcmd = argv[0] = help_unknown_cmd(cmd);\n+\t\t\tdone_help = 1;\n+\t\t} else\n+\t\t\tbreak;\n \t}\n \n \tfprintf(stderr, \"Failed to run command '%s': %s\\n\",\n-- \n1.6.1.62.g677ca\n"},{"id":"99313","messageId":"20090104172833.GA7139@myhost","threadId":"16984","inReplyTo":"1231089361-12619-1-git-send-email-dato@net.com.org.es","subject":"Re: [PATCH v2 resend] git.c: make autocorrected aliases work","fromName":"Alexander Potashev","fromEmail":"aspotashev@gmail.com","sentAt":"2009-01-04T17:28:33Z","receivedAt":"2009-01-04T17:28:33Z","isPatch":true,"sender":{"key":"aspotashev@gmail.com","avatar":null},"body":"On 18:16 Sun 04 Jan     , Adeodato Simó wrote:\n> help_unknown_cmd() is able to autocorrect a command to an alias, and not\n> only to internal or external commands. However, main() was not passing the\n> autocorrected command through handle_alias(), hence it failed if it was an\n> alias.\n> \n> This commit makes the autocorrected command go through handle_alias(), once\n> handle_internal_command() and execv_dashed_external() have been tried. Since\n> this is done twice in main() now, moved that logic to a new run_argv()\n> function.\n> \n> Also, print the same \"Expansion of alias 'x' failed\" message when the alias\n> was autocorrected, rather than a generic \"Failed to run command 'x'\".\n> \n> Signed-off-by: Adeodato Simó <dato@net.com.org.es>\n> ---\n> \n> Meh, I didn't realize that by attaching an incremental diff, I'd break\n> `git am`. Sorry about that.\n> \n>  git.c |   53 +++++++++++++++++++++++++++++++++--------------------\n>  1 files changed, 33 insertions(+), 20 deletions(-)\n> \n> diff --git a/git.c b/git.c\n> index e0d9071..ee331aa 100644\n> --- a/git.c\n> +++ b/git.c\n> @@ -416,12 +416,34 @@ static void execv_dashed_external(const char **argv)\n>  \tstrbuf_release(&cmd);\n>  }\n>  \n> +static int run_argv(int *argcp, const char ***argv)\n> +{\n> +\tint done_alias = 0;\n> +\n> +\twhile (1) {\n> +\t\t/* See if it's an internal command */\n> +\t\thandle_internal_command(*argcp, *argv);\n> +\n> +\t\t/* .. then try the external ones */\n> +\t\texecv_dashed_external(*argv);\n> +\n> +\t\t/* It could be an alias -- this works around the insanity\n> +\t\t * of overriding \"git log\" with \"git show\" by having\n> +\t\t * alias.log = show\n> +\t\t */\n> +\t\tif (done_alias || !handle_alias(argcp, argv))\n> +\t\t\tbreak;\n> +\t\tdone_alias = 1;\n> +\t}\n> +\n> +\treturn done_alias;\n> +}\n> +\n>  \n>  int main(int argc, const char **argv)\n>  {\n>  \tconst char *cmd = argv[0] && *argv[0] ? argv[0] : \"git-help\";\n>  \tchar *slash = (char *)cmd + strlen(cmd);\n> -\tint done_alias = 0;\n>  \n>  \t/*\n>  \t * Take the basename of argv[0] as the command\n> @@ -479,31 +501,22 @@ int main(int argc, const char **argv)\n>  \tsetup_path();\n>  \n>  \twhile (1) {\n> -\t\t/* See if it's an internal command */\n> -\t\thandle_internal_command(argc, argv);\n> -\n> -\t\t/* .. then try the external ones */\n> -\t\texecv_dashed_external(argv);\n> -\n> -\t\t/* It could be an alias -- this works around the insanity\n> -\t\t * of overriding \"git log\" with \"git show\" by having\n> -\t\t * alias.log = show\n> -\t\t */\n> -\t\tif (done_alias || !handle_alias(&argc, &argv))\n> +\t\tstatic int done_help = 0;\n> +\t\tstatic int was_alias = 0;\n> +\t\twas_alias = run_argv(&argc, &argv);\n> +\t\tif (errno != ENOENT)\n>  \t\t\tbreak;\n> -\t\tdone_alias = 1;\n> -\t}\n> -\n> -\tif (errno == ENOENT) {\n> -\t\tif (done_alias) {\n> +\t\tif (was_alias) {\n>  \t\t\tfprintf(stderr, \"Expansion of alias '%s' failed; \"\n>  \t\t\t\t\"'%s' is not a git-command\\n\",\n>  \t\t\t\tcmd, argv[0]);\n>  \t\t\texit(1);\n\nWhy not using 'die' here?\n\n\t\tdie(\"Expansion of alias '%s' failed;\n\t\t\t'%s' is not a git-command\",\n  \t\t\tcmd, argv[0]);\n\nDISCLAIMER: I have never used git's 'die'\n\n>  \t\t}\n> -\t\targv[0] = help_unknown_cmd(cmd);\n> -\t\thandle_internal_command(argc, argv);\n> -\t\texecv_dashed_external(argv);\n> +\t\tif (!done_help) {\n> +\t\t\tcmd = argv[0] = help_unknown_cmd(cmd);\n> +\t\t\tdone_help = 1;\n> +\t\t} else\n> +\t\t\tbreak;\n>  \t}\n>  \n>  \tfprintf(stderr, \"Failed to run command '%s': %s\\n\",\n> -- \n> 1.6.1.62.g677ca\n"},{"id":"99440","messageId":"7vd4f0kft3.fsf@gitster.siamese.dyndns.org","threadId":"16984","inReplyTo":"1231089361-12619-1-git-send-email-dato@net.com.org.es","subject":"Re: [PATCH v2 resend] git.c: make autocorrected aliases work","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-01-06T08:19:04Z","receivedAt":"2009-01-06T08:19:04Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thanks, queued.\n"},{"id":"99441","messageId":"7v7i58kfsy.fsf@gitster.siamese.dyndns.org","threadId":"16984","inReplyTo":"20090104172833.GA7139@myhost","subject":"Re: [PATCH v2 resend] git.c: make autocorrected aliases work","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-01-06T08:19:09Z","receivedAt":"2009-01-06T08:19:09Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Alexander Potashev <aspotashev@gmail.com> writes:\n\n>> @@ -479,31 +501,22 @@ int main(int argc, const char **argv)\n>> ...\n>> +\t\twas_alias = run_argv(&argc, &argv);\n>> +\t\tif (errno != ENOENT)\n>>  \t\t\tbreak;\n>> +\t\tif (was_alias) {\n>>  \t\t\tfprintf(stderr, \"Expansion of alias '%s' failed; \"\n>>  \t\t\t\t\"'%s' is not a git-command\\n\",\n>>  \t\t\t\tcmd, argv[0]);\n>>  \t\t\texit(1);\n>\n> Why not using 'die' here?\n\nThe code is in the context, and I do not think it is a good idea to\nconflate such a change to a patch that wants to add aliases auto\ncorrection.\n\nWhile I do not think it matters too much in practice (unless existing\nscripts that runs git depends on the exact error status value), there are\ntwo differences: the message will say \"fatal: \" in front, and the command\nexits with 128 not with 1.\n"}]}