{"thread":{"id":"10377","subject":"[PATCH] allow git to use the PATH for finding subcommands and help docs","startedAt":"2007-10-19T06:59:31Z","lastAt":"2007-10-20T06:42:40Z","messageCount":10,"participants":["Scott R Parish","Johannes Sixt","Scott Parish","Johannes Schindelin","Mike Hommey"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"56531","messageId":"20071019065931.GB1463@srparish.net","threadId":"10377","inReplyTo":null,"subject":"[PATCH] allow git to use the PATH for finding subcommands and help docs","fromName":"Scott R Parish","fromEmail":"srp@srparish.net","sentAt":"2007-10-19T06:59:31Z","receivedAt":"2007-10-19T06:59:31Z","isPatch":true,"sender":{"key":"srp@srparish.net","avatar":"https://gravatar.com/avatar/870e5b6fc4f710cf4db5684bd9af7f2cee5734b3dab3209b13e00cf64f6c9f0e?d=mp&s=160"},"body":" + check PATH for git_exec_path after other locations but before builtin\n + prepend MANPATH and PERL5LIB in addition to PATH\n\nSigned-off-by: Scott R Parish <srp@srparish.net>\n---\n exec_cmd.c |   50 ++++++++++++++++++++++++++++++++++++++-\n git.c      |   76 +++++++++++++++++++++++++++++++++++++++++------------------\n 2 files changed, 102 insertions(+), 24 deletions(-)\n\ndiff --git a/exec_cmd.c b/exec_cmd.c\nindex 9b74ed2..c6ecca9 100644\n--- a/exec_cmd.c\n+++ b/exec_cmd.c\n@@ -13,19 +13,67 @@ void git_set_exec_path(const char *exec_path)\n }\n \n \n+/* Return the first path in PATH that git is found in or NULL if not found */\n+char *git_path_from_env(void)\n+{\n+\tconst char *env_paths = getenv(\"PATH\");\n+\tconst char *git = \"/git\";\n+\tint git_len = strlen(git);\n+\tchar *paths, *path, *colon, *git_path;\n+\tint path_len;\n+\tstruct stat st;\n+\n+\tif (!env_paths)\n+\t\treturn NULL;\n+\n+\tpath_len = strlen(env_paths);\n+\tpath = paths = xmalloc(path_len + 1);\n+\tmemcpy(paths, env_paths, path_len + 1);\n+\n+\twhile ((char *)1 != path) {\n+\t\tif ((colon = strchr(path, ':')))\n+\t\t    *colon = 0;\n+\n+\t\tpath_len = strlen(path);\n+\t\tgit_path = xmalloc(path_len + git_len + 1);\n+\t\tmemcpy(git_path, path, path_len);\n+\t\tmemcpy(git_path + path_len, git, git_len + 1);\n+\n+\t\tif (!stat(git_path, &st)) { /* found */\n+\t\t\tfree(paths);\n+\t\t\tgit_path[path_len] = 0;\n+\t\t\treturn git_path;\n+\t\t}\n+\n+\t\tfree(git_path);\n+\t\tpath = colon + 1;\n+\t}\n+\n+\tfree(paths);\n+\treturn NULL;\n+}\n+\n+\n /* Returns the highest-priority, location to look for git programs. */\n const char *git_exec_path(void)\n {\n-\tconst char *env;\n+\tconst char *env, *path;\n \n \tif (current_exec_path)\n \t\treturn current_exec_path;\n \n \tenv = getenv(EXEC_PATH_ENVIRONMENT);\n \tif (env && *env) {\n+\t\tcurrent_exec_path = env;\n \t\treturn env;\n \t}\n \n+\tif ((path = git_path_from_env())) {\n+\t\tcurrent_exec_path = path;\n+\t\treturn path;\n+\t}\n+\n+\tcurrent_exec_path = builtin_exec_path;\n \treturn builtin_exec_path;\n }\n \ndiff --git a/git.c b/git.c\nindex 9eaca1d..252ee7c 100644\n--- a/git.c\n+++ b/git.c\n@@ -6,26 +6,56 @@\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+static void prepend_to_env(const char *env, const char *basedir,\n+\t\t\t   const char *subdir, const char *env_default)\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+\tconst char *old = getenv(env);\n+\tint basedir_len = strlen(basedir);\n+\tint subdir_len = strlen(subdir);\n+\tchar *new;\n+\tint old_len;\n+\t\n+\tif (!old)\n+\t\told = env_default;\n+\n+\told_len = strlen(old);\n+\n+\tnew = xmalloc(basedir_len + subdir_len + old_len + 1);\n+\t\n+\tmemcpy(new, basedir, basedir_len);\n+\tmemcpy(new + basedir_len, subdir, subdir_len);\n+\tmemcpy(new + basedir_len + subdir_len, old, old_len + 1);\n+\t\n+\tif (setenv(env, new, 1))\n+\t\tfprintf(stderr, \"Setenv failed: %s\\n\", strerror(errno));\n+\n+\tfree(new);\n+}\n \n-\tmemcpy(path, dir, len);\n-\tpath[len] = ':';\n-\tmemcpy(path + len + 1, old_path, path_len - len);\n+static void prepend_to_envs(const char *dir, int len)\n+{\n+\tchar *slash;\n+\tchar *basedir;\n+\n+\t/* basedir is dir with \"/bin\" stripped off */\n+\tbasedir = xmalloc(len + 1);\n+\tmemcpy(basedir, dir, len + 1);\n+\t\n+\tif ((slash = strrchr(basedir, '/'))) {\n+\t\t*slash = 0;\n+\t\twhile (slash == basedir + --len) /* found trailing slash */\n+\t\t\tif ((slash = strrchr(basedir, '/')))\n+\t\t\t\t*slash = 0;\n+\t}\n \n-\tsetenv(\"PATH\", path, 1);\n+\tprepend_to_env(\"PATH\", basedir, \"/bin:\",\n+\t\t       \"/usr/local/bin:/usr/bin:/bin\");\n+\tprepend_to_env(\"MANPATH\", basedir, \"/share/man:\",\n+\t\t       \"/usr/local/share/man:/usr/share/man\");\n+\tprepend_to_env(\"PERL5LIB\", basedir, \"/lib/perl5:\",\n+\t\t       \"/usr/lib/perl5\");\n \n-\tfree(path);\n+\tfree(basedir);\n }\n \n static int handle_options(const char*** argv, int* argc, int* envchanged)\n@@ -414,8 +444,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\texec_path = cmd;\n \t\tcmd = slash;\n \t}\n \n@@ -453,14 +482,15 @@ int main(int argc, const char **argv)\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 * environment, PATH environment, and $(gitexecdir) in\n+\t * Makefile while built, in this order.  For scripted\n+\t * commands, we prepend the value of the exec_path\n+\t * variable to the PATH.\n \t */\n \tif (exec_path)\n-\t\tprepend_to_path(exec_path, strlen(exec_path));\n+\t\tprepend_to_envs(exec_path, strlen(exec_path));\n \texec_path = git_exec_path();\n-\tprepend_to_path(exec_path, strlen(exec_path));\n+\tprepend_to_envs(exec_path, strlen(exec_path));\n \n \twhile (1) {\n \t\t/* See if it's an internal command */\n-- \n1.5.3.4.206.g58ba4-dirty\n"},{"id":"56536","messageId":"47185DAF.7060809@viscovery.net","threadId":"10377","inReplyTo":"20071019065931.GB1463@srparish.net","subject":"Re: [PATCH] allow git to use the PATH for finding subcommands and help docs","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2007-10-19T07:33:03Z","receivedAt":"2007-10-19T07:33:03Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Scott R Parish schrieb:\n>  + check PATH for git_exec_path after other locations but before builtin\n>  + prepend MANPATH and PERL5LIB in addition to PATH\n\nThis says *what* the patch does, but not *why*. Care to explain?\n\nAnd then your explanation should go into the commit message.\n\n-- Hannes\n"},{"id":"56569","messageId":"20071019130402.GD1463@srparish.net","threadId":"10377","inReplyTo":"47185DAF.7060809@viscovery.net","subject":"[PATCH] allow git to use the PATH for finding subcommands and help docs","fromName":"Scott Parish","fromEmail":"srp@srparish.net","sentAt":"2007-10-19T13:04:03Z","receivedAt":"2007-10-19T13:04:03Z","isPatch":true,"sender":{"key":"srp@srparish.net","avatar":"https://gravatar.com/avatar/870e5b6fc4f710cf4db5684bd9af7f2cee5734b3dab3209b13e00cf64f6c9f0e?d=mp&s=160"},"body":"I have a situation where software for a distribution is installed\ninto a fake \"prefix\" and then moved to one of several potential\nplaces to be used by users. Given that the final location isn't\nstatic, i can't depend on builtin_exec_path. I'd really like users\nto be able to get started with git as easily as possible. With the\ncurrent setup, they would have to create and maintain either an\nGIT_EXEC_PATH or an alias for including --exec-path, as well as a\nMANPATH and PERL5LIB. This seem like an unnessisary burden.\n\nI'd like to make it so that git works equally well when it is ran\nvia an absolute path (already partially works), relative path, or\nfrom the PATH. (in saying \"equally well\" i'm including perl commands\nand help commands)\n\nTo do this i've had to make the following changes:\n\n + check PATH for the location of git\n + the checking of argv[0] was restricted to absolute paths; remove\n   that restriction so it also works when called with a relative\n   path (eg ../../otheruser/usr/bin/git)\n + try to guess and set the env for the typical relative locations for\n   MANPATH and PERL5LIB based off exec_path\n\nSigned-off-by: Scott R Parish <srp@srparish.net>\n---\n exec_cmd.c |   50 ++++++++++++++++++++++++++++++++++++++-\n git.c      |   76 +++++++++++++++++++++++++++++++++++++++++------------------\n 2 files changed, 102 insertions(+), 24 deletions(-)\n\ndiff --git a/exec_cmd.c b/exec_cmd.c\nindex 9b74ed2..c6ecca9 100644\n--- a/exec_cmd.c\n+++ b/exec_cmd.c\n@@ -13,19 +13,67 @@ void git_set_exec_path(const char *exec_path)\n }\n \n \n+/* Return the first path in PATH that git is found in or NULL if not found */\n+char *git_path_from_env(void)\n+{\n+\tconst char *env_paths = getenv(\"PATH\");\n+\tconst char *git = \"/git\";\n+\tint git_len = strlen(git);\n+\tchar *paths, *path, *colon, *git_path;\n+\tint path_len;\n+\tstruct stat st;\n+\n+\tif (!env_paths)\n+\t\treturn NULL;\n+\n+\tpath_len = strlen(env_paths);\n+\tpath = paths = xmalloc(path_len + 1);\n+\tmemcpy(paths, env_paths, path_len + 1);\n+\n+\twhile ((char *)1 != path) {\n+\t\tif ((colon = strchr(path, ':')))\n+\t\t    *colon = 0;\n+\n+\t\tpath_len = strlen(path);\n+\t\tgit_path = xmalloc(path_len + git_len + 1);\n+\t\tmemcpy(git_path, path, path_len);\n+\t\tmemcpy(git_path + path_len, git, git_len + 1);\n+\n+\t\tif (!stat(git_path, &st)) { /* found */\n+\t\t\tfree(paths);\n+\t\t\tgit_path[path_len] = 0;\n+\t\t\treturn git_path;\n+\t\t}\n+\n+\t\tfree(git_path);\n+\t\tpath = colon + 1;\n+\t}\n+\n+\tfree(paths);\n+\treturn NULL;\n+}\n+\n+\n /* Returns the highest-priority, location to look for git programs. */\n const char *git_exec_path(void)\n {\n-\tconst char *env;\n+\tconst char *env, *path;\n \n \tif (current_exec_path)\n \t\treturn current_exec_path;\n \n \tenv = getenv(EXEC_PATH_ENVIRONMENT);\n \tif (env && *env) {\n+\t\tcurrent_exec_path = env;\n \t\treturn env;\n \t}\n \n+\tif ((path = git_path_from_env())) {\n+\t\tcurrent_exec_path = path;\n+\t\treturn path;\n+\t}\n+\n+\tcurrent_exec_path = builtin_exec_path;\n \treturn builtin_exec_path;\n }\n \ndiff --git a/git.c b/git.c\nindex 9eaca1d..252ee7c 100644\n--- a/git.c\n+++ b/git.c\n@@ -6,26 +6,56 @@\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+static void prepend_to_env(const char *env, const char *basedir,\n+\t\t\t   const char *subdir, const char *env_default)\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+\tconst char *old = getenv(env);\n+\tint basedir_len = strlen(basedir);\n+\tint subdir_len = strlen(subdir);\n+\tchar *new;\n+\tint old_len;\n+\t\n+\tif (!old)\n+\t\told = env_default;\n+\n+\told_len = strlen(old);\n+\n+\tnew = xmalloc(basedir_len + subdir_len + old_len + 1);\n+\t\n+\tmemcpy(new, basedir, basedir_len);\n+\tmemcpy(new + basedir_len, subdir, subdir_len);\n+\tmemcpy(new + basedir_len + subdir_len, old, old_len + 1);\n+\t\n+\tif (setenv(env, new, 1))\n+\t\tfprintf(stderr, \"Setenv failed: %s\\n\", strerror(errno));\n+\n+\tfree(new);\n+}\n \n-\tmemcpy(path, dir, len);\n-\tpath[len] = ':';\n-\tmemcpy(path + len + 1, old_path, path_len - len);\n+static void prepend_to_envs(const char *dir, int len)\n+{\n+\tchar *slash;\n+\tchar *basedir;\n+\n+\t/* basedir is dir with \"/bin\" stripped off */\n+\tbasedir = xmalloc(len + 1);\n+\tmemcpy(basedir, dir, len + 1);\n+\t\n+\tif ((slash = strrchr(basedir, '/'))) {\n+\t\t*slash = 0;\n+\t\twhile (slash == basedir + --len) /* found trailing slash */\n+\t\t\tif ((slash = strrchr(basedir, '/')))\n+\t\t\t\t*slash = 0;\n+\t}\n \n-\tsetenv(\"PATH\", path, 1);\n+\tprepend_to_env(\"PATH\", basedir, \"/bin:\",\n+\t\t       \"/usr/local/bin:/usr/bin:/bin\");\n+\tprepend_to_env(\"MANPATH\", basedir, \"/share/man:\",\n+\t\t       \"/usr/local/share/man:/usr/share/man\");\n+\tprepend_to_env(\"PERL5LIB\", basedir, \"/lib/perl5:\",\n+\t\t       \"/usr/lib/perl5\");\n \n-\tfree(path);\n+\tfree(basedir);\n }\n \n static int handle_options(const char*** argv, int* argc, int* envchanged)\n@@ -414,8 +444,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\texec_path = cmd;\n \t\tcmd = slash;\n \t}\n \n@@ -453,14 +482,15 @@ int main(int argc, const char **argv)\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 * environment, PATH environment, and $(gitexecdir) in\n+\t * Makefile while built, in this order.  For scripted\n+\t * commands, we prepend the value of the exec_path\n+\t * variable to the PATH.\n \t */\n \tif (exec_path)\n-\t\tprepend_to_path(exec_path, strlen(exec_path));\n+\t\tprepend_to_envs(exec_path, strlen(exec_path));\n \texec_path = git_exec_path();\n-\tprepend_to_path(exec_path, strlen(exec_path));\n+\tprepend_to_envs(exec_path, strlen(exec_path));\n \n \twhile (1) {\n \t\t/* See if it's an internal command */\n-- \n1.5.3.4.206.g58ba4-dirty\n"},{"id":"56579","messageId":"4718AF48.9020607@viscovery.net","threadId":"10377","inReplyTo":"20071019130402.GD1463@srparish.net","subject":"Re: [PATCH] allow git to use the PATH for finding subcommands and help docs","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2007-10-19T13:21:12Z","receivedAt":"2007-10-19T13:21:12Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Scott Parish schrieb:\n> I have a situation where software for a distribution is installed\n> into a fake \"prefix\" and then moved to one of several potential\n> places to be used by users. Given that the final location isn't\n> static, i can't depend on builtin_exec_path. I'd really like users\n> to be able to get started with git as easily as possible. With the\n> current setup, they would have to create and maintain either an\n> GIT_EXEC_PATH or an alias for including --exec-path, as well as a\n> MANPATH and PERL5LIB. This seem like an unnessisary burden.\n\nInteresting. How does this compare to this 2-patch-series:\n\nhttp://repo.or.cz/w/git/mingw.git?a=commitdiff;h=e479ea2f911b8c70a269ba59372a4fef90f8907c\nhttp://repo.or.cz/w/git/mingw.git?a=commitdiff;h=00a4ff4f3f8ec7e6b3ac15456f00b22b03f438ae\n\nwhich I had come up with to accomplish something very similar\n(on Windows). Your approach looks superior, but I hadn't gone\ninto depths, yet.\n\n-- Hannes\n"},{"id":"56583","messageId":"20071019141805.GE1463@srparish.net","threadId":"10377","inReplyTo":"4718AF48.9020607@viscovery.net","subject":"Re: [PATCH] allow git to use the PATH for finding subcommands and help docs","fromName":"Scott Parish","fromEmail":"srp@srparish.net","sentAt":"2007-10-19T14:18:05Z","receivedAt":"2007-10-19T14:18:05Z","isPatch":true,"sender":{"key":"srp@srparish.net","avatar":"https://gravatar.com/avatar/870e5b6fc4f710cf4db5684bd9af7f2cee5734b3dab3209b13e00cf64f6c9f0e?d=mp&s=160"},"body":"On Fri, Oct 19, 2007 at 03:21:12PM +0200, Johannes Sixt wrote:\n\n>  Scott Parish schrieb:\n> > I have a situation where software for a distribution is installed\n> > into a fake \"prefix\" and then moved to one of several potential\n> > places to be used by users. Given that the final location isn't\n> > static, i can't depend on builtin_exec_path. I'd really like users\n> > to be able to get started with git as easily as possible. With the\n> > current setup, they would have to create and maintain either an\n> > GIT_EXEC_PATH or an alias for including --exec-path, as well as a\n> > MANPATH and PERL5LIB. This seem like an unnessisary burden.\n> \n>  Interesting. How does this compare to this 2-patch-series:\n> \n>  http://repo.or.cz/w/git/mingw.git?a=commitdiff;h=e479ea2f911b8c70a269ba59372a4fef90f8907c\n>  http://repo.or.cz/w/git/mingw.git?a=commitdiff;h=00a4ff4f3f8ec7e6b3ac15456f00b22b03f438ae\n> \n>  which I had come up with to accomplish something very similar\n>  (on Windows). Your approach looks superior, but I hadn't gone\n>  into depths, yet.\n\nI know very little about what's available on windows. Looking at\nyour code, it looks like the command isn't passed in in argv[0] and\nthat it contains the windows style path seperators. My code currently\nassumes that PATH is a colon separated list, and that directories\nare separated with '/'. How should these assumptions change for\nwindows?\n\nsRp\n\n-- \nScott Parish\nhttp://srparish.net/\n"},{"id":"56584","messageId":"Pine.LNX.4.64.0710191616490.16728@wbgn129.biozentrum.uni-wuerzburg.de","threadId":"10377","inReplyTo":"20071019130402.GD1463@srparish.net","subject":"Re: [PATCH] allow git to use the PATH for finding subcommands and help docs","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-10-19T14:27:39Z","receivedAt":"2007-10-19T14:27:39Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 19 Oct 2007, Scott Parish wrote:\n\n>  + check PATH for the location of git\n\nOkay, but better do it only if the current exec_path did not succeed to \nfind something, to stay as backwards compatible as possible.\n\n>  + the checking of argv[0] was restricted to absolute paths; remove\n>    that restriction so it also works when called with a relative\n>    path (eg ../../otheruser/usr/bin/git)\n\nThis will utterly break down when you try to do things in a subdirectory \nof your project.  git will cd up, and the relative path will no longer be \nrelative.\n\n>  + try to guess and set the env for the typical relative locations for\n>    MANPATH and PERL5LIB based off exec_path\n\nNow this is ugly.  At least make it a separate patch.\n\n> +/* Return the first path in PATH that git is found in or NULL if not found */\n> +char *git_path_from_env(void)\n> +{\n> +\tconst char *env_paths = getenv(\"PATH\");\n> +\tconst char *git = \"/git\";\n> +\tint git_len = strlen(git);\n> +\tchar *paths, *path, *colon, *git_path;\n> +\tint path_len;\n> +\tstruct stat st;\n> +\n> +\tif (!env_paths)\n> +\t\treturn NULL;\n> +\n> +\tpath_len = strlen(env_paths);\n> +\tpath = paths = xmalloc(path_len + 1);\n> +\tmemcpy(paths, env_paths, path_len + 1);\n> +\n> +\twhile ((char *)1 != path) {\n> +\t\tif ((colon = strchr(path, ':')))\n> +\t\t    *colon = 0;\n> +\n> +\t\tpath_len = strlen(path);\n> +\t\tgit_path = xmalloc(path_len + git_len + 1);\n> +\t\tmemcpy(git_path, path, path_len);\n> +\t\tmemcpy(git_path + path_len, git, git_len + 1);\n> +\n> +\t\tif (!stat(git_path, &st)) { /* found */\n> +\t\t\tfree(paths);\n> +\t\t\tgit_path[path_len] = 0;\n> +\t\t\treturn git_path;\n> +\t\t}\n> +\n> +\t\tfree(git_path);\n> +\t\tpath = colon + 1;\n> +\t}\n> +\n> +\tfree(paths);\n> +\treturn NULL;\n> +}\n\nI am convinced that this function will look a lot less ugly when you use \nstrbufs.  And I'd call it \"find_git_in_path()\".\n\n>  /* Returns the highest-priority, location to look for git programs. */\n>  const char *git_exec_path(void)\n>  {\n> -\tconst char *env;\n> +\tconst char *env, *path;\n>  \n>  \tif (current_exec_path)\n>  \t\treturn current_exec_path;\n>  \n>  \tenv = getenv(EXEC_PATH_ENVIRONMENT);\n>  \tif (env && *env) {\n> +\t\tcurrent_exec_path = env;\n>  \t\treturn env;\n>  \t}\n>  \n> +\tif ((path = git_path_from_env())) {\n> +\t\tcurrent_exec_path = path;\n> +\t\treturn path;\n> +\t}\n> +\n> +\tcurrent_exec_path = builtin_exec_path;\n>  \treturn builtin_exec_path;\n>  }\n\nAs I said, I'd rather have git try with builtin_exec_path first, and only \nif that fails, search through the PATH, for the _current_ command.\n\n> -static void prepend_to_path(const char *dir, int len)\n> +static void prepend_to_env(const char *env, const char *basedir,\n\nI do not like this rename.  It makes things more obscure, rather than \nclearing things up.\n\n> +\t\t\t   const char *subdir, const char *env_default)\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> +\tconst char *old = getenv(env);\n> +\tint basedir_len = strlen(basedir);\n> +\tint subdir_len = strlen(subdir);\n> +\tchar *new;\n> +\tint old_len;\n> +\t\n> +\tif (!old)\n> +\t\told = env_default;\n> +\n> +\told_len = strlen(old);\n> +\n> +\tnew = xmalloc(basedir_len + subdir_len + old_len + 1);\n> +\t\n> +\tmemcpy(new, basedir, basedir_len);\n> +\tmemcpy(new + basedir_len, subdir, subdir_len);\n> +\tmemcpy(new + basedir_len + subdir_len, old, old_len + 1);\n> +\t\n> +\tif (setenv(env, new, 1))\n> +\t\tfprintf(stderr, \"Setenv failed: %s\\n\", strerror(errno));\n> +\n> +\tfree(new);\n> +}\n\nAgain, this would be so much more elegant using strbufs.\n\n>  \n> -\tmemcpy(path, dir, len);\n> -\tpath[len] = ':';\n> -\tmemcpy(path + len + 1, old_path, path_len - len);\n> +static void prepend_to_envs(const char *dir, int len)\n> +{\n> +\tchar *slash;\n> +\tchar *basedir;\n> +\n> +\t/* basedir is dir with \"/bin\" stripped off */\n> +\tbasedir = xmalloc(len + 1);\n> +\tmemcpy(basedir, dir, len + 1);\n> +\t\n> +\tif ((slash = strrchr(basedir, '/'))) {\n> +\t\t*slash = 0;\n> +\t\twhile (slash == basedir + --len) /* found trailing slash */\n> +\t\t\tif ((slash = strrchr(basedir, '/')))\n> +\t\t\t\t*slash = 0;\n> +\t}\n>  \n> -\tsetenv(\"PATH\", path, 1);\n> +\tprepend_to_env(\"PATH\", basedir, \"/bin:\",\n> +\t\t       \"/usr/local/bin:/usr/bin:/bin\");\n> +\tprepend_to_env(\"MANPATH\", basedir, \"/share/man:\",\n> +\t\t       \"/usr/local/share/man:/usr/share/man\");\n> +\tprepend_to_env(\"PERL5LIB\", basedir, \"/lib/perl5:\",\n> +\t\t       \"/usr/lib/perl5\");\n>  \n> -\tfree(path);\n> +\tfree(basedir);\n>  }\n\nAs I said, this is so controversial it belongs into an own patch.\n\n> @@ -414,8 +444,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\texec_path = cmd;\n\nAs I said, this breaks down.  This alone is enough reason to move it to \nits own patch.  And I strongly suggest the use of make_path_absolute() \n(with an xstrdup()).\n\n> @@ -453,14 +482,15 @@ int main(int argc, const char **argv)\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 * environment, PATH environment, and $(gitexecdir) in\n> +\t * Makefile while built, in this order.  For scripted\n> +\t * commands, we prepend the value of the exec_path\n> +\t * variable to the PATH.\n\nWhile reading this, I have to wonder why it is not just simpler to try \nwith builtin_exec_path first, and if that fails, just let exec() find the \nprogram in the PATH?\n\nCiao,\nDscho\n"},{"id":"56600","messageId":"4718C072.2070505@viscovery.net","threadId":"10377","inReplyTo":"20071019141805.GE1463@srparish.net","subject":"Re: [PATCH] allow git to use the PATH for finding subcommands and help docs","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2007-10-19T14:34:26Z","receivedAt":"2007-10-19T14:34:26Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Scott Parish schrieb:\n> On Fri, Oct 19, 2007 at 03:21:12PM +0200, Johannes Sixt wrote:\n> \n>>  Scott Parish schrieb:\n>>> I have a situation where software for a distribution is installed\n>>> into a fake \"prefix\" and then moved to one of several potential\n>>> places to be used by users. Given that the final location isn't\n>>> static, i can't depend on builtin_exec_path. I'd really like users\n>>> to be able to get started with git as easily as possible. With the\n>>> current setup, they would have to create and maintain either an\n>>> GIT_EXEC_PATH or an alias for including --exec-path, as well as a\n>>> MANPATH and PERL5LIB. This seem like an unnessisary burden.\n>>  Interesting. How does this compare to this 2-patch-series:\n>>\n>>  http://repo.or.cz/w/git/mingw.git?a=commitdiff;h=e479ea2f911b8c70a269ba59372a4fef90f8907c\n>>  http://repo.or.cz/w/git/mingw.git?a=commitdiff;h=00a4ff4f3f8ec7e6b3ac15456f00b22b03f438ae\n>>\n>>  which I had come up with to accomplish something very similar\n>>  (on Windows). Your approach looks superior, but I hadn't gone\n>>  into depths, yet.\n> \n> I know very little about what's available on windows. Looking at\n> your code, it looks like the command isn't passed in in argv[0] and\n> that it contains the windows style path seperators. My code currently\n> assumes that PATH is a colon separated list, and that directories\n> are separated with '/'. How should these assumptions change for\n> windows?\n\nThe question is rather whether my patches would be sufficient to also \nachieve your requirements. They turn bultin_exec_path into a non-constant \nthat derives exec-path from argv[0] (which on Windows happens to be \navailable in the global _pgmptr). Isn't this enough, or at least the essence \nof what you need?\n\n(How to get to the value of _pgmptr, ie. argv[0], on non-Windows is a \nsecondary matter.)\n\n-- Hannes\n"},{"id":"56601","messageId":"20071019164816.GA24573@glandium.org","threadId":"10377","inReplyTo":"Pine.LNX.4.64.0710191616490.16728@wbgn129.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] allow git to use the PATH for finding subcommands and help docs","fromName":"Mike Hommey","fromEmail":"mh@glandium.org","sentAt":"2007-10-19T16:48:16Z","receivedAt":"2007-10-19T16:48:16Z","isPatch":true,"sender":{"key":"mh@glandium.org","avatar":"https://avatars.githubusercontent.com/u/1038527?v=4"},"body":"On Fri, Oct 19, 2007 at 04:27:39PM +0200, Johannes Schindelin wrote:\n> While reading this, I have to wonder why it is not just simpler to try \n> with builtin_exec_path first, and if that fails, just let exec() find the \n> program in the PATH?\n\nWhy not try the directory where the git executable is, too ?\n\nMike\n"},{"id":"56602","messageId":"Pine.LNX.4.64.0710191917440.16728@wbgn129.biozentrum.uni-wuerzburg.de","threadId":"10377","inReplyTo":"20071019164816.GA24573@glandium.org","subject":"Re: [PATCH] allow git to use the PATH for finding subcommands and help docs","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-10-19T17:19:31Z","receivedAt":"2007-10-19T17:19:31Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 19 Oct 2007, Mike Hommey wrote:\n\n> On Fri, Oct 19, 2007 at 04:27:39PM +0200, Johannes Schindelin wrote:\n> > While reading this, I have to wonder why it is not just simpler to try \n> > with builtin_exec_path first, and if that fails, just let exec() find the \n> > program in the PATH?\n> \n> Why not try the directory where the git executable is, too ?\n\nI commented on that.  If the git command was not specified with an \nabsolute path, then make it absolute (and only if not even a relative path \nwas specified, ignore this altogether since git is in the PATH).\n\nI was a bit terse on the issue I have to admit, though.\n\nCiao,\nDscho\n"},{"id":"56667","messageId":"20071020064235.GA2237@srparish.net","threadId":"10377","inReplyTo":"Pine.LNX.4.64.0710191616490.16728@wbgn129.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] allow git to use the PATH for finding subcommands and help docs","fromName":"Scott Parish","fromEmail":"srp@srparish.net","sentAt":"2007-10-20T06:42:40Z","receivedAt":"2007-10-20T06:42:40Z","isPatch":true,"sender":{"key":"srp@srparish.net","avatar":"https://gravatar.com/avatar/870e5b6fc4f710cf4db5684bd9af7f2cee5734b3dab3209b13e00cf64f6c9f0e?d=mp&s=160"},"body":"On Fri, Oct 19, 2007 at 04:27:39PM +0200, Johannes Schindelin wrote:\n\n> While reading this, I have to wonder why it is not just simpler to try \n> with builtin_exec_path first, and if that fails, just let exec() find the \n> program in the PATH?\n\nI think you're right; that is a much better way to do this. I've\nrewritten this as two patches i'll post shortly. I have mixed\nfeelings about the MANPATH/PERL5LIB hack, so i'm leaving it out for\nnow.\n\nsRp\n\n-- \nScott Parish\nhttp://srparish.net/\n"}]}