2023-05-16 14:33:49 +08:00
|
|
|
#include "git-compat-util.h"
|
2023-03-21 14:25:58 +08:00
|
|
|
#include "abspath.h"
|
2023-03-21 14:26:03 +08:00
|
|
|
#include "environment.h"
|
2018-04-11 05:26:18 +08:00
|
|
|
#include "exec-cmd.h"
|
2023-03-21 14:25:54 +08:00
|
|
|
#include "gettext.h"
|
2023-04-23 04:17:20 +08:00
|
|
|
#include "path.h"
|
2023-05-16 14:33:49 +08:00
|
|
|
#include "run-command.h"
|
2020-07-29 04:23:39 +08:00
|
|
|
#include "strvec.h"
|
2023-04-11 11:00:38 +08:00
|
|
|
#include "trace.h"
|
|
|
|
#include "trace2.h"
|
2006-01-11 10:12:17 +08:00
|
|
|
|
2018-04-10 23:05:44 +08:00
|
|
|
#if defined(RUNTIME_PREFIX)
|
|
|
|
|
|
|
|
#if defined(HAVE_NS_GET_EXECUTABLE_PATH)
|
|
|
|
#include <mach-o/dyld.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(HAVE_BSD_KERN_PROC_SYSCTL)
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/sysctl.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* RUNTIME_PREFIX */
|
|
|
|
|
|
|
|
#define MAX_ARGS 32
|
|
|
|
|
|
|
|
static const char *system_prefix(void);
|
2006-01-11 10:12:17 +08:00
|
|
|
|
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 20:00:14 +08:00
|
|
|
#ifdef RUNTIME_PREFIX
|
2018-04-10 23:05:44 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* When using a runtime prefix, Git dynamically resolves paths relative to its
|
|
|
|
* executable.
|
|
|
|
*
|
|
|
|
* The method for determining the path of the executable is highly
|
|
|
|
* platform-specific.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Path to the current Git executable. Resolved on startup by
|
|
|
|
* 'git_resolve_executable_dir'.
|
|
|
|
*/
|
|
|
|
static const char *executable_dirname;
|
2009-01-18 20:00:09 +08:00
|
|
|
|
2017-09-06 20:30:28 +08:00
|
|
|
static const char *system_prefix(void)
|
|
|
|
{
|
|
|
|
static const char *prefix;
|
2009-01-18 20:00:09 +08:00
|
|
|
|
2018-04-10 23:05:44 +08:00
|
|
|
assert(executable_dirname);
|
|
|
|
assert(is_absolute_path(executable_dirname));
|
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 20:00:14 +08:00
|
|
|
|
2009-02-20 03:10:53 +08:00
|
|
|
if (!prefix &&
|
2018-04-10 23:05:44 +08:00
|
|
|
!(prefix = strip_path_suffix(executable_dirname, GIT_EXEC_PATH)) &&
|
|
|
|
!(prefix = strip_path_suffix(executable_dirname, BINDIR)) &&
|
|
|
|
!(prefix = strip_path_suffix(executable_dirname, "git"))) {
|
2018-04-21 19:18:42 +08:00
|
|
|
prefix = FALLBACK_RUNTIME_PREFIX;
|
2010-02-23 19:42:56 +08:00
|
|
|
trace_printf("RUNTIME_PREFIX requested, "
|
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 20:00:14 +08:00
|
|
|
"but prefix computation failed. "
|
|
|
|
"Using static fallback '%s'.\n", prefix);
|
|
|
|
}
|
2017-09-06 20:30:28 +08:00
|
|
|
return prefix;
|
|
|
|
}
|
2017-09-06 20:32:10 +08:00
|
|
|
|
2018-04-10 23:05:44 +08:00
|
|
|
/*
|
|
|
|
* Resolves the executable path from argv[0], only if it is absolute.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on failure.
|
|
|
|
*/
|
|
|
|
static int git_get_exec_path_from_argv0(struct strbuf *buf, const char *argv0)
|
2017-09-06 20:32:10 +08:00
|
|
|
{
|
|
|
|
const char *slash;
|
|
|
|
|
|
|
|
if (!argv0 || !*argv0)
|
2018-04-10 23:05:44 +08:00
|
|
|
return -1;
|
2017-09-06 20:32:10 +08:00
|
|
|
|
|
|
|
slash = find_last_dir_sep(argv0);
|
2018-04-10 23:05:44 +08:00
|
|
|
if (slash) {
|
|
|
|
trace_printf("trace: resolved executable path from argv0: %s\n",
|
|
|
|
argv0);
|
|
|
|
strbuf_add_absolute_path(buf, argv0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
2017-09-06 20:32:10 +08:00
|
|
|
|
2018-04-10 23:05:44 +08:00
|
|
|
#ifdef PROCFS_EXECUTABLE_PATH
|
|
|
|
/*
|
|
|
|
* Resolves the executable path by examining a procfs symlink.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on failure.
|
|
|
|
*/
|
|
|
|
static int git_get_exec_path_procfs(struct strbuf *buf)
|
|
|
|
{
|
|
|
|
if (strbuf_realpath(buf, PROCFS_EXECUTABLE_PATH, 0)) {
|
|
|
|
trace_printf(
|
|
|
|
"trace: resolved executable path from procfs: %s\n",
|
|
|
|
buf->buf);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif /* PROCFS_EXECUTABLE_PATH */
|
|
|
|
|
|
|
|
#ifdef HAVE_BSD_KERN_PROC_SYSCTL
|
|
|
|
/*
|
|
|
|
* Resolves the executable path using KERN_PROC_PATHNAME BSD sysctl.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on failure.
|
|
|
|
*/
|
|
|
|
static int git_get_exec_path_bsd_sysctl(struct strbuf *buf)
|
|
|
|
{
|
|
|
|
int mib[4];
|
|
|
|
char path[MAXPATHLEN];
|
|
|
|
size_t cb = sizeof(path);
|
|
|
|
|
|
|
|
mib[0] = CTL_KERN;
|
|
|
|
mib[1] = KERN_PROC;
|
|
|
|
mib[2] = KERN_PROC_PATHNAME;
|
|
|
|
mib[3] = -1;
|
|
|
|
if (!sysctl(mib, 4, path, &cb, NULL, 0)) {
|
|
|
|
trace_printf(
|
|
|
|
"trace: resolved executable path from sysctl: %s\n",
|
|
|
|
path);
|
|
|
|
strbuf_addstr(buf, path);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif /* HAVE_BSD_KERN_PROC_SYSCTL */
|
|
|
|
|
|
|
|
#ifdef HAVE_NS_GET_EXECUTABLE_PATH
|
|
|
|
/*
|
|
|
|
* Resolves the executable path by querying Darwin application stack.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on failure.
|
|
|
|
*/
|
|
|
|
static int git_get_exec_path_darwin(struct strbuf *buf)
|
|
|
|
{
|
|
|
|
char path[PATH_MAX];
|
|
|
|
uint32_t size = sizeof(path);
|
|
|
|
if (!_NSGetExecutablePath(path, &size)) {
|
|
|
|
trace_printf(
|
|
|
|
"trace: resolved executable path from Darwin stack: %s\n",
|
|
|
|
path);
|
|
|
|
strbuf_addstr(buf, path);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif /* HAVE_NS_GET_EXECUTABLE_PATH */
|
|
|
|
|
2024-08-22 21:52:12 +08:00
|
|
|
#ifdef HAVE_ZOS_GET_EXECUTABLE_PATH
|
|
|
|
/*
|
|
|
|
* Resolves the executable path from current program's directory and name.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on failure.
|
|
|
|
*/
|
|
|
|
static int git_get_exec_path_zos(struct strbuf *buf)
|
|
|
|
{
|
|
|
|
char *dir = __getprogramdir();
|
|
|
|
char *exe = getprogname();
|
|
|
|
if (dir && exe) {
|
|
|
|
strbuf_addf(buf, "%s/%s", dir, exe);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* HAVE_ZOS_GET_EXECUTABLE_PATH */
|
|
|
|
|
2018-04-10 23:05:45 +08:00
|
|
|
#ifdef HAVE_WPGMPTR
|
|
|
|
/*
|
|
|
|
* Resolves the executable path by using the global variable _wpgmptr.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on failure.
|
|
|
|
*/
|
|
|
|
static int git_get_exec_path_wpgmptr(struct strbuf *buf)
|
|
|
|
{
|
|
|
|
int len = wcslen(_wpgmptr) * 3 + 1;
|
|
|
|
strbuf_grow(buf, len);
|
|
|
|
len = xwcstoutf(buf->buf, _wpgmptr, len);
|
|
|
|
if (len < 0)
|
|
|
|
return -1;
|
|
|
|
buf->len += len;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif /* HAVE_WPGMPTR */
|
|
|
|
|
2018-04-10 23:05:44 +08:00
|
|
|
/*
|
|
|
|
* Resolves the absolute path of the current executable.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on failure.
|
|
|
|
*/
|
|
|
|
static int git_get_exec_path(struct strbuf *buf, const char *argv0)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Identifying the executable path is operating system specific.
|
|
|
|
* Selectively employ all available methods in order of preference,
|
|
|
|
* preferring highly-available authoritative methods over
|
|
|
|
* selectively-available or non-authoritative methods.
|
|
|
|
*
|
|
|
|
* All cases fall back on resolving against argv[0] if there isn't a
|
|
|
|
* better functional method. However, note that argv[0] can be
|
|
|
|
* used-supplied on many operating systems, and is not authoritative
|
|
|
|
* in those cases.
|
|
|
|
*
|
|
|
|
* Each of these functions returns 0 on success, so evaluation will stop
|
|
|
|
* after the first successful method.
|
|
|
|
*/
|
|
|
|
if (
|
|
|
|
#ifdef HAVE_BSD_KERN_PROC_SYSCTL
|
|
|
|
git_get_exec_path_bsd_sysctl(buf) &&
|
|
|
|
#endif /* HAVE_BSD_KERN_PROC_SYSCTL */
|
|
|
|
|
|
|
|
#ifdef HAVE_NS_GET_EXECUTABLE_PATH
|
|
|
|
git_get_exec_path_darwin(buf) &&
|
|
|
|
#endif /* HAVE_NS_GET_EXECUTABLE_PATH */
|
|
|
|
|
|
|
|
#ifdef PROCFS_EXECUTABLE_PATH
|
|
|
|
git_get_exec_path_procfs(buf) &&
|
|
|
|
#endif /* PROCFS_EXECUTABLE_PATH */
|
|
|
|
|
2018-04-10 23:05:45 +08:00
|
|
|
#ifdef HAVE_WPGMPTR
|
|
|
|
git_get_exec_path_wpgmptr(buf) &&
|
|
|
|
#endif /* HAVE_WPGMPTR */
|
|
|
|
|
2024-08-22 21:52:12 +08:00
|
|
|
#ifdef HAVE_ZOS_GET_EXECUTABLE_PATH
|
|
|
|
git_get_exec_path_zos(buf) &&
|
|
|
|
#endif /*HAVE_ZOS_GET_EXECUTABLE_PATH */
|
|
|
|
|
2018-04-10 23:05:44 +08:00
|
|
|
git_get_exec_path_from_argv0(buf, argv0)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strbuf_normalize_path(buf)) {
|
|
|
|
trace_printf("trace: could not normalize path: %s\n", buf->buf);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2019-02-23 06:25:01 +08:00
|
|
|
trace2_cmd_path(buf->buf);
|
|
|
|
|
2018-04-10 23:05:44 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2017-09-06 20:32:10 +08:00
|
|
|
|
2018-04-10 23:05:44 +08:00
|
|
|
void git_resolve_executable_dir(const char *argv0)
|
|
|
|
{
|
|
|
|
struct strbuf buf = STRBUF_INIT;
|
|
|
|
char *resolved;
|
|
|
|
const char *slash;
|
|
|
|
|
|
|
|
if (git_get_exec_path(&buf, argv0)) {
|
|
|
|
trace_printf(
|
|
|
|
"trace: could not determine executable path from: %s\n",
|
|
|
|
argv0);
|
|
|
|
strbuf_release(&buf);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
resolved = strbuf_detach(&buf, NULL);
|
|
|
|
slash = find_last_dir_sep(resolved);
|
2017-09-06 20:32:10 +08:00
|
|
|
if (slash)
|
2018-04-10 23:05:44 +08:00
|
|
|
resolved[slash - resolved] = '\0';
|
|
|
|
|
|
|
|
executable_dirname = resolved;
|
|
|
|
trace_printf("trace: resolved executable dir: %s\n",
|
|
|
|
executable_dirname);
|
2017-09-06 20:32:10 +08:00
|
|
|
}
|
|
|
|
|
2017-09-06 20:30:28 +08:00
|
|
|
#else
|
|
|
|
|
2018-04-10 23:05:44 +08:00
|
|
|
/*
|
|
|
|
* When not using a runtime prefix, Git uses a hard-coded path.
|
|
|
|
*/
|
2017-09-06 20:30:28 +08:00
|
|
|
static const char *system_prefix(void)
|
|
|
|
{
|
2018-04-21 19:18:42 +08:00
|
|
|
return FALLBACK_RUNTIME_PREFIX;
|
2017-09-06 20:30:28 +08:00
|
|
|
}
|
|
|
|
|
2018-04-10 23:05:44 +08:00
|
|
|
/*
|
|
|
|
* This is called during initialization, but No work needs to be done here when
|
|
|
|
* runtime prefix is not being used.
|
|
|
|
*/
|
2022-10-18 09:05:12 +08:00
|
|
|
void git_resolve_executable_dir(const char *argv0 UNUSED)
|
2017-09-06 20:32:10 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-09-06 20:30:28 +08:00
|
|
|
#endif /* RUNTIME_PREFIX */
|
|
|
|
|
|
|
|
char *system_path(const char *path)
|
|
|
|
{
|
|
|
|
struct strbuf d = STRBUF_INIT;
|
|
|
|
|
|
|
|
if (is_absolute_path(path))
|
|
|
|
return xstrdup(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 20:00:14 +08:00
|
|
|
|
2017-09-06 20:30:28 +08:00
|
|
|
strbuf_addf(&d, "%s/%s", system_prefix(), path);
|
2014-11-25 03:33:54 +08:00
|
|
|
return strbuf_detach(&d, NULL);
|
2008-07-14 04:31:18 +08:00
|
|
|
}
|
|
|
|
|
2018-04-10 23:05:44 +08:00
|
|
|
static const char *exec_path_value;
|
|
|
|
|
|
|
|
void git_set_exec_path(const char *exec_path)
|
2006-01-11 10:12:17 +08:00
|
|
|
{
|
2018-04-10 23:05:44 +08:00
|
|
|
exec_path_value = 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-22 06:21:18 +08:00
|
|
|
/*
|
|
|
|
* Propagate this setting to external programs.
|
|
|
|
*/
|
|
|
|
setenv(EXEC_PATH_ENVIRONMENT, exec_path, 1);
|
2006-01-11 10:12:17 +08:00
|
|
|
}
|
|
|
|
|
2018-04-10 23:05:44 +08:00
|
|
|
/* Returns the highest-priority location to look for git programs. */
|
2006-02-26 23:13:46 +08:00
|
|
|
const char *git_exec_path(void)
|
2006-01-11 10:12:17 +08:00
|
|
|
{
|
2018-04-10 23:05:44 +08:00
|
|
|
if (!exec_path_value) {
|
2017-01-09 14:00:12 +08:00
|
|
|
const char *env = getenv(EXEC_PATH_ENVIRONMENT);
|
|
|
|
if (env && *env)
|
2018-04-10 23:05:44 +08:00
|
|
|
exec_path_value = xstrdup(env);
|
2017-01-09 14:00:12 +08:00
|
|
|
else
|
2018-04-10 23:05:44 +08:00
|
|
|
exec_path_value = system_path(GIT_EXEC_PATH);
|
2006-01-11 10:12:17 +08:00
|
|
|
}
|
2018-04-10 23:05:44 +08:00
|
|
|
return exec_path_value;
|
2006-01-11 10:12:17 +08:00
|
|
|
}
|
|
|
|
|
2007-10-28 19:17:20 +08:00
|
|
|
static void add_path(struct strbuf *out, const char *path)
|
|
|
|
{
|
|
|
|
if (path && *path) {
|
2014-07-29 02:34:42 +08:00
|
|
|
strbuf_add_absolute_path(out, path);
|
2007-12-04 04:55:57 +08:00
|
|
|
strbuf_addch(out, PATH_SEP);
|
2007-10-28 19:17:20 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-22 03:19:52 +08:00
|
|
|
void setup_path(void)
|
2007-10-28 19:17:20 +08:00
|
|
|
{
|
2018-04-10 23:05:44 +08:00
|
|
|
const char *exec_path = git_exec_path();
|
2007-10-28 19:17:20 +08:00
|
|
|
const char *old_path = getenv("PATH");
|
2008-10-10 03:12:12 +08:00
|
|
|
struct strbuf new_path = STRBUF_INIT;
|
2007-10-28 19:17:20 +08:00
|
|
|
|
2018-04-10 23:05:44 +08:00
|
|
|
git_set_exec_path(exec_path);
|
|
|
|
add_path(&new_path, exec_path);
|
2007-10-28 19:17:20 +08:00
|
|
|
|
|
|
|
if (old_path)
|
|
|
|
strbuf_addstr(&new_path, old_path);
|
|
|
|
else
|
2010-04-13 17:07:13 +08:00
|
|
|
strbuf_addstr(&new_path, _PATH_DEFPATH);
|
2007-10-28 19:17:20 +08:00
|
|
|
|
|
|
|
setenv("PATH", new_path.buf, 1);
|
|
|
|
|
|
|
|
strbuf_release(&new_path);
|
|
|
|
}
|
2006-01-11 10:12:17 +08:00
|
|
|
|
2020-07-29 04:24:53 +08:00
|
|
|
const char **prepare_git_cmd(struct strvec *out, const char **argv)
|
2006-01-11 10:12:17 +08:00
|
|
|
{
|
2020-07-29 04:24:53 +08:00
|
|
|
strvec_push(out, "git");
|
|
|
|
strvec_pushv(out, argv);
|
2020-07-29 08:37:20 +08:00
|
|
|
return out->v;
|
2008-07-28 13:50:27 +08:00
|
|
|
}
|
|
|
|
|
2018-04-10 23:05:44 +08:00
|
|
|
int execv_git_cmd(const char **argv)
|
|
|
|
{
|
2020-07-29 04:24:53 +08:00
|
|
|
struct strvec nargv = STRVEC_INIT;
|
prepare_{git,shell}_cmd: use argv_array
These functions transform an existing argv into one suitable
for exec-ing or spawning via git or a shell. We can use an
argv_array in each to avoid dealing with manual counting and
allocation.
This also makes the memory allocation more clear and fixes
some leaks. In prepare_shell_cmd, we would sometimes
allocate a new string with "$@" in it and sometimes not,
meaning the caller could not correctly free it. On the
non-Windows side, we are in a child process which will
exec() or exit() immediately, so the leak isn't a big deal.
On Windows, though, we use spawn() from the parent process,
and leak a string for each shell command we run. On top of
that, the Windows code did not free the allocated argv array
at all (but does for the prepare_git_cmd case!).
By switching both of these functions to write into an
argv_array, we can consistently free the result as
appropriate.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-02-23 06:44:39 +08:00
|
|
|
|
|
|
|
prepare_git_cmd(&nargv, argv);
|
2020-07-29 08:37:20 +08:00
|
|
|
trace_argv_printf(nargv.v, "trace: exec:");
|
2006-06-25 21:56:18 +08:00
|
|
|
|
2007-10-28 19:17:20 +08:00
|
|
|
/* execvp() can only ever return if it fails */
|
2020-07-29 08:37:20 +08:00
|
|
|
sane_execvp("git", (char **)nargv.v);
|
2006-01-11 10:12:17 +08:00
|
|
|
|
2007-10-28 19:17:20 +08:00
|
|
|
trace_printf("trace: exec failed: %s\n", strerror(errno));
|
2006-06-25 21:56:18 +08:00
|
|
|
|
2020-07-29 04:24:53 +08:00
|
|
|
strvec_clear(&nargv);
|
2007-10-28 19:17:20 +08:00
|
|
|
return -1;
|
2006-01-11 10:12:17 +08:00
|
|
|
}
|
|
|
|
|
2018-04-10 23:05:44 +08:00
|
|
|
int execl_git_cmd(const char *cmd, ...)
|
2006-01-11 10:12:17 +08:00
|
|
|
{
|
|
|
|
int argc;
|
2006-03-05 18:47:29 +08:00
|
|
|
const char *argv[MAX_ARGS + 1];
|
|
|
|
const char *arg;
|
2006-01-11 10:12:17 +08: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)
|
2018-07-21 15:49:32 +08:00
|
|
|
return error(_("too many args to run %s"), cmd);
|
2006-01-11 10:12:17 +08:00
|
|
|
|
|
|
|
argv[argc] = NULL;
|
|
|
|
return execv_git_cmd(argv);
|
|
|
|
}
|