From 74c9625fa922ccc9d6af6090d95e749e1b24ed2a Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 14 Mar 2017 12:25:48 +0100 Subject: [PATCH 1/3] gettext: handle GIT_TEXTDOMAINDIR relative to $(prefix) On Windows, there is no single root directory. And what Git thinks is a root directory is not a root directory at all: everything is relative to the location where Git is installed. To handle this situation better, let's just allow for GIT_TEXTDOMAINDIR to be a path relative to the (runtime) prefix. To that end, we have to switch the order in which common-main handles argv0 and sets up gettext: in order to have access to the runtime prefix, we need it to be inferred from argv0 already. This patch also prepares for GIT_LOCALE_PATH to be relative to prefix, which is the even more important fix. Signed-off-by: Johannes Schindelin --- common-main.c | 4 ++-- gettext.c | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/common-main.c b/common-main.c index 6a689007e7..51a946f2d9 100644 --- a/common-main.c +++ b/common-main.c @@ -32,12 +32,12 @@ int main(int argc, const char **argv) */ sanitize_stdfds(); + git_extract_argv0_path(argv[0]); + git_setup_gettext(); attr_start(); - git_extract_argv0_path(argv[0]); - restore_sigpipe_to_default(); return cmd_main(argc, argv); diff --git a/gettext.c b/gettext.c index db727ea020..4dab914902 100644 --- a/gettext.c +++ b/gettext.c @@ -6,6 +6,8 @@ #include "gettext.h" #include "strbuf.h" #include "utf8.h" +#include "cache.h" +#include "exec_cmd.h" #ifndef NO_GETTEXT # include @@ -158,14 +160,20 @@ static void init_gettext_charset(const char *domain) void git_setup_gettext(void) { const char *podir = getenv("GIT_TEXTDOMAINDIR"); + char *p = NULL; if (!podir) podir = GIT_LOCALE_PATH; + if (!is_absolute_path(podir)) + podir = p = system_path(podir); + bindtextdomain("git", podir); setlocale(LC_MESSAGES, ""); setlocale(LC_TIME, ""); init_gettext_charset("git"); textdomain("git"); + + free(p); } /* return the number of columns of string 's' in current locale */ From 7c4f7f0c52954356a5e90ca2afc0cfa2f07bee55 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 14 Mar 2017 12:25:48 +0100 Subject: [PATCH 2/3] gettext: use a GIT_LOCALE_PATH relative to $(prefix) On Windows, we simply pass a POSIX path to bindtextdomain(), relying on the current libintl-8.dll implementation to handle that gracefully by resolving the path relative to the "root" directory inferred from the location of the .dll file itself. However, not only does this rely on the custom patches of the gettext library as shipped with MSYS2 (gettext's own source code is not prepared to handle POSIX paths on Windows), it also means that Git itself cannot use the `podir` variable at all because it does not handle absolute POSIX paths in system_path() correctly, leaving them as-is. This patch fixes that behavior by always using a GIT_LOCALE_PATH relative to the (runtime) prefix. Signed-off-by: Johannes Schindelin --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7f40f76739..a8089c5891 100644 --- a/Makefile +++ b/Makefile @@ -488,6 +488,7 @@ lib = lib # DESTDIR = pathsep = : +localedir_relative = $(patsubst $(prefix)/%,%,$(localedir)) mandir_relative = $(patsubst $(prefix)/%,%,$(mandir)) infodir_relative = $(patsubst $(prefix)/%,%,$(infodir)) htmldir_relative = $(patsubst $(prefix)/%,%,$(htmldir)) @@ -1735,6 +1736,7 @@ bindir_relative_SQ = $(subst ','\'',$(bindir_relative)) mandir_relative_SQ = $(subst ','\'',$(mandir_relative)) infodir_relative_SQ = $(subst ','\'',$(infodir_relative)) localedir_SQ = $(subst ','\'',$(localedir)) +localedir_relative_SQ = $(subst ','\'',$(localedir_relative)) gitexecdir_SQ = $(subst ','\'',$(gitexecdir)) template_dir_SQ = $(subst ','\'',$(template_dir)) htmldir_relative_SQ = $(subst ','\'',$(htmldir_relative)) @@ -2171,7 +2173,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 From ca884c9e108be67a8d27abae9e8428e3042c83c7 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 14 Mar 2017 12:39:54 +0100 Subject: [PATCH 3/3] gettext: avoid initialization if the locale dir is not present The runtime of a simple `git.exe version` call on Windows is currently dominated by the gettext setup, adding a whopping ~150ms to the ~210ms total. Given that this cost is added to each and every git.exe invocation goes through common-main's invocation of git_setup_gettext(), and given that scripts have to call git.exe dozens, if not hundreds, of times, this is a substantial performance penalty. This is particularly pointless when considering that Git for Windows ships without localization (to keep the installer's size to a bearable ~34MB): all that time setting up gettext is for naught. So let's be smart about it and skip setting up gettext if the locale directory is not even present. Signed-off-by: Johannes Schindelin --- gettext.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/gettext.c b/gettext.c index 4dab914902..cf0e4a2441 100644 --- a/gettext.c +++ b/gettext.c @@ -167,11 +167,13 @@ void git_setup_gettext(void) if (!is_absolute_path(podir)) podir = p = system_path(podir); - bindtextdomain("git", podir); - setlocale(LC_MESSAGES, ""); - setlocale(LC_TIME, ""); - init_gettext_charset("git"); - textdomain("git"); + if (is_directory(podir)) { + bindtextdomain("git", podir); + setlocale(LC_MESSAGES, ""); + setlocale(LC_TIME, ""); + init_gettext_charset("git"); + textdomain("git"); + } free(p); }