{"thread":{"id":"10456","subject":"[PATCH 1/7] \"git\" calls help_unknown_cmd(\"\"); \"git help\" and \"git help -a\" return 0","startedAt":"2007-10-25T03:37:11Z","lastAt":"2007-10-27T07:16:32Z","messageCount":19,"participants":["Scott R Parish","Junio C Hamano","Scott Parish"],"isPatch":true,"patchVersion":1,"patchTotal":7},"messages":[{"id":"57124","messageId":"1193283437-1706-1-git-send-email-srp@srparish.net","threadId":"10456","inReplyTo":null,"subject":"[PATCH 1/7] \"git\" calls help_unknown_cmd(\"\"); \"git help\" and \"git help -a\" return 0","fromName":"Scott R Parish","fromEmail":"srp@srparish.net","sentAt":"2007-10-25T03:37:11Z","receivedAt":"2007-10-25T03:37:11Z","isPatch":true,"sender":{"key":"srp@srparish.net","avatar":"https://gravatar.com/avatar/870e5b6fc4f710cf4db5684bd9af7f2cee5734b3dab3209b13e00cf64f6c9f0e?d=mp&s=160"},"body":"Signed-off-by: Scott R Parish <srp@srparish.net>\n---\n git.c  |    5 ++---\n help.c |    4 ++--\n 2 files changed, 4 insertions(+), 5 deletions(-)\n\ndiff --git a/git.c b/git.c\nindex 853e66c..e1c99e3 100644\n--- a/git.c\n+++ b/git.c\n@@ -445,9 +445,8 @@ int main(int argc, const char **argv)\n \t\tif (!prefixcmp(argv[0], \"--\"))\n \t\t\targv[0] += 2;\n \t} else {\n-\t\t/* Default command: \"help\" */\n-\t\targv[0] = \"help\";\n-\t\targc = 1;\n+\t\t/* The user didn't specify a command; give them help */\n+\t\thelp_unknown_cmd(\"\");\n \t}\n \tcmd = argv[0];\n \ndiff --git a/help.c b/help.c\nindex 1cd33ec..b0d2dd4 100644\n--- a/help.c\n+++ b/help.c\n@@ -204,14 +204,14 @@ int cmd_help(int argc, const char **argv, const char *prefix)\n \tif (!help_cmd) {\n \t\tprintf(\"usage: %s\\n\\n\", git_usage_string);\n \t\tlist_common_cmds_help();\n-\t\texit(1);\n+\t\texit(0);\n \t}\n \n \telse if (!strcmp(help_cmd, \"--all\") || !strcmp(help_cmd, \"-a\")) {\n \t\tprintf(\"usage: %s\\n\\n\", git_usage_string);\n \t\tif(exec_path)\n \t\t\tlist_commands(exec_path, \"git-*\");\n-\t\texit(1);\n+\t\texit(0);\n \t}\n \n \telse\n-- \ngitgui.0.8.4.11176.gd9205-dirty\n"},{"id":"57126","messageId":"1193283437-1706-2-git-send-email-srp@srparish.net","threadId":"10456","inReplyTo":"1193283437-1706-1-git-send-email-srp@srparish.net","subject":"[PATCH 2/7] s/pattern/prefix/ in help's list_commands","fromName":"Scott R Parish","fromEmail":"srp@srparish.net","sentAt":"2007-10-25T03:37:12Z","receivedAt":"2007-10-25T03:37:12Z","isPatch":true,"sender":{"key":"srp@srparish.net","avatar":"https://gravatar.com/avatar/870e5b6fc4f710cf4db5684bd9af7f2cee5734b3dab3209b13e00cf64f6c9f0e?d=mp&s=160"},"body":"list_commands() currently accepts and ignores a \"pattern\" argument,\nand then hard codes a prefix as well as some magic numbers. This\nrenames the arg from pattern to prefix and uses that instead of the\nhardcoded stuff.\n\nSigned-off-by: Scott R Parish <srp@srparish.net>\n---\n help.c |   13 +++++++------\n 1 files changed, 7 insertions(+), 6 deletions(-)\n\ndiff --git a/help.c b/help.c\nindex b0d2dd4..950f62d 100644\n--- a/help.c\n+++ b/help.c\n@@ -93,11 +93,12 @@ static void pretty_print_string_list(struct cmdname **cmdname, int longest)\n \t}\n }\n \n-static void list_commands(const char *exec_path, const char *pattern)\n+static void list_commands(const char *exec_path, const char *prefix)\n {\n \tunsigned int longest = 0;\n \tchar path[PATH_MAX];\n \tint dirlen;\n+\tint prefix_len = strlen(prefix);\n \tDIR *dir = opendir(exec_path);\n \tstruct dirent *de;\n \n@@ -120,7 +121,7 @@ static void list_commands(const char *exec_path, const char *pattern)\n \t\tstruct stat st;\n \t\tint entlen;\n \n-\t\tif (prefixcmp(de->d_name, \"git-\"))\n+\t\tif (prefixcmp(de->d_name, prefix))\n \t\t\tcontinue;\n \t\tstrcpy(path+dirlen, de->d_name);\n \t\tif (stat(path, &st) || /* stat, not lstat */\n@@ -128,14 +129,14 @@ static void list_commands(const char *exec_path, const char *pattern)\n \t\t    !(st.st_mode & S_IXUSR))\n \t\t\tcontinue;\n \n-\t\tentlen = strlen(de->d_name);\n+\t\tentlen = strlen(de->d_name) - prefix_len;\n \t\tif (has_extension(de->d_name, \".exe\"))\n \t\t\tentlen -= 4;\n \n \t\tif (longest < entlen)\n \t\t\tlongest = entlen;\n \n-\t\tadd_cmdname(de->d_name + 4, entlen-4);\n+\t\tadd_cmdname(de->d_name + prefix_len, entlen);\n \t}\n \tclosedir(dir);\n \n@@ -143,7 +144,7 @@ static void list_commands(const char *exec_path, const char *pattern)\n \tprintf(\"----------------------------\");\n \tmput_char('-', strlen(exec_path));\n \tputchar('\\n');\n-\tpretty_print_string_list(cmdname, longest - 4);\n+\tpretty_print_string_list(cmdname, longest);\n \tputchar('\\n');\n }\n \n@@ -210,7 +211,7 @@ int cmd_help(int argc, const char **argv, const char *prefix)\n \telse if (!strcmp(help_cmd, \"--all\") || !strcmp(help_cmd, \"-a\")) {\n \t\tprintf(\"usage: %s\\n\\n\", git_usage_string);\n \t\tif(exec_path)\n-\t\t\tlist_commands(exec_path, \"git-*\");\n+\t\t\tlist_commands(exec_path, \"git-\");\n \t\texit(0);\n \t}\n \n-- \ngitgui.0.8.4.11176.gd9205-dirty\n"},{"id":"57127","messageId":"1193283437-1706-3-git-send-email-srp@srparish.net","threadId":"10456","inReplyTo":"1193283437-1706-2-git-send-email-srp@srparish.net","subject":"[PATCH 3/7] \"current_exec_path\" is a misleading name, use \"argv_exec_path\" Signed-off-by: Scott R Parish <srp@srparish.net>","fromName":"Scott R Parish","fromEmail":"srp@srparish.net","sentAt":"2007-10-25T03:37:13Z","receivedAt":"2007-10-25T03:37:13Z","isPatch":true,"sender":{"key":"srp@srparish.net","avatar":"https://gravatar.com/avatar/870e5b6fc4f710cf4db5684bd9af7f2cee5734b3dab3209b13e00cf64f6c9f0e?d=mp&s=160"},"body":"---\n exec_cmd.c |   12 ++++++------\n exec_cmd.h |    2 +-\n git.c      |    2 +-\n 3 files changed, 8 insertions(+), 8 deletions(-)\n\ndiff --git a/exec_cmd.c b/exec_cmd.c\nindex 9b74ed2..8b681d0 100644\n--- a/exec_cmd.c\n+++ b/exec_cmd.c\n@@ -5,11 +5,11 @@\n \n extern char **environ;\n static const char *builtin_exec_path = GIT_EXEC_PATH;\n-static const char *current_exec_path;\n+static const char *argv_exec_path = 0;\n \n-void git_set_exec_path(const char *exec_path)\n+void git_set_argv_exec_path(const char *exec_path)\n {\n-\tcurrent_exec_path = exec_path;\n+\targv_exec_path = exec_path;\n }\n \n \n@@ -18,8 +18,8 @@ const char *git_exec_path(void)\n {\n \tconst char *env;\n \n-\tif (current_exec_path)\n-\t\treturn current_exec_path;\n+\tif (argv_exec_path)\n+\t\treturn argv_exec_path;\n \n \tenv = getenv(EXEC_PATH_ENVIRONMENT);\n \tif (env && *env) {\n@@ -34,7 +34,7 @@ int execv_git_cmd(const char **argv)\n {\n \tchar git_command[PATH_MAX + 1];\n \tint i;\n-\tconst char *paths[] = { current_exec_path,\n+\tconst char *paths[] = { argv_exec_path,\n \t\t\t\tgetenv(EXEC_PATH_ENVIRONMENT),\n \t\t\t\tbuiltin_exec_path };\n \ndiff --git a/exec_cmd.h b/exec_cmd.h\nindex 849a839..da99287 100644\n--- a/exec_cmd.h\n+++ b/exec_cmd.h\n@@ -1,7 +1,7 @@\n #ifndef GIT_EXEC_CMD_H\n #define GIT_EXEC_CMD_H\n \n-extern void git_set_exec_path(const char *exec_path);\n+extern void git_set_argv_exec_path(const char *exec_path);\n extern const char* git_exec_path(void);\n extern int execv_git_cmd(const char **argv); /* NULL terminated */\n extern int execl_git_cmd(const char *cmd, ...);\ndiff --git a/git.c b/git.c\nindex e1c99e3..f659338 100644\n--- a/git.c\n+++ b/git.c\n@@ -51,7 +51,7 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)\n \t\tif (!prefixcmp(cmd, \"--exec-path\")) {\n \t\t\tcmd += 11;\n \t\t\tif (*cmd == '=')\n-\t\t\t\tgit_set_exec_path(cmd + 1);\n+\t\t\t\tgit_set_argv_exec_path(cmd + 1);\n \t\t\telse {\n \t\t\t\tputs(git_exec_path());\n \t\t\t\texit(0);\n-- \ngitgui.0.8.4.11176.gd9205-dirty\n"},{"id":"57128","messageId":"1193283437-1706-4-git-send-email-srp@srparish.net","threadId":"10456","inReplyTo":"1193283437-1706-3-git-send-email-srp@srparish.net","subject":"[PATCH 4/7] use only the PATH for exec'ing git commands","fromName":"Scott R Parish","fromEmail":"srp@srparish.net","sentAt":"2007-10-25T03:37:14Z","receivedAt":"2007-10-25T03:37:14Z","isPatch":true,"sender":{"key":"srp@srparish.net","avatar":"https://gravatar.com/avatar/870e5b6fc4f710cf4db5684bd9af7f2cee5734b3dab3209b13e00cf64f6c9f0e?d=mp&s=160"},"body":"We need to correctly set up PATH for non-c based git commands. Since we\nalready do this, we can just use that PATH and execvp, instead of looping\nover the paths with execve.\n\nThis patch adds a setup_path() function to exec_cmd.c, which sets\nthe PATH order correctly for our search order. execv_git_cmd() is\nstripped down to setting up argv and calling execvp(). git.c's main()\nonly only needs to call setup_path().\n\nSigned-off-by: Scott R Parish <srp@srparish.net>\n---\n exec_cmd.c |  121 ++++++++++++++++++++++++++----------------------------------\n exec_cmd.h |    1 +\n git.c      |   43 +++------------------\n 3 files changed, 60 insertions(+), 105 deletions(-)\n\ndiff --git a/exec_cmd.c b/exec_cmd.c\nindex 8b681d0..c228dbf 100644\n--- a/exec_cmd.c\n+++ b/exec_cmd.c\n@@ -29,85 +29,68 @@ const char *git_exec_path(void)\n \treturn builtin_exec_path;\n }\n \n+static void add_path(struct strbuf *out, const char *path)\n+{\n+\tif (path && strlen(path)) {\n+\t\tif (is_absolute_path(path))\n+\t\t\tstrbuf_addstr(out, path);\n+\t\telse\n+\t\t\tstrbuf_addstr(out, make_absolute_path(path));\n+\n+\t\tstrbuf_addch(out, ':');\n+\t}\n+}\n+\n+void setup_path(const char *cmd_path)\n+{\n+\tconst char *old_path = getenv(\"PATH\");\n+\tstruct strbuf new_path;\n+\n+\tstrbuf_init(&new_path, 0);\n+\n+\tadd_path(&new_path, argv_exec_path);\n+\tadd_path(&new_path, getenv(EXEC_PATH_ENVIRONMENT));\n+\tadd_path(&new_path, builtin_exec_path);\n+\tadd_path(&new_path, cmd_path);\n+\n+\tif (old_path)\n+\t\tstrbuf_addstr(&new_path, old_path);\n+\telse\n+\t\tstrbuf_addstr(&new_path, \"/usr/local/bin:/usr/bin:/bin\");\n+\n+\tsetenv(\"PATH\", new_path.buf, 1);\n+\n+\tstrbuf_release(&new_path);\n+}\n \n int execv_git_cmd(const char **argv)\n {\n-\tchar git_command[PATH_MAX + 1];\n-\tint i;\n-\tconst char *paths[] = { argv_exec_path,\n-\t\t\t\tgetenv(EXEC_PATH_ENVIRONMENT),\n-\t\t\t\tbuiltin_exec_path };\n-\n-\tfor (i = 0; i < ARRAY_SIZE(paths); ++i) {\n-\t\tsize_t len;\n-\t\tint rc;\n-\t\tconst char *exec_dir = paths[i];\n-\t\tconst char *tmp;\n-\n-\t\tif (!exec_dir || !*exec_dir) continue;\n-\n-\t\tif (*exec_dir != '/') {\n-\t\t\tif (!getcwd(git_command, sizeof(git_command))) {\n-\t\t\t\tfprintf(stderr, \"git: cannot determine \"\n-\t\t\t\t\t\"current directory: %s\\n\",\n-\t\t\t\t\tstrerror(errno));\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t\tlen = strlen(git_command);\n-\n-\t\t\t/* Trivial cleanup */\n-\t\t\twhile (!prefixcmp(exec_dir, \"./\")) {\n-\t\t\t\texec_dir += 2;\n-\t\t\t\twhile (*exec_dir == '/')\n-\t\t\t\t\texec_dir++;\n-\t\t\t}\n-\n-\t\t\trc = snprintf(git_command + len,\n-\t\t\t\t      sizeof(git_command) - len, \"/%s\",\n-\t\t\t\t      exec_dir);\n-\t\t\tif (rc < 0 || rc >= sizeof(git_command) - len) {\n-\t\t\t\tfprintf(stderr, \"git: command name given \"\n-\t\t\t\t\t\"is too long.\\n\");\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t} else {\n-\t\t\tif (strlen(exec_dir) + 1 > sizeof(git_command)) {\n-\t\t\t\tfprintf(stderr, \"git: command name given \"\n-\t\t\t\t\t\"is too long.\\n\");\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t\tstrcpy(git_command, exec_dir);\n-\t\t}\n-\n-\t\tlen = strlen(git_command);\n-\t\trc = snprintf(git_command + len, sizeof(git_command) - len,\n-\t\t\t      \"/git-%s\", argv[0]);\n-\t\tif (rc < 0 || rc >= sizeof(git_command) - len) {\n-\t\t\tfprintf(stderr,\n-\t\t\t\t\"git: command name given is too long.\\n\");\n-\t\t\tbreak;\n-\t\t}\n+\tstruct strbuf cmd;\n+\tconst char *tmp;\n \n-\t\t/* argv[0] must be the git command, but the argv array\n-\t\t * belongs to the caller, and my be reused in\n-\t\t * subsequent loop iterations. Save argv[0] and\n-\t\t * restore it on error.\n-\t\t */\n+\tstrbuf_init(&cmd, 0);\n+\tstrbuf_addf(&cmd, \"git-%s\", argv[0]);\n \n-\t\ttmp = argv[0];\n-\t\targv[0] = git_command;\n+\t/* argv[0] must be the git command, but the argv array\n+\t * belongs to the caller, and my be reused in\n+\t * subsequent loop iterations. Save argv[0] and\n+\t * restore it on error.\n+\t */\n+\ttmp = argv[0];\n+\targv[0] = cmd.buf;\n \n-\t\ttrace_argv_printf(argv, -1, \"trace: exec:\");\n+\ttrace_argv_printf(argv, -1, \"trace: exec:\");\n \n-\t\t/* execve() can only ever return if it fails */\n-\t\texecve(git_command, (char **)argv, environ);\n+\t/* execvp() can only ever return if it fails */\n+\texecvp(cmd.buf, (char **)argv);\n \n-\t\ttrace_printf(\"trace: exec failed: %s\\n\", strerror(errno));\n+\ttrace_printf(\"trace: exec failed: %s\\n\", strerror(errno));\n \n-\t\targv[0] = tmp;\n-\t}\n-\treturn -1;\n+\targv[0] = tmp;\n \n+\tstrbuf_release(&cmd);\n+\n+\treturn -1;\n }\n \n \ndiff --git a/exec_cmd.h b/exec_cmd.h\nindex da99287..a892355 100644\n--- a/exec_cmd.h\n+++ b/exec_cmd.h\n@@ -3,6 +3,7 @@\n \n extern void git_set_argv_exec_path(const char *exec_path);\n extern const char* git_exec_path(void);\n+extern void setup_path(const char *);\n extern int execv_git_cmd(const char **argv); /* NULL terminated */\n extern int execl_git_cmd(const char *cmd, ...);\n \ndiff --git a/git.c b/git.c\nindex f659338..a639e42 100644\n--- a/git.c\n+++ b/git.c\n@@ -6,28 +6,6 @@\n const char git_usage_string[] =\n \t\"git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]\";\n \n-static void prepend_to_path(const char *dir, int len)\n-{\n-\tconst char *old_path = getenv(\"PATH\");\n-\tchar *path;\n-\tint path_len = len;\n-\n-\tif (!old_path)\n-\t\told_path = \"/usr/local/bin:/usr/bin:/bin\";\n-\n-\tpath_len = len + strlen(old_path) + 1;\n-\n-\tpath = xmalloc(path_len + 1);\n-\n-\tmemcpy(path, dir, len);\n-\tpath[len] = ':';\n-\tmemcpy(path + len + 1, old_path, path_len - len);\n-\n-\tsetenv(\"PATH\", path, 1);\n-\n-\tfree(path);\n-}\n-\n static int handle_options(const char*** argv, int* argc, int* envchanged)\n {\n \tint handled = 0;\n@@ -403,7 +381,7 @@ int main(int argc, const char **argv)\n {\n \tconst char *cmd = argv[0] ? argv[0] : \"git-help\";\n \tchar *slash = strrchr(cmd, '/');\n-\tconst char *exec_path = NULL;\n+\tconst char *cmd_path = NULL;\n \tint done_alias = 0;\n \n \t/*\n@@ -413,10 +391,7 @@ int main(int argc, const char **argv)\n \t */\n \tif (slash) {\n \t\t*slash++ = 0;\n-\t\tif (*cmd == '/')\n-\t\t\texec_path = cmd;\n-\t\telse\n-\t\t\texec_path = xstrdup(make_absolute_path(cmd));\n+\t\tcmd_path = cmd;\n \t\tcmd = slash;\n \t}\n \n@@ -451,16 +426,12 @@ int main(int argc, const char **argv)\n \tcmd = argv[0];\n \n \t/*\n-\t * We execute external git command via execv_git_cmd(),\n-\t * which looks at \"--exec-path\" option, GIT_EXEC_PATH\n-\t * environment, and $(gitexecdir) in Makefile while built,\n-\t * in this order.  For scripted commands, we prepend\n-\t * the value of the exec_path variable to the PATH.\n+\t * We use PATH to find git commands, but we prepend some higher\n+\t * precidence paths: the \"--exec-path\" option, the GIT_EXEC_PATH\n+\t * environment, and the $(gitexecdir) from the Makefile at build\n+\t * time.\n \t */\n-\tif (exec_path)\n-\t\tprepend_to_path(exec_path, strlen(exec_path));\n-\texec_path = git_exec_path();\n-\tprepend_to_path(exec_path, strlen(exec_path));\n+\tsetup_path(cmd_path);\n \n \twhile (1) {\n \t\t/* See if it's an internal command */\n-- \ngitgui.0.8.4.11176.gd9205-dirty\n"},{"id":"57129","messageId":"1193283437-1706-5-git-send-email-srp@srparish.net","threadId":"10456","inReplyTo":"1193283437-1706-4-git-send-email-srp@srparish.net","subject":"[PATCH 5/7] chdir() into list_commands() dir instead of building paths for stat()","fromName":"Scott R Parish","fromEmail":"srp@srparish.net","sentAt":"2007-10-25T03:37:15Z","receivedAt":"2007-10-25T03:37:15Z","isPatch":true,"sender":{"key":"srp@srparish.net","avatar":"https://gravatar.com/avatar/870e5b6fc4f710cf4db5684bd9af7f2cee5734b3dab3209b13e00cf64f6c9f0e?d=mp&s=160"},"body":"Signed-off-by: Scott R Parish <srp@srparish.net>\n---\n help.c |   18 +++---------------\n 1 files changed, 3 insertions(+), 15 deletions(-)\n\ndiff --git a/help.c b/help.c\nindex 950f62d..906f8f6 100644\n--- a/help.c\n+++ b/help.c\n@@ -96,35 +96,23 @@ static void pretty_print_string_list(struct cmdname **cmdname, int longest)\n static void list_commands(const char *exec_path, const char *prefix)\n {\n \tunsigned int longest = 0;\n-\tchar path[PATH_MAX];\n-\tint dirlen;\n \tint prefix_len = strlen(prefix);\n \tDIR *dir = opendir(exec_path);\n \tstruct dirent *de;\n \n-\tif (!dir) {\n+\tif (!dir || chdir(exec_path)) {\n \t\tfprintf(stderr, \"git: '%s': %s\\n\", exec_path, strerror(errno));\n \t\texit(1);\n \t}\n \n-\tdirlen = strlen(exec_path);\n-\tif (PATH_MAX - 20 < dirlen) {\n-\t\tfprintf(stderr, \"git: insanely long exec-path '%s'\\n\",\n-\t\t\texec_path);\n-\t\texit(1);\n-\t}\n-\n-\tmemcpy(path, exec_path, dirlen);\n-\tpath[dirlen++] = '/';\n-\n \twhile ((de = readdir(dir)) != NULL) {\n \t\tstruct stat st;\n \t\tint entlen;\n \n \t\tif (prefixcmp(de->d_name, prefix))\n \t\t\tcontinue;\n-\t\tstrcpy(path+dirlen, de->d_name);\n-\t\tif (stat(path, &st) || /* stat, not lstat */\n+\n+\t\tif (stat(de->d_name, &st) || /* stat, not lstat */\n \t\t    !S_ISREG(st.st_mode) ||\n \t\t    !(st.st_mode & S_IXUSR))\n \t\t\tcontinue;\n-- \ngitgui.0.8.4.11176.gd9205-dirty\n"},{"id":"57125","messageId":"1193283437-1706-6-git-send-email-srp@srparish.net","threadId":"10456","inReplyTo":"1193283437-1706-5-git-send-email-srp@srparish.net","subject":"[PATCH 6/7] walk PATH to generate list of commands for \"help -a\"","fromName":"Scott R Parish","fromEmail":"srp@srparish.net","sentAt":"2007-10-25T03:37:16Z","receivedAt":"2007-10-25T03:37:16Z","isPatch":true,"sender":{"key":"srp@srparish.net","avatar":"https://gravatar.com/avatar/870e5b6fc4f710cf4db5684bd9af7f2cee5734b3dab3209b13e00cf64f6c9f0e?d=mp&s=160"},"body":"Signed-off-by: Scott R Parish <srp@srparish.net>\n---\n help.c |   69 ++++++++++++++++++++++++++++++++++++++++++++++++---------------\n 1 files changed, 52 insertions(+), 17 deletions(-)\n\ndiff --git a/help.c b/help.c\nindex 906f8f6..3f8b4aa 100644\n--- a/help.c\n+++ b/help.c\n@@ -64,6 +64,19 @@ static int cmdname_compare(const void *a_, const void *b_)\n \treturn strcmp(a->name, b->name);\n }\n \n+static void uniq(struct cmdname **cmdname)\n+{\n+\tint i, j;\n+\n+\tfor (i = j = 1; i < cmdname_cnt; i++) {\n+\t\tif (strcmp(cmdname[i]->name, cmdname[i-1]->name)) {\n+\t\t\tcmdname[j++] = cmdname[i];\n+\t\t}\n+\t}\n+\n+\tcmdname_cnt = j;\n+}\n+\n static void pretty_print_string_list(struct cmdname **cmdname, int longest)\n {\n \tint cols = 1, rows;\n@@ -71,12 +84,13 @@ static void pretty_print_string_list(struct cmdname **cmdname, int longest)\n \tint max_cols = term_columns() - 1; /* don't print *on* the edge */\n \tint i, j;\n \n+\tqsort(cmdname, cmdname_cnt, sizeof(*cmdname), cmdname_compare);\n+\tuniq(cmdname);\n+\n \tif (space < max_cols)\n \t\tcols = max_cols / space;\n \trows = (cmdname_cnt + cols - 1) / cols;\n \n-\tqsort(cmdname, cmdname_cnt, sizeof(*cmdname), cmdname_compare);\n-\n \tfor (i = 0; i < rows; i++) {\n \t\tprintf(\"  \");\n \n@@ -93,19 +107,17 @@ static void pretty_print_string_list(struct cmdname **cmdname, int longest)\n \t}\n }\n \n-static void list_commands(const char *exec_path, const char *prefix)\n+static unsigned int list_commands_in_dir(const char *dir, const char *prefix)\n {\n \tunsigned int longest = 0;\n \tint prefix_len = strlen(prefix);\n-\tDIR *dir = opendir(exec_path);\n+\tDIR *dirp = opendir(dir);\n \tstruct dirent *de;\n \n-\tif (!dir || chdir(exec_path)) {\n-\t\tfprintf(stderr, \"git: '%s': %s\\n\", exec_path, strerror(errno));\n-\t\texit(1);\n-\t}\n+\tif (!dirp || chdir(dir))\n+\t\treturn 0;\n \n-\twhile ((de = readdir(dir)) != NULL) {\n+\twhile ((de = readdir(dirp)) != NULL) {\n \t\tstruct stat st;\n \t\tint entlen;\n \n@@ -126,12 +138,37 @@ static void list_commands(const char *exec_path, const char *prefix)\n \n \t\tadd_cmdname(de->d_name + prefix_len, entlen);\n \t}\n-\tclosedir(dir);\n+\tclosedir(dirp);\n \n-\tprintf(\"git commands available in '%s'\\n\", exec_path);\n-\tprintf(\"----------------------------\");\n-\tmput_char('-', strlen(exec_path));\n-\tputchar('\\n');\n+\treturn longest;\n+}\n+\n+static void list_commands(const char *prefix)\n+{\n+\tunsigned int longest = 0;\n+\tunsigned int len;\n+\tconst char *env_path = getenv(\"PATH\");\n+\tchar *paths, *path, *colon;\n+\n+\tif (!env_path) {\n+\t\tfprintf(stderr, \"PATH not set\\n\");\n+\t\texit(1);\n+\t}\n+\n+\tpath = paths = xstrdup(env_path);\n+\twhile ((char *)1 != path) {\n+\t\tif ((colon = strchr(path, ':')))\n+\t\t\t*colon = 0;\n+\n+\t\tlen = list_commands_in_dir(path, prefix);\n+\t\tlongest = MAX(longest, len);\n+\n+\t\tpath = colon + 1;\n+\t}\n+\tfree(paths);\n+\n+\tprintf(\"available git commands\\n\");\n+\tprintf(\"----------------------\\n\");\n \tpretty_print_string_list(cmdname, longest);\n \tputchar('\\n');\n }\n@@ -188,7 +225,6 @@ int cmd_version(int argc, const char **argv, const char *prefix)\n int cmd_help(int argc, const char **argv, const char *prefix)\n {\n \tconst char *help_cmd = argc > 1 ? argv[1] : NULL;\n-\tconst char *exec_path = git_exec_path();\n \n \tif (!help_cmd) {\n \t\tprintf(\"usage: %s\\n\\n\", git_usage_string);\n@@ -198,8 +234,7 @@ int cmd_help(int argc, const char **argv, const char *prefix)\n \n \telse if (!strcmp(help_cmd, \"--all\") || !strcmp(help_cmd, \"-a\")) {\n \t\tprintf(\"usage: %s\\n\\n\", git_usage_string);\n-\t\tif(exec_path)\n-\t\t\tlist_commands(exec_path, \"git-\");\n+\t\tlist_commands(\"git-\");\n \t\texit(0);\n \t}\n \n-- \ngitgui.0.8.4.11176.gd9205-dirty\n"},{"id":"57131","messageId":"1193283437-1706-7-git-send-email-srp@srparish.net","threadId":"10456","inReplyTo":"1193283437-1706-6-git-send-email-srp@srparish.net","subject":"[PATCH 7/7] shell should call setup_path() instead of manually setting up its path","fromName":"Scott R Parish","fromEmail":"srp@srparish.net","sentAt":"2007-10-25T03:37:17Z","receivedAt":"2007-10-25T03:37:17Z","isPatch":true,"sender":{"key":"srp@srparish.net","avatar":"https://gravatar.com/avatar/870e5b6fc4f710cf4db5684bd9af7f2cee5734b3dab3209b13e00cf64f6c9f0e?d=mp&s=160"},"body":"Signed-off-by: Scott R Parish <srp@srparish.net>\n---\n shell.c |    8 +-------\n 1 files changed, 1 insertions(+), 7 deletions(-)\n\ndiff --git a/shell.c b/shell.c\nindex cfe372b..9826109 100644\n--- a/shell.c\n+++ b/shell.c\n@@ -24,17 +24,11 @@ static int do_cvs_cmd(const char *me, char *arg)\n \tconst char *cvsserver_argv[3] = {\n \t\t\"cvsserver\", \"server\", NULL\n \t};\n-\tconst char *oldpath = getenv(\"PATH\");\n-\tstruct strbuf newpath = STRBUF_INIT;\n \n \tif (!arg || strcmp(arg, \"server\"))\n \t\tdie(\"git-cvsserver only handles server: %s\", arg);\n \n-\tstrbuf_addstr(&newpath, git_exec_path());\n-\tstrbuf_addch(&newpath, ':');\n-\tstrbuf_addstr(&newpath, oldpath);\n-\n-\tsetenv(\"PATH\", strbuf_detach(&newpath, NULL), 1);\n+\tsetup_path(NULL);\n \n \treturn execv_git_cmd(cvsserver_argv);\n }\n-- \ngitgui.0.8.4.11176.gd9205-dirty\n"},{"id":"57133","messageId":"7vd4v33iy0.fsf@gitster.siamese.dyndns.org","threadId":"10456","inReplyTo":"1193283437-1706-1-git-send-email-srp@srparish.net","subject":"Re: [PATCH 1/7] \"git\" calls help_unknown_cmd(\"\"); \"git help\" and \"git help -a\" return 0","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-10-25T04:40:55Z","receivedAt":"2007-10-25T04:40:55Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Scott R Parish <srp@srparish.net> writes:\n\n> Signed-off-by: Scott R Parish <srp@srparish.net>\n> ---\n>  git.c  |    5 ++---\n>  help.c |    4 ++--\n>  2 files changed, 4 insertions(+), 5 deletions(-)\n>\n> diff --git a/git.c b/git.c\n> index 853e66c..e1c99e3 100644\n> --- a/git.c\n> +++ b/git.c\n> @@ -445,9 +445,8 @@ int main(int argc, const char **argv)\n>  \t\tif (!prefixcmp(argv[0], \"--\"))\n>  \t\t\targv[0] += 2;\n>  \t} else {\n> -\t\t/* Default command: \"help\" */\n> -\t\targv[0] = \"help\";\n> -\t\targc = 1;\n> +\t\t/* The user didn't specify a command; give them help */\n> +\t\thelp_unknown_cmd(\"\");\n\nSorry, but I fail to see why this is an improvement.\n\nIf you type \"git<Enter>\", before this patch we call cmd_help()\nwithout help_cmd, which gives the usage string and lists common\ncommands, and exits with 1.\n\nWith this patch, you get \"git: '' is not a git-command\",\nfollowed by list of common commands, and then the invocation\nexits with 1.\n\nI think \"git help\" should exit with 0.  The user asked for help,\nwe give help, everything is going as expected and there is no\nreason to exit with non-zero.\n\nHowever, with the current implementation, these changes to\nhelp.c also make \"git<Enter>\" to exit with 0 after it gives\nhelp, which is not so nice (both \"cvs\" and \"svn\" without\nparameter seem to exit with 1 and it sort of makes sense,\nalthough I do not think it matters much).  As a few datapoints,\n\"cvs -H\" exits with 1 and \"svn help\" exits with 0.\n\nSo in short,\n\n - \"git\" should retain the current behaviour (both output and\n   exit code).\n\n - \"git help\" should retain the current output but probably\n   should exit with 0.\n\n - Ditto for \"git help -a\".\n"},{"id":"57134","messageId":"7v640v3ix1.fsf@gitster.siamese.dyndns.org","threadId":"10456","inReplyTo":"1193283437-1706-2-git-send-email-srp@srparish.net","subject":"Re: [PATCH 2/7] s/pattern/prefix/ in help's list_commands","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-10-25T04:41:30Z","receivedAt":"2007-10-25T04:41:30Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Scott R Parish <srp@srparish.net> writes:\n\n> list_commands() currently accepts and ignores a \"pattern\" argument,\n> and then hard codes a prefix as well as some magic numbers.\n\nCorrect observation.\n\nPersonally, I find this static function should not pretend to be\nas flexible --- it is to list git subcommands anyway (and it\neven knows about \".exe\"), so rather than renaming the pattern\nand using it, it might be simpler and cleaner to just drop the\nparameter and be done with it.\n"},{"id":"57135","messageId":"7vve8v24al.fsf@gitster.siamese.dyndns.org","threadId":"10456","inReplyTo":"1193283437-1706-6-git-send-email-srp@srparish.net","subject":"Re: [PATCH 6/7] walk PATH to generate list of commands for \"help -a\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-10-25T04:42:42Z","receivedAt":"2007-10-25T04:42:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Scott R Parish <srp@srparish.net> writes:\n\n> Signed-off-by: Scott R Parish <srp@srparish.net>\n\nRationale?\n\nThere are two cases execv_git_cmd() runs \"git-that\" from a non\nstandard place, if we take your [PATCH 4/7].\n\n - If there is a directory that contains a location that used to\n   hold an old installation of git-* commands (some of which may\n   have been removed in the latest git) and if the user has that\n   directory on PATH, we would run obsolete git subcommand from\n   there.\n\n - If the user has a custom command \"git-that\" in $HOME/bin/\n   that is outside GIT_EXEC_PATH, the new subcommand \"that\" can\n   be used as if it is part of the official git.  This is an\n   improvement [PATCH 4/7] would bring in.  We allow this\n   already for scripts anyway, and the patch is merely making\n   the behaviour of the execv_git_cmd() consistent with it.\n\nIt may be nicer if the user can somehow tell from the output if\neach of the command is from the standard set (i.e. on\nGIT_EXEC_PATH or built-in), or from a non standard place (either\ncustom command as intended, or an unintended obsolete leftover).\n"},{"id":"57136","messageId":"20071025045228.GE759@srparish.net","threadId":"10456","inReplyTo":"7vd4v33iy0.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 1/7] \"git\" calls help_unknown_cmd(\"\"); \"git help\" and \"git help -a\" return 0","fromName":"Scott Parish","fromEmail":"srp@srparish.net","sentAt":"2007-10-25T04:52:29Z","receivedAt":"2007-10-25T04:52:29Z","isPatch":true,"sender":{"key":"srp@srparish.net","avatar":"https://gravatar.com/avatar/870e5b6fc4f710cf4db5684bd9af7f2cee5734b3dab3209b13e00cf64f6c9f0e?d=mp&s=160"},"body":"On Wed, Oct 24, 2007 at 09:40:55PM -0700, Junio C Hamano wrote:\n\n> Sorry, but I fail to see why this is an improvement.\n> \n> However, with the current implementation, these changes to\n> help.c also make \"git<Enter>\" to exit with 0 after it gives\n> help, which is not so nice (both \"cvs\" and \"svn\" without\n> parameter seem to exit with 1 and it sort of makes sense,\n> although I do not think it matters much).  As a few datapoints,\n> \"cvs -H\" exits with 1 and \"svn help\" exits with 0.\n\nThat's strange because when i run that patch on my system:\n\n  % ./git; echo $?\n  git: '' is not a git-command\n \n  <list of common commands>\n  1\n  % ./git help; echo $?\n  <list of common commands>\n  0\n  % ./git help -a; echo $?\n  <list of all commands>\n  0\n\n> So in short,\n> \n>  - \"git\" should retain the current behaviour (both output and\n>    exit code).\n> \n>  - \"git help\" should retain the current output but probably\n>    should exit with 0.\n> \n>  - Ditto for \"git help -a\".\n\nThat's what i was hoping this patch did. I'm not entirely sure how\nits wrong as it seems to work for me.\n\nRegarding \"git: '' is not a git-command\" the way i was seeing that\nis that git is usually only called with commands, and '' isn't a\nvalid command, hence the reason to exit 1, the help is just a nice\nuser experience.\n\nsRp\n\n-- \nScott Parish\nhttp://srparish.net/\n"},{"id":"57137","messageId":"20071025045349.GF759@srparish.net","threadId":"10456","inReplyTo":"7v640v3ix1.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 2/7] s/pattern/prefix/ in help's list_commands","fromName":"Scott Parish","fromEmail":"srp@srparish.net","sentAt":"2007-10-25T04:53:50Z","receivedAt":"2007-10-25T04:53:50Z","isPatch":true,"sender":{"key":"srp@srparish.net","avatar":"https://gravatar.com/avatar/870e5b6fc4f710cf4db5684bd9af7f2cee5734b3dab3209b13e00cf64f6c9f0e?d=mp&s=160"},"body":"On Wed, Oct 24, 2007 at 09:41:30PM -0700, Junio C Hamano wrote:\n\n> Scott R Parish <srp@srparish.net> writes:\n> \n> > list_commands() currently accepts and ignores a \"pattern\" argument,\n> > and then hard codes a prefix as well as some magic numbers.\n> \n> Correct observation.\n> \n> Personally, I find this static function should not pretend to be\n> as flexible --- it is to list git subcommands anyway (and it\n> even knows about \".exe\"), so rather than renaming the pattern\n> and using it, it might be simpler and cleaner to just drop the\n> parameter and be done with it.\n\nNice, i like that even better\n\nsRp\n\n-- \nScott Parish\nhttp://srparish.net/\n"},{"id":"57138","messageId":"20071025050736.GG759@srparish.net","threadId":"10456","inReplyTo":"7vve8v24al.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 6/7] walk PATH to generate list of commands for \"help -a\"","fromName":"Scott Parish","fromEmail":"srp@srparish.net","sentAt":"2007-10-25T05:07:36Z","receivedAt":"2007-10-25T05:07:36Z","isPatch":true,"sender":{"key":"srp@srparish.net","avatar":"https://gravatar.com/avatar/870e5b6fc4f710cf4db5684bd9af7f2cee5734b3dab3209b13e00cf64f6c9f0e?d=mp&s=160"},"body":"On Wed, Oct 24, 2007 at 09:42:42PM -0700, Junio C Hamano wrote:\n\n> Scott R Parish <srp@srparish.net> writes:\n> \n> > Signed-off-by: Scott R Parish <srp@srparish.net>\n> \n> Rationale?\n\nWell, the ultimate reason that i've been working on all of this is\ni'd like to push git as a viable development tool where i work. To\ngive an effective idea, lets say that shared tools get placed on\nnfs servers, which can be mounted to different paths depending on\nwhich nfs server is up or down or which system is the nfs client.\n\nI have no control over each users PATH nor things like MANPATH or\nGIT_EXEC_PATH and have no way of compiling in a path ahead of time,\nbut i would like to provide the easiest user experiance possible,\nmeaning that whether they have git in their PATH, or whether they\nare using an absolute or relative path to it, it just works, hopefully\nincluding \"git help\" and \"git help -a\".\n\nShould i be putting all that in my commit messages?\n\n> There are two cases execv_git_cmd() runs \"git-that\" from a non\n> standard place, if we take your [PATCH 4/7].\n> \n>  - If there is a directory that contains a location that used to\n>    hold an old installation of git-* commands (some of which may\n>    have been removed in the latest git) and if the user has that\n>    directory on PATH, we would run obsolete git subcommand from\n>    there.\n\nI could see that as being problematic. I suppose there are ways\naround that (have \"git\" pass to \"git-cmd\" an argument of what version\nit is) but none that i really like.\n\n>  - If the user has a custom command \"git-that\" in $HOME/bin/\n>    that is outside GIT_EXEC_PATH, the new subcommand \"that\" can\n>    be used as if it is part of the official git.  This is an\n>    improvement [PATCH 4/7] would bring in.  We allow this\n>    already for scripts anyway, and the patch is merely making\n>    the behaviour of the execv_git_cmd() consistent with it.\n> \n> It may be nicer if the user can somehow tell from the output if\n> each of the command is from the standard set (i.e. on\n> GIT_EXEC_PATH or built-in), or from a non standard place (either\n> custom command as intended, or an unintended obsolete leftover).\n\nWhat if git marked commands that weren't found in the location where\nit thinks that it is running from?\n\nsRp\n\n-- \nScott Parish\nhttp://srparish.net/\n"},{"id":"57139","messageId":"7vk5pb21xv.fsf@gitster.siamese.dyndns.org","threadId":"10456","inReplyTo":"20071025050736.GG759@srparish.net","subject":"Re: [PATCH 6/7] walk PATH to generate list of commands for \"help -a\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-10-25T05:33:32Z","receivedAt":"2007-10-25T05:33:32Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Scott Parish <sRp@srparish.net> writes:\n\n> On Wed, Oct 24, 2007 at 09:42:42PM -0700, Junio C Hamano wrote:\n>\n>> Scott R Parish <srp@srparish.net> writes:\n>> \n>> > Signed-off-by: Scott R Parish <srp@srparish.net>\n>> \n>> Rationale?\n>\n> Well, the ultimate reason that i've been working on all of this is\n> i'd like to push git as a viable development tool where i work. To\n> give an effective idea, lets say that shared tools get placed on\n> nfs servers, which can be mounted to different paths depending on\n> which nfs server is up or down or which system is the nfs client.\n\nIt sounds to me that your nfs client systems might find what\npeople usually expect in /usr/local/bin not there but on\n/mnt/random47/bin depending on the system, without a reasonable\nsystem administration effort that places stable symlinks to give\nend users a consistent view of the world regardless from which\nclient, which sounds insane.  I personally do not think we\nshould support lazy system administrators by making git unsafe.\n\nBut using PATH as a fallback is what we already do for scripts,\nand that is good enough to deal with such an installation.\n\n> Should i be putting all that in my commit messages?\n\nEven in a well behaved installation, where everything is found\nwhere they should be (iow, GIT_EXEC_PATH), this is needed\nbecause 4/7 lets you run a custom \"git that\" command from PATH\nand this 6/7 is to teach \"help -a\" about it.  I think at least\nthat much needs to be said in the commit message.\n\n>> There are two cases execv_git_cmd() runs \"git-that\" from a non\n>> standard place, if we take your [PATCH 4/7].\n>> \n>>  - If there is a directory that contains a location that used to\n>>    hold an old installation of git-* commands (some of which may\n>>    have been removed in the latest git) and if the user has that\n>>    directory on PATH, we would run obsolete git subcommand from\n>>    there.\n>\n> I could see that as being problematic. I suppose there are ways\n> around that (have \"git\" pass to \"git-cmd\" an argument of what version\n> it is) but none that i really like.\n\nAs I said, this is making git a bit less safe from unintended\nleftover executables, but the scripts already work that way and\nyour 4/7 merely makes the C level in line with that behaviour.\nI do not think it is too much of a problem anyway.\n\n>> It may be nicer if the user can somehow tell from the output if\n>> each of the command is from the standard set (i.e. on\n>> GIT_EXEC_PATH or built-in), or from a non standard place (either\n>> custom command as intended, or an unintended obsolete leftover).\n>\n> What if git marked commands that weren't found in the location where\n> it thinks that it is running from?\n\nCurrently \"git help -a\" says \"available in $where\" at the top.\nPerhaps make a separate list that is listed as \"available from\nelsewhere\" and show the ones that are on PATH but not masked by\nthe ones on GIT_EXEC_PATH?\n\n    git commands available in '/home/junio/git-next/bin'\n    ----------------------------------------------------\n      add                 gui                 rebase--interactive\n      add--interactive    hash-object         receive-pack\n      ...\n\n    git commands available from elsewhere on your $PATH\n    ----------------------------------------------------\n      frotz               nitfol\n"},{"id":"57142","messageId":"1193293802-3732-1-git-send-email-srp@srparish.net","threadId":"10456","inReplyTo":"7v640v3ix1.fsf@gitster.siamese.dyndns.org","subject":"[PATCH 2/7] remove unused/unneeded \"pattern\" argument of list_commands","fromName":"Scott R Parish","fromEmail":"srp@srparish.net","sentAt":"2007-10-25T06:30:02Z","receivedAt":"2007-10-25T06:30:02Z","isPatch":true,"sender":{"key":"srp@srparish.net","avatar":"https://gravatar.com/avatar/870e5b6fc4f710cf4db5684bd9af7f2cee5734b3dab3209b13e00cf64f6c9f0e?d=mp&s=160"},"body":"list_commands() currently accepts and ignores a \"pattern\" argument,\nand then hard codes a prefix as well as some magic numbers. This\nhardcodes the prefix inside of the function and removes the magic\nnumbers.\n\nSigned-off-by: Scott R Parish <srp@srparish.net>\n---\n help.c |   14 ++++++++------\n 1 files changed, 8 insertions(+), 6 deletions(-)\n\ndiff --git a/help.c b/help.c\nindex b0d2dd4..d6dfdff 100644\n--- a/help.c\n+++ b/help.c\n@@ -93,10 +93,12 @@ static void pretty_print_string_list(struct cmdname **cmdname, int longest)\n \t}\n }\n \n-static void list_commands(const char *exec_path, const char *pattern)\n+static void list_commands(const char *exec_path)\n {\n \tunsigned int longest = 0;\n \tchar path[PATH_MAX];\n+\tconst char *prefix = \"git-\";\n+\tint prefix_len = strlen(prefix);\n \tint dirlen;\n \tDIR *dir = opendir(exec_path);\n \tstruct dirent *de;\n@@ -120,7 +122,7 @@ static void list_commands(const char *exec_path, const char *pattern)\n \t\tstruct stat st;\n \t\tint entlen;\n \n-\t\tif (prefixcmp(de->d_name, \"git-\"))\n+\t\tif (prefixcmp(de->d_name, prefix))\n \t\t\tcontinue;\n \t\tstrcpy(path+dirlen, de->d_name);\n \t\tif (stat(path, &st) || /* stat, not lstat */\n@@ -128,14 +130,14 @@ static void list_commands(const char *exec_path, const char *pattern)\n \t\t    !(st.st_mode & S_IXUSR))\n \t\t\tcontinue;\n \n-\t\tentlen = strlen(de->d_name);\n+\t\tentlen = strlen(de->d_name) - prefix_len;\n \t\tif (has_extension(de->d_name, \".exe\"))\n \t\t\tentlen -= 4;\n \n \t\tif (longest < entlen)\n \t\t\tlongest = entlen;\n \n-\t\tadd_cmdname(de->d_name + 4, entlen-4);\n+\t\tadd_cmdname(de->d_name + prefix_len, entlen);\n \t}\n \tclosedir(dir);\n \n@@ -143,7 +145,7 @@ static void list_commands(const char *exec_path, const char *pattern)\n \tprintf(\"----------------------------\");\n \tmput_char('-', strlen(exec_path));\n \tputchar('\\n');\n-\tpretty_print_string_list(cmdname, longest - 4);\n+\tpretty_print_string_list(cmdname, longest);\n \tputchar('\\n');\n }\n \n@@ -210,7 +212,7 @@ int cmd_help(int argc, const char **argv, const char *prefix)\n \telse if (!strcmp(help_cmd, \"--all\") || !strcmp(help_cmd, \"-a\")) {\n \t\tprintf(\"usage: %s\\n\\n\", git_usage_string);\n \t\tif(exec_path)\n-\t\t\tlist_commands(exec_path, \"git-*\");\n+\t\t\tlist_commands(exec_path);\n \t\texit(0);\n \t}\n \n-- \ngitgui.0.8.4.11178.g9a1bf-dirty\n"},{"id":"57143","messageId":"1193293956-3759-1-git-send-email-srp@srparish.net","threadId":"10456","inReplyTo":"1193293802-3732-1-git-send-email-srp@srparish.net","subject":"[PATCH 5/7] chdir() into list_commands() dir instead of building paths for stat()","fromName":"Scott R Parish","fromEmail":"srp@srparish.net","sentAt":"2007-10-25T06:32:36Z","receivedAt":"2007-10-25T06:32:36Z","isPatch":true,"sender":{"key":"srp@srparish.net","avatar":"https://gravatar.com/avatar/870e5b6fc4f710cf4db5684bd9af7f2cee5734b3dab3209b13e00cf64f6c9f0e?d=mp&s=160"},"body":"Signed-off-by: Scott R Parish <srp@srparish.net>\n---\n help.c |   18 +++---------------\n 1 files changed, 3 insertions(+), 15 deletions(-)\n\ndiff --git a/help.c b/help.c\nindex d6dfdff..322ddaa 100644\n--- a/help.c\n+++ b/help.c\n@@ -96,36 +96,24 @@ static void pretty_print_string_list(struct cmdname **cmdname, int longest)\n static void list_commands(const char *exec_path)\n {\n \tunsigned int longest = 0;\n-\tchar path[PATH_MAX];\n \tconst char *prefix = \"git-\";\n \tint prefix_len = strlen(prefix);\n-\tint dirlen;\n \tDIR *dir = opendir(exec_path);\n \tstruct dirent *de;\n \n-\tif (!dir) {\n+\tif (!dir || chdir(exec_path)) {\n \t\tfprintf(stderr, \"git: '%s': %s\\n\", exec_path, strerror(errno));\n \t\texit(1);\n \t}\n \n-\tdirlen = strlen(exec_path);\n-\tif (PATH_MAX - 20 < dirlen) {\n-\t\tfprintf(stderr, \"git: insanely long exec-path '%s'\\n\",\n-\t\t\texec_path);\n-\t\texit(1);\n-\t}\n-\n-\tmemcpy(path, exec_path, dirlen);\n-\tpath[dirlen++] = '/';\n-\n \twhile ((de = readdir(dir)) != NULL) {\n \t\tstruct stat st;\n \t\tint entlen;\n \n \t\tif (prefixcmp(de->d_name, prefix))\n \t\t\tcontinue;\n-\t\tstrcpy(path+dirlen, de->d_name);\n-\t\tif (stat(path, &st) || /* stat, not lstat */\n+\n+\t\tif (stat(de->d_name, &st) || /* stat, not lstat */\n \t\t    !S_ISREG(st.st_mode) ||\n \t\t    !(st.st_mode & S_IXUSR))\n \t\t\tcontinue;\n-- \ngitgui.0.8.4.11178.g9a1bf-dirty\n"},{"id":"57144","messageId":"20071025070744.GH759@srparish.net","threadId":"10456","inReplyTo":"7vk5pb21xv.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 6/7] walk PATH to generate list of commands for \"help -a\"","fromName":"Scott Parish","fromEmail":"srp@srparish.net","sentAt":"2007-10-25T07:07:45Z","receivedAt":"2007-10-25T07:07:45Z","isPatch":true,"sender":{"key":"srp@srparish.net","avatar":"https://gravatar.com/avatar/870e5b6fc4f710cf4db5684bd9af7f2cee5734b3dab3209b13e00cf64f6c9f0e?d=mp&s=160"},"body":"On Wed, Oct 24, 2007 at 10:33:32PM -0700, Junio C Hamano wrote:\n\n> > Well, the ultimate reason that i've been working on all of this is\n> > i'd like to push git as a viable development tool where i work. To\n> > give an effective idea, lets say that shared tools get placed on\n> > nfs servers, which can be mounted to different paths depending on\n> > which nfs server is up or down or which system is the nfs client.\n> \n> It sounds to me that your nfs client systems might find what\n> people usually expect in /usr/local/bin not there but on\n> /mnt/random47/bin depending on the system, without a reasonable\n> system administration effort that places stable symlinks to give\n> end users a consistent view of the world regardless from which\n> client, which sounds insane.  I personally do not think we\n> should support lazy system administrators by making git unsafe.\n\nWell, the exact details are completely fictitious, made up to\nillustrate the situation without breaking confidential agreements.\nI'm not sure i completely agree with the design, but there are good\nreasons for it, and at this point i have little or no control over\nit.\n\n> >> It may be nicer if the user can somehow tell from the output if\n> >> each of the command is from the standard set (i.e. on\n> >> GIT_EXEC_PATH or built-in), or from a non standard place (either\n> >> custom command as intended, or an unintended obsolete leftover).\n> >\n> > What if git marked commands that weren't found in the location where\n> > it thinks that it is running from?\n> \n> Currently \"git help -a\" says \"available in $where\" at the top.\n> Perhaps make a separate list that is listed as \"available from\n> elsewhere\" and show the ones that are on PATH but not masked by\n> the ones on GIT_EXEC_PATH?\n> \n>     git commands available in '/home/junio/git-next/bin'\n>     ----------------------------------------------------\n>       add                 gui                 rebase--interactive\n>       add--interactive    hash-object         receive-pack\n>       ...\n> \n>     git commands available from elsewhere on your $PATH\n>     ----------------------------------------------------\n>       frotz               nitfol\n\nNice! I'll try doing that, probably won't have time to finish until\nlater tomorrow.\n\nsRp\n\n-- \nScott Parish\nhttp://srparish.net/\n"},{"id":"57313","messageId":"7v640twka3.fsf@gitster.siamese.dyndns.org","threadId":"10456","inReplyTo":"20071025045228.GE759@srparish.net","subject":"Re: [PATCH 1/7] \"git\" calls help_unknown_cmd(\"\"); \"git help\" and \"git help -a\" return 0","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-10-26T23:03:48Z","receivedAt":"2007-10-26T23:03:48Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Scott Parish <sRp@srparish.net> writes:\n\n> That's what i was hoping this patch did. I'm not entirely sure how\n> its wrong as it seems to work for me.\n\nI misread the patch.  My mistake.\n\n> Regarding \"git: '' is not a git-command\" the way i was seeing that\n> is that git is usually only called with commands, and '' isn't a\n> valid command, hence the reason to exit 1, the help is just a nice\n> user experience.\n\nBut think who would type \"git<Enter>\".  They are either people\nwho (1) do not even know that \"git\" alone is not useful and that\nit always wants a subcommand, or (2) know \"git<Enter>\" is the\nsame as \"git help\" and wants to get the \"common command list\"\nquickly.  Technically, \"'' is not a git-command\" is correct, but\nthe message does not help either audience, does it?\n"},{"id":"57330","messageId":"20071027071631.GA16359@srparish.net","threadId":"10456","inReplyTo":"7v640twka3.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 1/7] \"git\" calls help_unknown_cmd(\"\"); \"git help\" and \"git help -a\" return 0","fromName":"Scott Parish","fromEmail":"srp@srparish.net","sentAt":"2007-10-27T07:16:32Z","receivedAt":"2007-10-27T07:16:32Z","isPatch":true,"sender":{"key":"srp@srparish.net","avatar":"https://gravatar.com/avatar/870e5b6fc4f710cf4db5684bd9af7f2cee5734b3dab3209b13e00cf64f6c9f0e?d=mp&s=160"},"body":"On Fri, Oct 26, 2007 at 04:03:48PM -0700, Junio C Hamano wrote:\n\n> > Regarding \"git: '' is not a git-command\" the way i was seeing that\n> > is that git is usually only called with commands, and '' isn't a\n> > valid command, hence the reason to exit 1, the help is just a nice\n> > user experience.\n> \n> But think who would type \"git<Enter>\".  They are either people\n> who (1) do not even know that \"git\" alone is not useful and that\n> it always wants a subcommand, or (2) know \"git<Enter>\" is the\n> same as \"git help\" and wants to get the \"common command list\"\n> quickly.  Technically, \"'' is not a git-command\" is correct, but\n> the message does not help either audience, does it?\n\nFair enough, i'll drop that in the updated patch set i'm about ready\nto send. Incidentally i was also missing the \"usage\" string.\n\nsRp\n\n-- \nScott Parish\nhttp://srparish.net/\n"}]}