Merge branch 'dj/runtime-prefix'
A build-time option has been added to allow Git to be told to refer to its associated files relative to the main binary, in the same way that has been possible on Windows for quite some time, for Linux, BSDs and Darwin. * dj/runtime-prefix: Makefile: quote $INSTLIBDIR when passing it to sed Makefile: remove unused @@PERLLIBDIR@@ substitution variable mingw/msvc: use the new-style RUNTIME_PREFIX helper exec_cmd: provide a new-style RUNTIME_PREFIX helper for Windows exec_cmd: RUNTIME_PREFIX on some POSIX systems Makefile: add Perl runtime prefix support Makefile: generate Perl header from template file
This commit is contained in:
commit
92034a9cd5
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,6 +3,7 @@
|
||||
/GIT-LDFLAGS
|
||||
/GIT-PREFIX
|
||||
/GIT-PERL-DEFINES
|
||||
/GIT-PERL-HEADER
|
||||
/GIT-PYTHON-VARS
|
||||
/GIT-SCRIPT-DEFINES
|
||||
/GIT-USER-AGENT
|
||||
|
128
Makefile
128
Makefile
@ -441,6 +441,29 @@ all::
|
||||
#
|
||||
# When cross-compiling, define HOST_CPU as the canonical name of the CPU on
|
||||
# which the built Git will run (for instance "x86_64").
|
||||
#
|
||||
# Define RUNTIME_PREFIX to configure Git to resolve its ancillary tooling and
|
||||
# support files relative to the location of the runtime binary, rather than
|
||||
# hard-coding them into the binary. Git installations built with RUNTIME_PREFIX
|
||||
# can be moved to arbitrary filesystem locations. RUNTIME_PREFIX also causes
|
||||
# Perl scripts to use a modified entry point header allowing them to resolve
|
||||
# support files at runtime.
|
||||
#
|
||||
# When using RUNTIME_PREFIX, define HAVE_BSD_KERN_PROC_SYSCTL if your platform
|
||||
# supports the KERN_PROC BSD sysctl function.
|
||||
#
|
||||
# When using RUNTIME_PREFIX, define PROCFS_EXECUTABLE_PATH if your platform
|
||||
# mounts a "procfs" filesystem capable of resolving the path of the current
|
||||
# executable. If defined, this must be the canonical path for the "procfs"
|
||||
# current executable path.
|
||||
#
|
||||
# When using RUNTIME_PREFIX, define HAVE_NS_GET_EXECUTABLE_PATH if your platform
|
||||
# supports calling _NSGetExecutablePath to retrieve the path of the running
|
||||
# executable.
|
||||
#
|
||||
# When using RUNTIME_PREFIX, define HAVE_WPGMPTR if your platform offers
|
||||
# the global variable _wpgmptr containing the absolute path of the current
|
||||
# executable (this is the case on Windows).
|
||||
|
||||
GIT-VERSION-FILE: FORCE
|
||||
@$(SHELL_PATH) ./GIT-VERSION-GEN
|
||||
@ -478,6 +501,8 @@ ARFLAGS = rcs
|
||||
# mandir
|
||||
# infodir
|
||||
# htmldir
|
||||
# localedir
|
||||
# perllibdir
|
||||
# This can help installing the suite in a relocatable way.
|
||||
|
||||
prefix = $(HOME)
|
||||
@ -502,7 +527,9 @@ bindir_relative = $(patsubst $(prefix)/%,%,$(bindir))
|
||||
mandir_relative = $(patsubst $(prefix)/%,%,$(mandir))
|
||||
infodir_relative = $(patsubst $(prefix)/%,%,$(infodir))
|
||||
gitexecdir_relative = $(patsubst $(prefix)/%,%,$(gitexecdir))
|
||||
localedir_relative = $(patsubst $(prefix)/%,%,$(localedir))
|
||||
htmldir_relative = $(patsubst $(prefix)/%,%,$(htmldir))
|
||||
perllibdir_relative = $(patsubst $(prefix)/%,%,$(perllibdir))
|
||||
|
||||
export prefix bindir sharedir sysconfdir gitwebdir perllibdir localedir
|
||||
|
||||
@ -1670,10 +1697,27 @@ ifdef HAVE_BSD_SYSCTL
|
||||
BASIC_CFLAGS += -DHAVE_BSD_SYSCTL
|
||||
endif
|
||||
|
||||
ifdef HAVE_BSD_KERN_PROC_SYSCTL
|
||||
BASIC_CFLAGS += -DHAVE_BSD_KERN_PROC_SYSCTL
|
||||
endif
|
||||
|
||||
ifdef HAVE_GETDELIM
|
||||
BASIC_CFLAGS += -DHAVE_GETDELIM
|
||||
endif
|
||||
|
||||
ifneq ($(PROCFS_EXECUTABLE_PATH),)
|
||||
procfs_executable_path_SQ = $(subst ','\'',$(PROCFS_EXECUTABLE_PATH))
|
||||
BASIC_CFLAGS += '-DPROCFS_EXECUTABLE_PATH="$(procfs_executable_path_SQ)"'
|
||||
endif
|
||||
|
||||
ifdef HAVE_NS_GET_EXECUTABLE_PATH
|
||||
BASIC_CFLAGS += -DHAVE_NS_GET_EXECUTABLE_PATH
|
||||
endif
|
||||
|
||||
ifdef HAVE_WPGMPTR
|
||||
BASIC_CFLAGS += -DHAVE_WPGMPTR
|
||||
endif
|
||||
|
||||
ifeq ($(TCLTK_PATH),)
|
||||
NO_TCLTK = NoThanks
|
||||
endif
|
||||
@ -1758,11 +1802,13 @@ mandir_relative_SQ = $(subst ','\'',$(mandir_relative))
|
||||
infodir_relative_SQ = $(subst ','\'',$(infodir_relative))
|
||||
perllibdir_SQ = $(subst ','\'',$(perllibdir))
|
||||
localedir_SQ = $(subst ','\'',$(localedir))
|
||||
localedir_relative_SQ = $(subst ','\'',$(localedir_relative))
|
||||
gitexecdir_SQ = $(subst ','\'',$(gitexecdir))
|
||||
gitexecdir_relative_SQ = $(subst ','\'',$(gitexecdir_relative))
|
||||
template_dir_SQ = $(subst ','\'',$(template_dir))
|
||||
htmldir_relative_SQ = $(subst ','\'',$(htmldir_relative))
|
||||
prefix_SQ = $(subst ','\'',$(prefix))
|
||||
perllibdir_relative_SQ = $(subst ','\'',$(perllibdir_relative))
|
||||
gitwebdir_SQ = $(subst ','\'',$(gitwebdir))
|
||||
|
||||
SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
|
||||
@ -1773,6 +1819,31 @@ TCLTK_PATH_SQ = $(subst ','\'',$(TCLTK_PATH))
|
||||
DIFF_SQ = $(subst ','\'',$(DIFF))
|
||||
PERLLIB_EXTRA_SQ = $(subst ','\'',$(PERLLIB_EXTRA))
|
||||
|
||||
# RUNTIME_PREFIX's resolution logic requires resource paths to be expressed
|
||||
# relative to each other and share an installation path.
|
||||
#
|
||||
# This is a dependency in:
|
||||
# - Git's binary RUNTIME_PREFIX logic in (see "exec_cmd.c").
|
||||
# - The runtime prefix Perl header (see
|
||||
# "perl/header_templates/runtime_prefix.template.pl").
|
||||
ifdef RUNTIME_PREFIX
|
||||
|
||||
ifneq ($(filter /%,$(firstword $(gitexecdir_relative))),)
|
||||
$(error RUNTIME_PREFIX requires a relative gitexecdir, not: $(gitexecdir))
|
||||
endif
|
||||
|
||||
ifneq ($(filter /%,$(firstword $(localedir_relative))),)
|
||||
$(error RUNTIME_PREFIX requires a relative localedir, not: $(localedir))
|
||||
endif
|
||||
|
||||
ifndef NO_PERL
|
||||
ifneq ($(filter /%,$(firstword $(perllibdir_relative))),)
|
||||
$(error RUNTIME_PREFIX requires a relative perllibdir, not: $(perllibdir))
|
||||
endif
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
# We must filter out any object files from $(GITLIBS),
|
||||
# as it is typically used like:
|
||||
#
|
||||
@ -1993,27 +2064,44 @@ git.res: git.rc GIT-VERSION-FILE
|
||||
# This makes sure we depend on the NO_PERL setting itself.
|
||||
$(SCRIPT_PERL_GEN): GIT-BUILD-OPTIONS
|
||||
|
||||
ifndef NO_PERL
|
||||
$(SCRIPT_PERL_GEN):
|
||||
# Used for substitution in Perl modules. Disabled when using RUNTIME_PREFIX
|
||||
# since the locale directory is injected.
|
||||
perl_localedir_SQ = $(localedir_SQ)
|
||||
|
||||
ifndef NO_PERL
|
||||
PERL_HEADER_TEMPLATE = perl/header_templates/fixed_prefix.template.pl
|
||||
PERL_DEFINES = $(PERL_PATH_SQ):$(PERLLIB_EXTRA_SQ):$(perllibdir_SQ)
|
||||
$(SCRIPT_PERL_GEN): % : %.perl GIT-PERL-DEFINES GIT-VERSION-FILE
|
||||
|
||||
PERL_DEFINES := $(PERL_PATH_SQ) $(PERLLIB_EXTRA_SQ) $(perllibdir_SQ)
|
||||
PERL_DEFINES += $(RUNTIME_PREFIX)
|
||||
|
||||
# Support Perl runtime prefix. In this mode, a different header is installed
|
||||
# into Perl scripts.
|
||||
ifdef RUNTIME_PREFIX
|
||||
|
||||
PERL_HEADER_TEMPLATE = perl/header_templates/runtime_prefix.template.pl
|
||||
|
||||
# Don't export a fixed $(localedir) path; it will be resolved by the Perl header
|
||||
# at runtime.
|
||||
perl_localedir_SQ =
|
||||
|
||||
endif
|
||||
|
||||
PERL_DEFINES += $(gitexecdir) $(perllibdir) $(localedir)
|
||||
|
||||
$(SCRIPT_PERL_GEN): % : %.perl GIT-PERL-DEFINES GIT-PERL-HEADER GIT-VERSION-FILE
|
||||
$(QUIET_GEN)$(RM) $@ $@+ && \
|
||||
INSTLIBDIR='$(perllibdir_SQ)' && \
|
||||
INSTLIBDIR_EXTRA='$(PERLLIB_EXTRA_SQ)' && \
|
||||
INSTLIBDIR="$$INSTLIBDIR$${INSTLIBDIR_EXTRA:+:$$INSTLIBDIR_EXTRA}" && \
|
||||
sed -e '1{' \
|
||||
-e ' s|#!.*perl|#!$(PERL_PATH_SQ)|' \
|
||||
-e ' h' \
|
||||
-e ' s=.*=use lib (split(/$(pathsep)/, $$ENV{GITPERLLIB} || "'"$$INSTLIBDIR"'"));=' \
|
||||
-e ' H' \
|
||||
-e ' x' \
|
||||
-e ' rGIT-PERL-HEADER' \
|
||||
-e ' G' \
|
||||
-e '}' \
|
||||
-e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
|
||||
$< >$@+ && \
|
||||
chmod +x $@+ && \
|
||||
mv $@+ $@
|
||||
|
||||
PERL_DEFINES := $(subst $(space),:,$(PERL_DEFINES))
|
||||
GIT-PERL-DEFINES: FORCE
|
||||
@FLAGS='$(PERL_DEFINES)'; \
|
||||
if test x"$$FLAGS" != x"`cat $@ 2>/dev/null`" ; then \
|
||||
@ -2021,6 +2109,19 @@ GIT-PERL-DEFINES: FORCE
|
||||
echo "$$FLAGS" >$@; \
|
||||
fi
|
||||
|
||||
GIT-PERL-HEADER: $(PERL_HEADER_TEMPLATE) GIT-PERL-DEFINES Makefile
|
||||
$(QUIET_GEN)$(RM) $@ && \
|
||||
INSTLIBDIR='$(perllibdir_SQ)' && \
|
||||
INSTLIBDIR_EXTRA='$(PERLLIB_EXTRA_SQ)' && \
|
||||
INSTLIBDIR="$$INSTLIBDIR$${INSTLIBDIR_EXTRA:+:$$INSTLIBDIR_EXTRA}" && \
|
||||
sed -e 's=@@PATHSEP@@=$(pathsep)=g' \
|
||||
-e "s=@@INSTLIBDIR@@=$$INSTLIBDIR=g" \
|
||||
-e 's=@@PERLLIBDIR_REL@@=$(perllibdir_relative_SQ)=g' \
|
||||
-e 's=@@GITEXECDIR_REL@@=$(gitexecdir_relative_SQ)=g' \
|
||||
-e 's=@@LOCALEDIR_REL@@=$(localedir_relative_SQ)=g' \
|
||||
$< >$@+ && \
|
||||
mv $@+ $@
|
||||
|
||||
.PHONY: perllibdir
|
||||
perllibdir:
|
||||
@echo '$(perllibdir_SQ)'
|
||||
@ -2168,6 +2269,7 @@ endif
|
||||
exec-cmd.sp exec-cmd.s exec-cmd.o: GIT-PREFIX
|
||||
exec-cmd.sp exec-cmd.s exec-cmd.o: EXTRA_CPPFLAGS = \
|
||||
'-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' \
|
||||
'-DGIT_LOCALE_PATH="$(localedir_relative_SQ)"' \
|
||||
'-DBINDIR="$(bindir_relative_SQ)"' \
|
||||
'-DPREFIX="$(prefix_SQ)"'
|
||||
|
||||
@ -2185,7 +2287,7 @@ attr.sp attr.s attr.o: EXTRA_CPPFLAGS = \
|
||||
|
||||
gettext.sp gettext.s gettext.o: GIT-PREFIX
|
||||
gettext.sp gettext.s gettext.o: EXTRA_CPPFLAGS = \
|
||||
-DGIT_LOCALE_PATH='"$(localedir_SQ)"'
|
||||
-DGIT_LOCALE_PATH='"$(localedir_relative_SQ)"'
|
||||
|
||||
http-push.sp http.sp http-walker.sp remote-curl.sp imap-send.sp: SPARSE_FLAGS += \
|
||||
-DCURL_DISABLE_TYPECHECK
|
||||
@ -2345,7 +2447,7 @@ endif
|
||||
|
||||
perl/build/lib/%.pm: perl/%.pm
|
||||
$(QUIET_GEN)mkdir -p $(dir $@) && \
|
||||
sed -e 's|@@LOCALEDIR@@|$(localedir_SQ)|g' \
|
||||
sed -e 's|@@LOCALEDIR@@|$(perl_localedir_SQ)|g' \
|
||||
-e 's|@@NO_PERL_CPAN_FALLBACKS@@|$(NO_PERL_CPAN_FALLBACKS_SQ)|g' \
|
||||
< $< > $@
|
||||
|
||||
@ -2803,7 +2905,7 @@ ifndef NO_TCLTK
|
||||
endif
|
||||
$(RM) GIT-VERSION-FILE GIT-CFLAGS GIT-LDFLAGS GIT-BUILD-OPTIONS
|
||||
$(RM) GIT-USER-AGENT GIT-PREFIX
|
||||
$(RM) GIT-SCRIPT-DEFINES GIT-PERL-DEFINES GIT-PYTHON-VARS
|
||||
$(RM) GIT-SCRIPT-DEFINES GIT-PERL-DEFINES GIT-PERL-HEADER GIT-PYTHON-VARS
|
||||
|
||||
.PHONY: all install profile-clean clean strip
|
||||
.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
|
||||
|
1
cache.h
1
cache.h
@ -428,6 +428,7 @@ static inline enum object_type object_type(unsigned int mode)
|
||||
#define GIT_ICASE_PATHSPECS_ENVIRONMENT "GIT_ICASE_PATHSPECS"
|
||||
#define GIT_QUARANTINE_ENVIRONMENT "GIT_QUARANTINE_PATH"
|
||||
#define GIT_OPTIONAL_LOCKS_ENVIRONMENT "GIT_OPTIONAL_LOCKS"
|
||||
#define GIT_TEXT_DOMAIN_DIR_ENVIRONMENT "GIT_TEXTDOMAINDIR"
|
||||
|
||||
/*
|
||||
* Environment variable used in handshaking the wire protocol.
|
||||
|
@ -32,14 +32,14 @@ int main(int argc, const char **argv)
|
||||
*/
|
||||
sanitize_stdfds();
|
||||
|
||||
git_resolve_executable_dir(argv[0]);
|
||||
|
||||
git_setup_gettext();
|
||||
|
||||
initialize_the_repository();
|
||||
|
||||
attr_start();
|
||||
|
||||
git_extract_argv0_path(argv[0]);
|
||||
|
||||
restore_sigpipe_to_default();
|
||||
|
||||
return cmd_main(argc, argv);
|
||||
|
@ -2221,7 +2221,7 @@ void mingw_startup(void)
|
||||
die_startup();
|
||||
|
||||
/* determine size of argv and environ conversion buffer */
|
||||
maxlen = wcslen(_wpgmptr);
|
||||
maxlen = wcslen(wargv[0]);
|
||||
for (i = 1; i < argc; i++)
|
||||
maxlen = max(maxlen, wcslen(wargv[i]));
|
||||
for (i = 0; wenv[i]; i++)
|
||||
@ -2241,8 +2241,7 @@ void mingw_startup(void)
|
||||
buffer = malloc_startup(maxlen);
|
||||
|
||||
/* convert command line arguments and environment to UTF-8 */
|
||||
__argv[0] = wcstoutfdup_startup(buffer, _wpgmptr, maxlen);
|
||||
for (i = 1; i < argc; i++)
|
||||
for (i = 0; i < argc; i++)
|
||||
__argv[i] = wcstoutfdup_startup(buffer, wargv[i], maxlen);
|
||||
for (i = 0; wenv[i]; i++)
|
||||
environ[i] = wcstoutfdup_startup(buffer, wenv[i], maxlen);
|
||||
|
@ -37,6 +37,7 @@ ifeq ($(uname_S),Linux)
|
||||
HAVE_GETDELIM = YesPlease
|
||||
SANE_TEXT_GREP=-a
|
||||
FREAD_READS_DIRECTORIES = UnfortunatelyYes
|
||||
PROCFS_EXECUTABLE_PATH = /proc/self/exe
|
||||
endif
|
||||
ifeq ($(uname_S),GNU/kFreeBSD)
|
||||
HAVE_ALLOCA_H = YesPlease
|
||||
@ -111,6 +112,7 @@ ifeq ($(uname_S),Darwin)
|
||||
BASIC_CFLAGS += -DPROTECT_HFS_DEFAULT=1
|
||||
HAVE_BSD_SYSCTL = YesPlease
|
||||
FREAD_READS_DIRECTORIES = UnfortunatelyYes
|
||||
HAVE_NS_GET_EXECUTABLE_PATH = YesPlease
|
||||
endif
|
||||
ifeq ($(uname_S),SunOS)
|
||||
NEEDS_SOCKET = YesPlease
|
||||
@ -205,6 +207,7 @@ ifeq ($(uname_S),FreeBSD)
|
||||
HAVE_PATHS_H = YesPlease
|
||||
GMTIME_UNRELIABLE_ERRORS = UnfortunatelyYes
|
||||
HAVE_BSD_SYSCTL = YesPlease
|
||||
HAVE_BSD_KERN_PROC_SYSCTL = YesPlease
|
||||
PAGER_ENV = LESS=FRX LV=-c MORE=FRX
|
||||
FREAD_READS_DIRECTORIES = UnfortunatelyYes
|
||||
endif
|
||||
@ -217,6 +220,8 @@ ifeq ($(uname_S),OpenBSD)
|
||||
BASIC_LDFLAGS += -L/usr/local/lib
|
||||
HAVE_PATHS_H = YesPlease
|
||||
HAVE_BSD_SYSCTL = YesPlease
|
||||
HAVE_BSD_KERN_PROC_SYSCTL = YesPlease
|
||||
PROCFS_EXECUTABLE_PATH = /proc/curproc/file
|
||||
endif
|
||||
ifeq ($(uname_S),MirBSD)
|
||||
NO_STRCASESTR = YesPlease
|
||||
@ -235,6 +240,8 @@ ifeq ($(uname_S),NetBSD)
|
||||
USE_ST_TIMESPEC = YesPlease
|
||||
HAVE_PATHS_H = YesPlease
|
||||
HAVE_BSD_SYSCTL = YesPlease
|
||||
HAVE_BSD_KERN_PROC_SYSCTL = YesPlease
|
||||
PROCFS_EXECUTABLE_PATH = /proc/curproc/exe
|
||||
endif
|
||||
ifeq ($(uname_S),AIX)
|
||||
DEFAULT_PAGER = more
|
||||
@ -350,6 +357,7 @@ ifeq ($(uname_S),Windows)
|
||||
SNPRINTF_RETURNS_BOGUS = YesPlease
|
||||
NO_SVN_TESTS = YesPlease
|
||||
RUNTIME_PREFIX = YesPlease
|
||||
HAVE_WPGMPTR = YesWeDo
|
||||
NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
|
||||
NO_NSEC = YesPlease
|
||||
USE_WIN32_MMAP = YesPlease
|
||||
@ -499,6 +507,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
|
||||
NO_SVN_TESTS = YesPlease
|
||||
NO_PERL_MAKEMAKER = YesPlease
|
||||
RUNTIME_PREFIX = YesPlease
|
||||
HAVE_WPGMPTR = YesWeDo
|
||||
NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
|
||||
NO_NSEC = YesPlease
|
||||
USE_WIN32_MMAP = YesPlease
|
||||
|
258
exec-cmd.c
258
exec-cmd.c
@ -2,24 +2,52 @@
|
||||
#include "exec-cmd.h"
|
||||
#include "quote.h"
|
||||
#include "argv-array.h"
|
||||
#define MAX_ARGS 32
|
||||
|
||||
static const char *argv_exec_path;
|
||||
#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);
|
||||
|
||||
#ifdef RUNTIME_PREFIX
|
||||
static const char *argv0_path;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
static const char *system_prefix(void)
|
||||
{
|
||||
static const char *prefix;
|
||||
|
||||
assert(argv0_path);
|
||||
assert(is_absolute_path(argv0_path));
|
||||
assert(executable_dirname);
|
||||
assert(is_absolute_path(executable_dirname));
|
||||
|
||||
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"))) {
|
||||
!(prefix = strip_path_suffix(executable_dirname, GIT_EXEC_PATH)) &&
|
||||
!(prefix = strip_path_suffix(executable_dirname, BINDIR)) &&
|
||||
!(prefix = strip_path_suffix(executable_dirname, "git"))) {
|
||||
prefix = PREFIX;
|
||||
trace_printf("RUNTIME_PREFIX requested, "
|
||||
"but prefix computation failed. "
|
||||
@ -28,27 +56,201 @@ static const char *system_prefix(void)
|
||||
return prefix;
|
||||
}
|
||||
|
||||
void git_extract_argv0_path(const char *argv0)
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
const char *slash;
|
||||
|
||||
if (!argv0 || !*argv0)
|
||||
return;
|
||||
return -1;
|
||||
|
||||
slash = find_last_dir_sep(argv0);
|
||||
if (slash) {
|
||||
trace_printf("trace: resolved executable path from argv0: %s\n",
|
||||
argv0);
|
||||
strbuf_add_absolute_path(buf, argv0);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#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 */
|
||||
|
||||
#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 */
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
|
||||
#ifdef HAVE_WPGMPTR
|
||||
git_get_exec_path_wpgmptr(buf) &&
|
||||
#endif /* HAVE_WPGMPTR */
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
if (slash)
|
||||
argv0_path = xstrndup(argv0, slash - argv0);
|
||||
resolved[slash - resolved] = '\0';
|
||||
|
||||
executable_dirname = resolved;
|
||||
trace_printf("trace: resolved executable dir: %s\n",
|
||||
executable_dirname);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* When not using a runtime prefix, Git uses a hard-coded path.
|
||||
*/
|
||||
static const char *system_prefix(void)
|
||||
{
|
||||
return PREFIX;
|
||||
}
|
||||
|
||||
void git_extract_argv0_path(const char *argv0)
|
||||
/*
|
||||
* This is called during initialization, but No work needs to be done here when
|
||||
* runtime prefix is not being used.
|
||||
*/
|
||||
void git_resolve_executable_dir(const char *argv0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -65,32 +267,28 @@ char *system_path(const char *path)
|
||||
return strbuf_detach(&d, NULL);
|
||||
}
|
||||
|
||||
void git_set_argv_exec_path(const char *exec_path)
|
||||
static const char *exec_path_value;
|
||||
|
||||
void git_set_exec_path(const char *exec_path)
|
||||
{
|
||||
argv_exec_path = exec_path;
|
||||
exec_path_value = exec_path;
|
||||
/*
|
||||
* Propagate this setting to external programs.
|
||||
*/
|
||||
setenv(EXEC_PATH_ENVIRONMENT, exec_path, 1);
|
||||
}
|
||||
|
||||
|
||||
/* Returns the highest-priority, location to look for git programs. */
|
||||
/* Returns the highest-priority location to look for git programs. */
|
||||
const char *git_exec_path(void)
|
||||
{
|
||||
static char *cached_exec_path;
|
||||
|
||||
if (argv_exec_path)
|
||||
return argv_exec_path;
|
||||
|
||||
if (!cached_exec_path) {
|
||||
if (!exec_path_value) {
|
||||
const char *env = getenv(EXEC_PATH_ENVIRONMENT);
|
||||
if (env && *env)
|
||||
cached_exec_path = xstrdup(env);
|
||||
exec_path_value = xstrdup(env);
|
||||
else
|
||||
cached_exec_path = system_path(GIT_EXEC_PATH);
|
||||
exec_path_value = system_path(GIT_EXEC_PATH);
|
||||
}
|
||||
return cached_exec_path;
|
||||
return exec_path_value;
|
||||
}
|
||||
|
||||
static void add_path(struct strbuf *out, const char *path)
|
||||
@ -103,10 +301,12 @@ static void add_path(struct strbuf *out, const char *path)
|
||||
|
||||
void setup_path(void)
|
||||
{
|
||||
const char *exec_path = git_exec_path();
|
||||
const char *old_path = getenv("PATH");
|
||||
struct strbuf new_path = STRBUF_INIT;
|
||||
|
||||
add_path(&new_path, git_exec_path());
|
||||
git_set_exec_path(exec_path);
|
||||
add_path(&new_path, exec_path);
|
||||
|
||||
if (old_path)
|
||||
strbuf_addstr(&new_path, old_path);
|
||||
@ -125,7 +325,8 @@ const char **prepare_git_cmd(struct argv_array *out, const char **argv)
|
||||
return out->argv;
|
||||
}
|
||||
|
||||
int execv_git_cmd(const char **argv) {
|
||||
int execv_git_cmd(const char **argv)
|
||||
{
|
||||
struct argv_array nargv = ARGV_ARRAY_INIT;
|
||||
|
||||
prepare_git_cmd(&nargv, argv);
|
||||
@ -140,8 +341,7 @@ int execv_git_cmd(const char **argv) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int execl_git_cmd(const char *cmd,...)
|
||||
int execl_git_cmd(const char *cmd, ...)
|
||||
{
|
||||
int argc;
|
||||
const char *argv[MAX_ARGS + 1];
|
||||
|
@ -3,8 +3,8 @@
|
||||
|
||||
struct argv_array;
|
||||
|
||||
extern void git_set_argv_exec_path(const char *exec_path);
|
||||
extern void git_extract_argv0_path(const char *path);
|
||||
extern void git_set_exec_path(const char *exec_path);
|
||||
extern void git_resolve_executable_dir(const char *path);
|
||||
extern const char *git_exec_path(void);
|
||||
extern void setup_path(void);
|
||||
extern const char **prepare_git_cmd(struct argv_array *out, const char **argv);
|
||||
|
@ -2,7 +2,8 @@
|
||||
* Copyright (c) 2010 Ævar Arnfjörð Bjarmason
|
||||
*/
|
||||
|
||||
#include "git-compat-util.h"
|
||||
#include "cache.h"
|
||||
#include "exec-cmd.h"
|
||||
#include "gettext.h"
|
||||
#include "strbuf.h"
|
||||
#include "utf8.h"
|
||||
@ -157,10 +158,11 @@ static void init_gettext_charset(const char *domain)
|
||||
|
||||
void git_setup_gettext(void)
|
||||
{
|
||||
const char *podir = getenv("GIT_TEXTDOMAINDIR");
|
||||
const char *podir = getenv(GIT_TEXT_DOMAIN_DIR_ENVIRONMENT);
|
||||
|
||||
if (!podir)
|
||||
podir = GIT_LOCALE_PATH;
|
||||
podir = system_path(GIT_LOCALE_PATH);
|
||||
|
||||
bindtextdomain("git", podir);
|
||||
setlocale(LC_MESSAGES, "");
|
||||
setlocale(LC_TIME, "");
|
||||
|
2
git.c
2
git.c
@ -83,7 +83,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
|
||||
*/
|
||||
if (skip_prefix(cmd, "--exec-path", &cmd)) {
|
||||
if (*cmd == '=')
|
||||
git_set_argv_exec_path(cmd + 1);
|
||||
git_set_exec_path(cmd + 1);
|
||||
else {
|
||||
puts(git_exec_path());
|
||||
exit(0);
|
||||
|
@ -18,7 +18,7 @@ our @EXPORT_OK = @EXPORT;
|
||||
|
||||
sub __bootstrap_locale_messages {
|
||||
our $TEXTDOMAIN = 'git';
|
||||
our $TEXTDOMAINDIR = $ENV{GIT_TEXTDOMAINDIR} || '@@LOCALEDIR@@';
|
||||
our $TEXTDOMAINDIR ||= $ENV{GIT_TEXTDOMAINDIR} || '@@LOCALEDIR@@';
|
||||
|
||||
require POSIX;
|
||||
POSIX->import(qw(setlocale));
|
||||
|
1
perl/header_templates/fixed_prefix.template.pl
Normal file
1
perl/header_templates/fixed_prefix.template.pl
Normal file
@ -0,0 +1 @@
|
||||
use lib (split(/@@PATHSEP@@/, $ENV{GITPERLLIB} || '@@INSTLIBDIR@@'));
|
42
perl/header_templates/runtime_prefix.template.pl
Normal file
42
perl/header_templates/runtime_prefix.template.pl
Normal file
@ -0,0 +1,42 @@
|
||||
# BEGIN RUNTIME_PREFIX generated code.
|
||||
#
|
||||
# This finds our Git::* libraries relative to the script's runtime path.
|
||||
sub __git_system_path {
|
||||
my ($relpath) = @_;
|
||||
my $gitexecdir_relative = '@@GITEXECDIR_REL@@';
|
||||
|
||||
# GIT_EXEC_PATH is supplied by `git` or the test suite.
|
||||
my $exec_path;
|
||||
if (exists $ENV{GIT_EXEC_PATH}) {
|
||||
$exec_path = $ENV{GIT_EXEC_PATH};
|
||||
} else {
|
||||
# This can happen if this script is being directly invoked instead of run
|
||||
# by "git".
|
||||
require FindBin;
|
||||
$exec_path = $FindBin::Bin;
|
||||
}
|
||||
|
||||
# Trim off the relative gitexecdir path to get the system path.
|
||||
(my $prefix = $exec_path) =~ s/\Q$gitexecdir_relative\E$//;
|
||||
|
||||
require File::Spec;
|
||||
return File::Spec->catdir($prefix, $relpath);
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
use lib split /@@PATHSEP@@/,
|
||||
(
|
||||
$ENV{GITPERLLIB} ||
|
||||
do {
|
||||
my $perllibdir = __git_system_path('@@PERLLIBDIR_REL@@');
|
||||
(-e $perllibdir) || die("Invalid system path ($relpath): $path");
|
||||
$perllibdir;
|
||||
}
|
||||
);
|
||||
|
||||
# Export the system locale directory to the I18N module. The locale directory
|
||||
# is only installed if NO_GETTEXT is set.
|
||||
$Git::I18N::TEXTDOMAINDIR = __git_system_path('@@LOCALEDIR_REL@@');
|
||||
}
|
||||
|
||||
# END RUNTIME_PREFIX generated code.
|
@ -145,7 +145,7 @@ test_trace () {
|
||||
expect="$1"
|
||||
shift
|
||||
GIT_TRACE=1 test-tool run-command "$@" run-command true 2>&1 >/dev/null | \
|
||||
sed 's/.* run_command: //' >actual &&
|
||||
sed -e 's/.* run_command: //' -e '/trace: .*/d' >actual &&
|
||||
echo "$expect true" >expect &&
|
||||
test_cmp expect actual
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user