2006-01-11 03:12:17 +01:00
|
|
|
#include "cache.h"
|
|
|
|
#include "exec_cmd.h"
|
2006-06-25 15:56:18 +02:00
|
|
|
#include "quote.h"
|
2006-01-11 03:12:17 +01:00
|
|
|
#define MAX_ARGS 32
|
|
|
|
|
|
|
|
extern char **environ;
|
2007-10-27 10:36:51 +02:00
|
|
|
static const char *argv_exec_path;
|
2008-07-21 21:19:52 +02:00
|
|
|
static const char *argv0_path;
|
2006-01-11 03:12:17 +01:00
|
|
|
|
2008-07-13 22:31:18 +02:00
|
|
|
const char *system_path(const char *path)
|
|
|
|
{
|
Compute prefix at runtime if RUNTIME_PREFIX is set
This commit adds support for relocatable binaries (called
RUNTIME_PREFIX). Such binaries can be moved together with the
system configuration files to a different directory, as long as the
relative paths from the binary to the configuration files is
preserved. This functionality is essential on Windows where we
deliver git binaries with an installer that allows to freely choose
the installation location.
If RUNTIME_PREFIX is unset we use the static prefix. This will be
the default on Unix. Thus, the behavior on Unix will remain
identical to the old implementation, which used to add the prefix
in the Makefile.
If RUNTIME_PREFIX is set the prefix is computed from the location
of the executable. In this case, system_path() tries to strip
known directories that executables can be located in from the path
of the executable. If the path is successfully stripped it is used
as the prefix. For example, if the executable is
"/msysgit/bin/git" and BINDIR is "bin", then the prefix computed is
"/msysgit".
If the runtime prefix computation fails, we fall back to the static
prefix specified in the makefile. This can be the case if the
executable is not installed at a known location. Note that our
test system sets GIT_CONFIG_NOSYSTEM to tell git to ignore global
configuration files during testing. Hence testing does not trigger
the fall back.
Note that RUNTIME_PREFIX only works on Windows, though adding
support on Unix should not be too hard. The implementation
requires argv0_path to be set to an absolute path. argv0_path must
point to the directory of the executable. We use assert() to
verify this in debug builds. On Windows, the wrapper for main()
(see compat/mingw.h) guarantees that argv0_path is correctly
initialized. On Unix, further work is required before
RUNTIME_PREFIX can be enabled.
Signed-off-by: Steffen Prohaska <prohaska@zib.de>
Acked-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-01-18 13:00:14 +01:00
|
|
|
#ifdef RUNTIME_PREFIX
|
|
|
|
static const char *prefix;
|
|
|
|
#else
|
2009-01-18 13:00:09 +01:00
|
|
|
static const char *prefix = PREFIX;
|
Compute prefix at runtime if RUNTIME_PREFIX is set
This commit adds support for relocatable binaries (called
RUNTIME_PREFIX). Such binaries can be moved together with the
system configuration files to a different directory, as long as the
relative paths from the binary to the configuration files is
preserved. This functionality is essential on Windows where we
deliver git binaries with an installer that allows to freely choose
the installation location.
If RUNTIME_PREFIX is unset we use the static prefix. This will be
the default on Unix. Thus, the behavior on Unix will remain
identical to the old implementation, which used to add the prefix
in the Makefile.
If RUNTIME_PREFIX is set the prefix is computed from the location
of the executable. In this case, system_path() tries to strip
known directories that executables can be located in from the path
of the executable. If the path is successfully stripped it is used
as the prefix. For example, if the executable is
"/msysgit/bin/git" and BINDIR is "bin", then the prefix computed is
"/msysgit".
If the runtime prefix computation fails, we fall back to the static
prefix specified in the makefile. This can be the case if the
executable is not installed at a known location. Note that our
test system sets GIT_CONFIG_NOSYSTEM to tell git to ignore global
configuration files during testing. Hence testing does not trigger
the fall back.
Note that RUNTIME_PREFIX only works on Windows, though adding
support on Unix should not be too hard. The implementation
requires argv0_path to be set to an absolute path. argv0_path must
point to the directory of the executable. We use assert() to
verify this in debug builds. On Windows, the wrapper for main()
(see compat/mingw.h) guarantees that argv0_path is correctly
initialized. On Unix, further work is required before
RUNTIME_PREFIX can be enabled.
Signed-off-by: Steffen Prohaska <prohaska@zib.de>
Acked-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-01-18 13:00:14 +01:00
|
|
|
#endif
|
2009-01-18 13:00:09 +01:00
|
|
|
struct strbuf d = STRBUF_INIT;
|
|
|
|
|
|
|
|
if (is_absolute_path(path))
|
|
|
|
return path;
|
|
|
|
|
Compute prefix at runtime if RUNTIME_PREFIX is set
This commit adds support for relocatable binaries (called
RUNTIME_PREFIX). Such binaries can be moved together with the
system configuration files to a different directory, as long as the
relative paths from the binary to the configuration files is
preserved. This functionality is essential on Windows where we
deliver git binaries with an installer that allows to freely choose
the installation location.
If RUNTIME_PREFIX is unset we use the static prefix. This will be
the default on Unix. Thus, the behavior on Unix will remain
identical to the old implementation, which used to add the prefix
in the Makefile.
If RUNTIME_PREFIX is set the prefix is computed from the location
of the executable. In this case, system_path() tries to strip
known directories that executables can be located in from the path
of the executable. If the path is successfully stripped it is used
as the prefix. For example, if the executable is
"/msysgit/bin/git" and BINDIR is "bin", then the prefix computed is
"/msysgit".
If the runtime prefix computation fails, we fall back to the static
prefix specified in the makefile. This can be the case if the
executable is not installed at a known location. Note that our
test system sets GIT_CONFIG_NOSYSTEM to tell git to ignore global
configuration files during testing. Hence testing does not trigger
the fall back.
Note that RUNTIME_PREFIX only works on Windows, though adding
support on Unix should not be too hard. The implementation
requires argv0_path to be set to an absolute path. argv0_path must
point to the directory of the executable. We use assert() to
verify this in debug builds. On Windows, the wrapper for main()
(see compat/mingw.h) guarantees that argv0_path is correctly
initialized. On Unix, further work is required before
RUNTIME_PREFIX can be enabled.
Signed-off-by: Steffen Prohaska <prohaska@zib.de>
Acked-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-01-18 13:00:14 +01:00
|
|
|
#ifdef RUNTIME_PREFIX
|
|
|
|
assert(argv0_path);
|
|
|
|
assert(is_absolute_path(argv0_path));
|
|
|
|
|
2009-02-19 20:10:53 +01:00
|
|
|
if (!prefix &&
|
|
|
|
!(prefix = strip_path_suffix(argv0_path, GIT_EXEC_PATH)) &&
|
|
|
|
!(prefix = strip_path_suffix(argv0_path, BINDIR)) &&
|
|
|
|
!(prefix = strip_path_suffix(argv0_path, "git"))) {
|
Compute prefix at runtime if RUNTIME_PREFIX is set
This commit adds support for relocatable binaries (called
RUNTIME_PREFIX). Such binaries can be moved together with the
system configuration files to a different directory, as long as the
relative paths from the binary to the configuration files is
preserved. This functionality is essential on Windows where we
deliver git binaries with an installer that allows to freely choose
the installation location.
If RUNTIME_PREFIX is unset we use the static prefix. This will be
the default on Unix. Thus, the behavior on Unix will remain
identical to the old implementation, which used to add the prefix
in the Makefile.
If RUNTIME_PREFIX is set the prefix is computed from the location
of the executable. In this case, system_path() tries to strip
known directories that executables can be located in from the path
of the executable. If the path is successfully stripped it is used
as the prefix. For example, if the executable is
"/msysgit/bin/git" and BINDIR is "bin", then the prefix computed is
"/msysgit".
If the runtime prefix computation fails, we fall back to the static
prefix specified in the makefile. This can be the case if the
executable is not installed at a known location. Note that our
test system sets GIT_CONFIG_NOSYSTEM to tell git to ignore global
configuration files during testing. Hence testing does not trigger
the fall back.
Note that RUNTIME_PREFIX only works on Windows, though adding
support on Unix should not be too hard. The implementation
requires argv0_path to be set to an absolute path. argv0_path must
point to the directory of the executable. We use assert() to
verify this in debug builds. On Windows, the wrapper for main()
(see compat/mingw.h) guarantees that argv0_path is correctly
initialized. On Unix, further work is required before
RUNTIME_PREFIX can be enabled.
Signed-off-by: Steffen Prohaska <prohaska@zib.de>
Acked-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-01-18 13:00:14 +01:00
|
|
|
prefix = PREFIX;
|
|
|
|
fprintf(stderr, "RUNTIME_PREFIX requested, "
|
|
|
|
"but prefix computation failed. "
|
|
|
|
"Using static fallback '%s'.\n", prefix);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-01-18 13:00:09 +01:00
|
|
|
strbuf_addf(&d, "%s/%s", prefix, path);
|
|
|
|
path = strbuf_detach(&d, NULL);
|
2008-07-13 22:31:18 +02:00
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
2009-01-18 13:00:10 +01:00
|
|
|
const char *git_extract_argv0_path(const char *argv0)
|
2008-07-21 21:19:52 +02:00
|
|
|
{
|
2009-01-18 13:00:11 +01:00
|
|
|
const char *slash;
|
|
|
|
|
|
|
|
if (!argv0 || !*argv0)
|
|
|
|
return NULL;
|
|
|
|
slash = argv0 + strlen(argv0);
|
2009-01-18 13:00:10 +01:00
|
|
|
|
|
|
|
while (argv0 <= slash && !is_dir_sep(*slash))
|
|
|
|
slash--;
|
|
|
|
|
|
|
|
if (slash >= argv0) {
|
|
|
|
argv0_path = xstrndup(argv0, slash - argv0);
|
|
|
|
return slash + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return argv0;
|
2008-07-21 21:19:52 +02:00
|
|
|
}
|
|
|
|
|
2007-10-27 10:36:51 +02:00
|
|
|
void git_set_argv_exec_path(const char *exec_path)
|
2006-01-11 03:12:17 +01:00
|
|
|
{
|
2007-10-27 10:36:51 +02:00
|
|
|
argv_exec_path = exec_path;
|
Propagate --exec-path setting to external commands via GIT_EXEC_PATH
Let PATH0=$PATH that was set before the invocation.
Let /foo be a build directory.
Let /pfx be the installation prefix.
Let pfxexecpath=/pfx/libexec/git-core.
The following is going on when 'git --exec-path=/foo gc' is invoked:
1. git sets PATH=/foo:$PATH0 using the path from --exec-path
2. gc execs 'git repack' (note: no dash).
3. Since there is a git in /foo (it's a build directory), /foo/git is
taken.
4. No explicit exec-path is set this time, hence, this secondary git sets
PATH=$pfxexecpath:/foo:$PATH
5. Since 'repack' is not a built-in, execv_dashed_external execs
'git-repack' (note: dash).
6. There is a $pfxexecpath/git-repack, and it is taken.
7. This git-repack runs 'git pack-objects' (note: no dash).
8. There is no git in $pfxexecpath, but there is one in /foo. Hence,
/foo/git is run.
9. pack-objects is a builtin, hence, in effect /foo/git-pack-objects
is run.
As you can see, the way in which we previously set the PATH allowed to
mix gits of different vintage. By setting GIT_EXEC_PATH when --exec-path
was given on the command line, we reduce the confusion.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-03-21 23:21:18 +01:00
|
|
|
/*
|
|
|
|
* Propagate this setting to external programs.
|
|
|
|
*/
|
|
|
|
setenv(EXEC_PATH_ENVIRONMENT, exec_path, 1);
|
2006-01-11 03:12:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Returns the highest-priority, location to look for git programs. */
|
2006-02-26 16:13:46 +01:00
|
|
|
const char *git_exec_path(void)
|
2006-01-11 03:12:17 +01:00
|
|
|
{
|
|
|
|
const char *env;
|
|
|
|
|
2007-10-27 10:36:51 +02:00
|
|
|
if (argv_exec_path)
|
|
|
|
return argv_exec_path;
|
2006-01-11 03:12:17 +01:00
|
|
|
|
2006-12-19 10:28:15 +01:00
|
|
|
env = getenv(EXEC_PATH_ENVIRONMENT);
|
2006-05-29 02:34:34 +02:00
|
|
|
if (env && *env) {
|
2006-01-11 03:12:17 +01:00
|
|
|
return env;
|
|
|
|
}
|
|
|
|
|
2008-07-23 21:12:18 +02:00
|
|
|
return system_path(GIT_EXEC_PATH);
|
2006-01-11 03:12:17 +01:00
|
|
|
}
|
|
|
|
|
2007-10-28 12:17:20 +01:00
|
|
|
static void add_path(struct strbuf *out, const char *path)
|
|
|
|
{
|
|
|
|
if (path && *path) {
|
|
|
|
if (is_absolute_path(path))
|
|
|
|
strbuf_addstr(out, path);
|
|
|
|
else
|
2008-07-21 21:19:55 +02:00
|
|
|
strbuf_addstr(out, make_nonrelative_path(path));
|
2007-10-28 12:17:20 +01:00
|
|
|
|
2007-12-03 21:55:57 +01:00
|
|
|
strbuf_addch(out, PATH_SEP);
|
2007-10-28 12:17:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-21 21:19:52 +02:00
|
|
|
void setup_path(void)
|
2007-10-28 12:17:20 +01:00
|
|
|
{
|
|
|
|
const char *old_path = getenv("PATH");
|
2008-10-09 21:12:12 +02:00
|
|
|
struct strbuf new_path = STRBUF_INIT;
|
2007-10-28 12:17:20 +01:00
|
|
|
|
Modify setup_path() to only add git_exec_path() to PATH
Searching git programs only in the highest priority location is
sufficient. It does not make sense that some of the required
programs are located at the highest priority location but other
programs are picked up from a lower priority exec-path. If
exec-path is overridden a complete set of commands should be
provided, otherwise several different versions could get mixed,
which is likely to cause confusion.
If a user explicitly overrides the default location (by --exec-path
or GIT_EXEC_PATH), we now expect that all the required programs are
found there. Instead of adding the directories "argv_exec_path",
"getenv(EXEC_PATH_ENVIRONMENT)", and "system_path(GIT_EXEC_PATH)"
to PATH, we now rely on git_exec_path(), which implements the same
order, but only returns the highest priority location to search for
executables.
Accessing only the location with highest priority is also required
for testing executables built with RUNTIME_PREFIX. The call to
system_path() should be avoided if RUNTIME_PREFIX is set and the
executable is not installed at its final destination. Because we
test before installing, we want to avoid calling system_path()
during tests. The modifications in this commit avoid calling
system_path(GIT_EXEC_PATH) if a higher-priority location is
provided, which is the case when running the tests.
Signed-off-by: Steffen Prohaska <prohaska@zib.de>
Acked-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-01-18 13:00:13 +01:00
|
|
|
add_path(&new_path, git_exec_path());
|
2008-07-21 21:19:52 +02:00
|
|
|
add_path(&new_path, argv0_path);
|
2007-10-28 12:17:20 +01:00
|
|
|
|
|
|
|
if (old_path)
|
|
|
|
strbuf_addstr(&new_path, old_path);
|
|
|
|
else
|
|
|
|
strbuf_addstr(&new_path, "/usr/local/bin:/usr/bin:/bin");
|
|
|
|
|
|
|
|
setenv("PATH", new_path.buf, 1);
|
|
|
|
|
|
|
|
strbuf_release(&new_path);
|
|
|
|
}
|
2006-01-11 03:12:17 +01:00
|
|
|
|
2008-07-28 07:50:27 +02:00
|
|
|
const char **prepare_git_cmd(const char **argv)
|
2006-01-11 03:12:17 +01:00
|
|
|
{
|
2007-12-02 07:09:22 +01:00
|
|
|
int argc;
|
|
|
|
const char **nargv;
|
2006-01-11 03:12:17 +01:00
|
|
|
|
2007-12-02 07:09:22 +01:00
|
|
|
for (argc = 0; argv[argc]; argc++)
|
|
|
|
; /* just counting */
|
|
|
|
nargv = xmalloc(sizeof(*nargv) * (argc + 2));
|
2006-01-11 03:12:17 +01:00
|
|
|
|
2007-12-02 07:09:22 +01:00
|
|
|
nargv[0] = "git";
|
|
|
|
for (argc = 0; argv[argc]; argc++)
|
|
|
|
nargv[argc + 1] = argv[argc];
|
|
|
|
nargv[argc + 1] = NULL;
|
2008-07-28 07:50:27 +02:00
|
|
|
return nargv;
|
|
|
|
}
|
|
|
|
|
|
|
|
int execv_git_cmd(const char **argv) {
|
|
|
|
const char **nargv = prepare_git_cmd(argv);
|
2007-12-02 07:09:22 +01:00
|
|
|
trace_argv_printf(nargv, "trace: exec:");
|
2006-06-25 15:56:18 +02:00
|
|
|
|
2007-10-28 12:17:20 +01:00
|
|
|
/* execvp() can only ever return if it fails */
|
2007-12-02 07:09:22 +01:00
|
|
|
execvp("git", (char **)nargv);
|
2006-01-11 03:12:17 +01:00
|
|
|
|
2007-10-28 12:17:20 +01:00
|
|
|
trace_printf("trace: exec failed: %s\n", strerror(errno));
|
2006-06-25 15:56:18 +02:00
|
|
|
|
2007-12-02 07:09:22 +01:00
|
|
|
free(nargv);
|
2007-10-28 12:17:20 +01:00
|
|
|
return -1;
|
2006-01-11 03:12:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-03-05 11:47:29 +01:00
|
|
|
int execl_git_cmd(const char *cmd,...)
|
2006-01-11 03:12:17 +01:00
|
|
|
{
|
|
|
|
int argc;
|
2006-03-05 11:47:29 +01:00
|
|
|
const char *argv[MAX_ARGS + 1];
|
|
|
|
const char *arg;
|
2006-01-11 03:12:17 +01:00
|
|
|
va_list param;
|
|
|
|
|
|
|
|
va_start(param, cmd);
|
|
|
|
argv[0] = cmd;
|
|
|
|
argc = 1;
|
|
|
|
while (argc < MAX_ARGS) {
|
|
|
|
arg = argv[argc++] = va_arg(param, char *);
|
|
|
|
if (!arg)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
va_end(param);
|
|
|
|
if (MAX_ARGS <= argc)
|
|
|
|
return error("too many args to run %s", cmd);
|
|
|
|
|
|
|
|
argv[argc] = NULL;
|
|
|
|
return execv_git_cmd(argv);
|
|
|
|
}
|