/GIT-LDFLAGS
/GIT-PREFIX
/GIT-PERL-DEFINES
+ /GIT-PERL-HEADER
/GIT-PYTHON-VARS
/GIT-SCRIPT-DEFINES
/GIT-USER-AGENT
/git-rm
/git-send-email
/git-send-pack
+/git-serve
/git-sh-i18n
/git-sh-i18n--envsubst
/git-sh-setup
#
# 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
# mandir
# infodir
# htmldir
+ # localedir
+ # perllibdir
# This can help installing the suite in a relocatable way.
prefix = $(HOME)
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
PROGRAM_OBJS += sh-i18n--envsubst.o
PROGRAM_OBJS += shell.o
PROGRAM_OBJS += show-index.o
-PROGRAM_OBJS += upload-pack.o
PROGRAM_OBJS += remote-testsvn.o
# Binary suffix, set to .exe for Windows builds
TEST_PROGRAMS_NEED_X += test-fake-ssh
TEST_PROGRAMS_NEED_X += test-line-buffer
TEST_PROGRAMS_NEED_X += test-parse-options
+TEST_PROGRAMS_NEED_X += test-pkt-line
TEST_PROGRAMS_NEED_X += test-svn-fe
TEST_PROGRAMS_NEED_X += test-tool
LIB_OBJS += bulk-checkin.o
LIB_OBJS += bundle.o
LIB_OBJS += cache-tree.o
+LIB_OBJS += chdir-notify.o
LIB_OBJS += checkout.o
LIB_OBJS += color.o
LIB_OBJS += column.o
LIB_OBJS += ewah/ewah_bitmap.o
LIB_OBJS += ewah/ewah_io.o
LIB_OBJS += ewah/ewah_rlw.o
-LIB_OBJS += exec_cmd.o
+LIB_OBJS += exec-cmd.o
LIB_OBJS += fetch-object.o
LIB_OBJS += fetch-pack.o
LIB_OBJS += fsck.o
LIB_OBJS += ll-merge.o
LIB_OBJS += lockfile.o
LIB_OBJS += log-tree.o
+LIB_OBJS += ls-refs.o
LIB_OBJS += mailinfo.o
LIB_OBJS += mailmap.o
LIB_OBJS += match-trees.o
+LIB_OBJS += mem-pool.o
LIB_OBJS += merge.o
LIB_OBJS += merge-blobs.o
LIB_OBJS += merge-recursive.o
LIB_OBJS += refs/ref-cache.o
LIB_OBJS += ref-filter.o
LIB_OBJS += remote.o
-LIB_OBJS += replace_object.o
+LIB_OBJS += replace-object.o
LIB_OBJS += repository.o
LIB_OBJS += rerere.o
LIB_OBJS += resolve-undo.o
LIB_OBJS += run-command.o
LIB_OBJS += send-pack.o
LIB_OBJS += sequencer.o
+LIB_OBJS += serve.o
LIB_OBJS += server-info.o
LIB_OBJS += setup.o
LIB_OBJS += sha1-array.o
LIB_OBJS += sha1-lookup.o
-LIB_OBJS += sha1_file.o
-LIB_OBJS += sha1_name.o
+LIB_OBJS += sha1-file.o
+LIB_OBJS += sha1-name.o
LIB_OBJS += shallow.o
LIB_OBJS += sideband.o
LIB_OBJS += sigchain.o
LIB_OBJS += tree.o
LIB_OBJS += tree-walk.o
LIB_OBJS += unpack-trees.o
+LIB_OBJS += upload-pack.o
LIB_OBJS += url.o
LIB_OBJS += urlmatch.o
LIB_OBJS += usage.o
LIB_OBJS += wildmatch.o
LIB_OBJS += worktree.o
LIB_OBJS += wrapper.o
-LIB_OBJS += write_or_die.o
+LIB_OBJS += write-or-die.o
LIB_OBJS += ws.o
LIB_OBJS += wt-status.o
LIB_OBJS += xdiff-interface.o
BUILTIN_OBJS += builtin/revert.o
BUILTIN_OBJS += builtin/rm.o
BUILTIN_OBJS += builtin/send-pack.o
+BUILTIN_OBJS += builtin/serve.o
BUILTIN_OBJS += builtin/shortlog.o
BUILTIN_OBJS += builtin/show-branch.o
BUILTIN_OBJS += builtin/show-ref.o
BUILTIN_OBJS += builtin/update-ref.o
BUILTIN_OBJS += builtin/update-server-info.o
BUILTIN_OBJS += builtin/upload-archive.o
+BUILTIN_OBJS += builtin/upload-pack.o
BUILTIN_OBJS += builtin/var.o
BUILTIN_OBJS += builtin/verify-commit.o
BUILTIN_OBJS += builtin/verify-pack.o
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
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))
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:
#
# 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 \
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)'
+
.PHONY: gitweb
gitweb:
$(QUIET_SUBDIR0)gitweb $(QUIET_SUBDIR1) all
$(OBJECTS): $(LIB_H)
endif
-exec_cmd.sp exec_cmd.s exec_cmd.o: GIT-PREFIX
-exec_cmd.sp exec_cmd.s exec_cmd.o: EXTRA_CPPFLAGS = \
+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)"'
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
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' \
< $< > $@
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
#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.
extern char *get_object_directory(void);
extern char *get_index_file(void);
extern char *get_graft_file(void);
-extern int set_git_dir(const char *path);
+extern void set_git_dir(const char *path);
extern int get_common_dir_noenv(struct strbuf *sb, const char *gitdir);
extern int get_common_dir(struct strbuf *sb, const char *gitdir);
extern const char *get_git_namespace(void);
#include "cache.h"
-#include "exec_cmd.h"
+#include "exec-cmd.h"
#include "attr.h"
/*
*/
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);
--- /dev/null
- #define MAX_ARGS 32
+#include "cache.h"
+#include "exec-cmd.h"
+#include "quote.h"
+#include "argv-array.h"
- static const char *argv_exec_path;
+
- static const char *argv0_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
- assert(argv0_path);
- assert(is_absolute_path(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;
+
- !(prefix = strip_path_suffix(argv0_path, GIT_EXEC_PATH)) &&
- !(prefix = strip_path_suffix(argv0_path, BINDIR)) &&
- !(prefix = strip_path_suffix(argv0_path, "git"))) {
++ assert(executable_dirname);
++ assert(is_absolute_path(executable_dirname));
+
+ if (!prefix &&
- void git_extract_argv0_path(const char *argv0)
++ !(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. "
+ "Using static fallback '%s'.\n", prefix);
+ }
+ return prefix;
+}
+
- return;
++/*
++ * 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)
- argv0_path = xstrndup(argv0, slash - argv0);
++ 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)
- void git_extract_argv0_path(const char *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_set_argv_exec_path(const char *exec_path)
++/*
++ * 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)
+{
+}
+
+#endif /* RUNTIME_PREFIX */
+
+char *system_path(const char *path)
+{
+ struct strbuf d = STRBUF_INIT;
+
+ if (is_absolute_path(path))
+ return xstrdup(path);
+
+ strbuf_addf(&d, "%s/%s", system_prefix(), path);
+ return strbuf_detach(&d, NULL);
+}
+
- argv_exec_path = exec_path;
++static const char *exec_path_value;
++
++void git_set_exec_path(const char *exec_path)
+{
-
- /* Returns the highest-priority, location to look for git programs. */
++ exec_path_value = exec_path;
+ /*
+ * Propagate this setting to external programs.
+ */
+ setenv(EXEC_PATH_ENVIRONMENT, exec_path, 1);
+}
+
- static char *cached_exec_path;
-
- if (argv_exec_path)
- return argv_exec_path;
-
- if (!cached_exec_path) {
++/* Returns the highest-priority location to look for git programs. */
+const char *git_exec_path(void)
+{
- cached_exec_path = xstrdup(env);
++ if (!exec_path_value) {
+ const char *env = getenv(EXEC_PATH_ENVIRONMENT);
+ if (env && *env)
- cached_exec_path = system_path(GIT_EXEC_PATH);
++ exec_path_value = xstrdup(env);
+ else
- return cached_exec_path;
++ exec_path_value = system_path(GIT_EXEC_PATH);
+ }
- add_path(&new_path, git_exec_path());
++ return exec_path_value;
+}
+
+static void add_path(struct strbuf *out, const char *path)
+{
+ if (path && *path) {
+ strbuf_add_absolute_path(out, path);
+ strbuf_addch(out, PATH_SEP);
+ }
+}
+
+void setup_path(void)
+{
++ const char *exec_path = git_exec_path();
+ const char *old_path = getenv("PATH");
+ struct strbuf new_path = STRBUF_INIT;
+
- int execv_git_cmd(const char **argv) {
++ git_set_exec_path(exec_path);
++ add_path(&new_path, exec_path);
+
+ if (old_path)
+ strbuf_addstr(&new_path, old_path);
+ else
+ strbuf_addstr(&new_path, _PATH_DEFPATH);
+
+ setenv("PATH", new_path.buf, 1);
+
+ strbuf_release(&new_path);
+}
+
+const char **prepare_git_cmd(struct argv_array *out, const char **argv)
+{
+ argv_array_push(out, "git");
+ argv_array_pushv(out, argv);
+ return out->argv;
+}
+
-
- int execl_git_cmd(const char *cmd,...)
++int execv_git_cmd(const char **argv)
++{
+ struct argv_array nargv = ARGV_ARRAY_INIT;
+
+ prepare_git_cmd(&nargv, argv);
+ trace_argv_printf(nargv.argv, "trace: exec:");
+
+ /* execvp() can only ever return if it fails */
+ sane_execvp("git", (char **)nargv.argv);
+
+ trace_printf("trace: exec failed: %s\n", strerror(errno));
+
+ argv_array_clear(&nargv);
+ return -1;
+}
+
++int execl_git_cmd(const char *cmd, ...)
+{
+ int argc;
+ const char *argv[MAX_ARGS + 1];
+ const char *arg;
+ 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);
+}
--- /dev/null
- extern void git_set_argv_exec_path(const char *exec_path);
- extern void git_extract_argv0_path(const char *path);
+#ifndef GIT_EXEC_CMD_H
+#define GIT_EXEC_CMD_H
+
+struct argv_array;
+
++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);
+extern int execv_git_cmd(const char **argv); /* NULL terminated */
+LAST_ARG_MUST_BE_NULL
+extern int execl_git_cmd(const char *cmd, ...);
+extern char *system_path(const char *path);
+
+#endif /* GIT_EXEC_CMD_H */
* Copyright (c) 2010 Ævar Arnfjörð Bjarmason
*/
- #include "git-compat-util.h"
+ #include "cache.h"
-#include "exec_cmd.h"
++#include "exec-cmd.h"
#include "gettext.h"
#include "strbuf.h"
#include "utf8.h"
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, "");
#include "builtin.h"
#include "config.h"
-#include "exec_cmd.h"
+#include "exec-cmd.h"
#include "help.h"
#include "run-command.h"
*/
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);
{ "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE },
{ "rm", cmd_rm, RUN_SETUP },
{ "send-pack", cmd_send_pack, RUN_SETUP },
+ { "serve", cmd_serve, RUN_SETUP },
{ "shortlog", cmd_shortlog, RUN_SETUP_GENTLY | USE_PAGER },
{ "show", cmd_show, RUN_SETUP },
{ "show-branch", cmd_show_branch, RUN_SETUP },
{ "update-server-info", cmd_update_server_info, RUN_SETUP },
{ "upload-archive", cmd_upload_archive, NO_PARSEOPT },
{ "upload-archive--writer", cmd_upload_archive_writer, NO_PARSEOPT },
+ { "upload-pack", cmd_upload_pack },
{ "var", cmd_var, RUN_SETUP_GENTLY | NO_PARSEOPT },
{ "verify-commit", cmd_verify_commit, RUN_SETUP },
{ "verify-pack", cmd_verify_pack },