From 74ca2faec75fae6e0162e967faeda8c7143ed299 Mon Sep 17 00:00:00 2001 From: Sebastian Schuberth Date: Wed, 4 Sep 2013 18:18:49 +0200 Subject: [PATCH 01/21] Makefile: Set htmldir to match the default HTML docs location under MSYS Signed-off-by: Sebastian Schuberth --- config.mak.uname | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.mak.uname b/config.mak.uname index 6b17c6110d..480c3d3e23 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -597,7 +597,7 @@ ifneq (,$(findstring MINGW,$(uname_S))) X = .exe SPARSE_FLAGS = -Wno-one-bit-signed-bitfield ifneq (,$(wildcard ../THIS_IS_MSYSGIT)) - htmldir = doc/git/html/ + htmldir = share/doc/git/$(firstword $(subst -, ,$(GIT_VERSION)))/html prefix = INSTALL = /bin/install EXTLIBS += /mingw/lib/libz.a From 08bef8af5cd4e56968bcf7436395a7dd565a0bec Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 20 Feb 2015 09:52:07 +0000 Subject: [PATCH 02/21] Help debugging with MSys2 by optionally executing bash with strace MSys2's strace facility is very useful for debugging... With this patch, the bash will be executed through strace if the environment variable GIT_STRACE_COMMANDS is set, which comes in real handy when investigating issues in the test suite. Also support passing a path to a log file via GIT_STRACE_COMMANDS to force Git to call strace.exe with the `-o ` argument, i.e. to log into a file rather than print the log directly. That comes in handy when the output would otherwise misinterpreted by a calling process as part of Git's output. Note: the values "1", "yes" or "true" are *not* specifying paths, but tell Git to let strace.exe log directly to the console. Signed-off-by: Johannes Schindelin --- compat/mingw.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/compat/mingw.c b/compat/mingw.c index 941ebad6ee..16e189fe33 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -1410,6 +1410,7 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen HANDLE cons; const char *(*quote_arg)(const char *arg) = is_msys2_sh(*argv) ? quote_arg_msys2 : quote_arg_msvc; + const char *strace_env; do_unset_environment_variables(); @@ -1467,6 +1468,31 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen free(quoted); } + strace_env = getenv("GIT_STRACE_COMMANDS"); + if (strace_env) { + char *p = path_lookup("strace.exe", 1); + if (!p) + return error("strace not found!"); + if (xutftowcs_path(wcmd, p) < 0) { + free(p); + return -1; + } + free(p); + if (!strcmp("1", strace_env) || + !strcasecmp("yes", strace_env) || + !strcasecmp("true", strace_env)) + strbuf_insert(&args, 0, "strace ", 7); + else { + const char *quoted = quote_arg(strace_env); + struct strbuf buf = STRBUF_INIT; + strbuf_addf(&buf, "strace -o %s ", quoted); + if (quoted != strace_env) + free((char *)quoted); + strbuf_insert(&args, 0, buf.buf, buf.len); + strbuf_release(&buf); + } + } + ALLOC_ARRAY(wargs, st_add(st_mult(2, args.len), 1)); xutftowcs(wargs, args.buf, 2 * args.len + 1); strbuf_release(&args); From 9b66ab2b5f4b15e67cbaf28a0409ac5a847154dc Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 16 Feb 2015 14:06:59 +0100 Subject: [PATCH 03/21] Build Python stuff with MSys2 Signed-off-by: Johannes Schindelin --- config.mak.uname | 1 + 1 file changed, 1 insertion(+) diff --git a/config.mak.uname b/config.mak.uname index 480c3d3e23..a31f6d7594 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -640,6 +640,7 @@ else NO_LIBPCRE1_JIT = UnfortunatelyYes NO_CURL = USE_NED_ALLOCATOR = YesPlease + NO_PYTHON = else COMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO NO_CURL = YesPlease From b302fac631d7a59334de83c76571ba0ce2a6045a Mon Sep 17 00:00:00 2001 From: Cesar Eduardo Barros Date: Mon, 9 Mar 2015 08:51:38 +0100 Subject: [PATCH 04/21] mingw: Embed a manifest to trick UAC into Doing The Right Thing On Windows >= Vista, not having an application manifest with a requestedExecutionLevel can cause several kinds of confusing behavior. The first and more obvious behavior is "Installer Detection", where Windows sometimes decides (by looking at things like the file name and even sequences of bytes within the executable) that an executable is an installer and should run elevated (causing the well-known popup dialog to appear). In Git's context, subcommands such as "git patch-id" or "git update-index" fall prey to this behavior. The second and more confusing behavior is "File Virtualization". It means that when files are written without having write permission, it does not fail (as expected), but they are instead redirected to somewhere else. When the files are read, the original contents are returned, though, not the ones that were just written somewhere else. Even more confusing, not all write accesses are redirected; Trying to write to write-protected .exe files, for example, will fail instead of redirecting. In addition to being unwanted behavior, File Virtualization causes dramatic slowdowns in Git (see for instance http://code.google.com/p/msysgit/issues/detail?id=320). There are two ways to prevent those two behaviors: Either you embed an application manifest within all your executables, or you add an external manifest (a file with the same name followed by .manifest) to all your executables. Since Git's builtins are hardlinked (or copied), it is simpler and more robust to embed a manifest. A recent enough MSVC compiler should already embed a working internal manifest, but for MinGW you have to do so by hand. Very lightly tested on Wine, where like on Windows XP it should not make any difference. References: - New UAC Technologies for Windows Vista http://msdn.microsoft.com/en-us/library/bb756960.aspx - Create and Embed an Application Manifest (UAC) http://msdn.microsoft.com/en-us/library/bb756929.aspx [js: simplified the embedding dramatically by reusing Git for Windows' existing Windows resource file, removed the optional (and dubious) processorArchitecture attribute of the manifest's assemblyIdentity section.] Signed-off-by: Cesar Eduardo Barros Signed-off-by: Johannes Schindelin --- compat/win32/git.manifest | 25 +++++++++++++++++++++++++ git.rc | 2 ++ 2 files changed, 27 insertions(+) create mode 100644 compat/win32/git.manifest diff --git a/compat/win32/git.manifest b/compat/win32/git.manifest new file mode 100644 index 0000000000..771e3cce43 --- /dev/null +++ b/compat/win32/git.manifest @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/git.rc b/git.rc index 49002e0d54..cc3fdc6cc6 100644 --- a/git.rc +++ b/git.rc @@ -20,3 +20,5 @@ BEGIN VALUE "Translation", 0x409, 1200 END END + +1 RT_MANIFEST "compat/win32/git.manifest" From b13804c4ee8c3c4ca57d75e029a4ff8a85fd804c Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 2 Nov 2015 08:41:10 +0100 Subject: [PATCH 05/21] mingw: enable stack smashing protector As suggested privately to Brendan Forster by some unnamed person (suggestion for the future: use the public mailing list, or even the public GitHub issue tracker, that is a much better place to offer such suggestions), we should make use of gcc's stack smashing protector that helps detect stack buffer overruns early. Rather than using -fstack-protector, we use -fstack-protector-strong because it strikes a better balance between how much code is affected and the performance impact. In a local test (time git log --grep=is -p), best of 5 timings went from 23.009s to 22.997s (i.e. the performance impact was *well* lost in the noise). This fixes https://github.com/git-for-windows/git/issues/501 Signed-off-by: Johannes Schindelin --- config.mak.uname | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config.mak.uname b/config.mak.uname index a31f6d7594..1176b6f7a6 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -628,7 +628,8 @@ else BASIC_LDFLAGS += -Wl,--large-address-aware endif CC = gcc - COMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO=0 -DDETECT_MSYS_TTY + COMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO=0 -DDETECT_MSYS_TTY \ + -fstack-protector-strong EXTLIBS += -lntdll INSTALL = /bin/install NO_R_TO_GCC_LINKER = YesPlease From 6f0b4c4cdff7eb761f92be6b51c4b2babfc9c8f1 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 6 Apr 2015 10:37:04 +0100 Subject: [PATCH 06/21] Avoid illegal filenames when building Documentation on NTFS A '+' is not a valid part of a filename with Windows file systems (it is reserved because the '+' operator meant file concatenation back in the DOS days). Let's just not use it. Signed-off-by: Johannes Schindelin --- Documentation/Makefile | 88 +++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/Documentation/Makefile b/Documentation/Makefile index d5d936e6a7..1adcb60df3 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -287,9 +287,9 @@ docdep_prereqs = \ cmd-list.made $(cmds_txt) doc.dep : $(docdep_prereqs) $(wildcard *.txt) $(wildcard config/*.txt) build-docdep.perl - $(QUIET_GEN)$(RM) $@+ $@ && \ - $(PERL_PATH) ./build-docdep.perl >$@+ $(QUIET_STDERR) && \ - mv $@+ $@ + $(QUIET_GEN)$(RM) $@.new $@ && \ + $(PERL_PATH) ./build-docdep.perl >$@.new $(QUIET_STDERR) && \ + mv $@.new $@ -include doc.dep @@ -325,8 +325,8 @@ mergetools-list.made: ../git-mergetool--lib.sh $(wildcard ../mergetools/*) date >$@ clean: - $(RM) *.xml *.xml+ *.html *.html+ *.1 *.5 *.7 - $(RM) *.texi *.texi+ *.texi++ git.info gitman.info + $(RM) *.xml *.xml.new *.html *.html.new *.1 *.5 *.7 + $(RM) *.texi *.texi.new *.texi.new.new git.info gitman.info $(RM) *.pdf $(RM) howto-index.txt howto/*.html doc.dep $(RM) technical/*.html technical/api-index.txt @@ -335,14 +335,14 @@ clean: $(RM) manpage-base-url.xsl $(MAN_HTML): %.html : %.txt asciidoc.conf - $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ - $(TXT_TO_HTML) -d manpage -o $@+ $< && \ - mv $@+ $@ + $(QUIET_ASCIIDOC)$(RM) $@.new $@ && \ + $(TXT_TO_HTML) -d manpage -o $@.new $< && \ + mv $@.new $@ $(OBSOLETE_HTML): %.html : %.txto asciidoc.conf - $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ - $(TXT_TO_HTML) -o $@+ $< && \ - mv $@+ $@ + $(QUIET_ASCIIDOC)$(RM) $@.new $@ && \ + $(TXT_TO_HTML) -o $@.new $< && \ + mv $@.new $@ manpage-base-url.xsl: manpage-base-url.xsl.in $(QUIET_GEN)sed "s|@@MAN_BASE_URL@@|$(MAN_BASE_URL)|" $< > $@ @@ -352,14 +352,14 @@ manpage-base-url.xsl: manpage-base-url.xsl.in $(XMLTO) -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $< %.xml : %.txt asciidoc.conf - $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ - $(TXT_TO_XML) -d manpage -o $@+ $< && \ - mv $@+ $@ + $(QUIET_ASCIIDOC)$(RM) $@.new $@ && \ + $(TXT_TO_XML) -d manpage -o $@.new $< && \ + mv $@.new $@ user-manual.xml: user-manual.txt user-manual.conf - $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ - $(TXT_TO_XML) -d book -o $@+ $< && \ - mv $@+ $@ + $(QUIET_ASCIIDOC)$(RM) $@.new $@ && \ + $(TXT_TO_XML) -d book -o $@.new $< && \ + mv $@.new $@ technical/api-index.txt: technical/api-index-skel.txt \ technical/api-index.sh $(patsubst %,%.txt,$(API_DOCS)) @@ -376,46 +376,46 @@ XSLT = docbook.xsl XSLTOPTS = --xinclude --stringparam html.stylesheet docbook-xsl.css user-manual.html: user-manual.xml $(XSLT) - $(QUIET_XSLTPROC)$(RM) $@+ $@ && \ - xsltproc $(XSLTOPTS) -o $@+ $(XSLT) $< && \ - mv $@+ $@ + $(QUIET_XSLTPROC)$(RM) $@.new $@ && \ + xsltproc $(XSLTOPTS) -o $@.new $(XSLT) $< && \ + mv $@.new $@ git.info: user-manual.texi $(QUIET_MAKEINFO)$(MAKEINFO) --no-split -o $@ user-manual.texi user-manual.texi: user-manual.xml - $(QUIET_DB2TEXI)$(RM) $@+ $@ && \ - $(DOCBOOK2X_TEXI) user-manual.xml --encoding=UTF-8 --to-stdout >$@++ && \ - $(PERL_PATH) fix-texi.perl <$@++ >$@+ && \ - rm $@++ && \ - mv $@+ $@ + $(QUIET_DB2TEXI)$(RM) $@.new $@ && \ + $(DOCBOOK2X_TEXI) user-manual.xml --encoding=UTF-8 --to-stdout >$@.new.new && \ + $(PERL_PATH) fix-texi.perl <$@.new.new >$@.new && \ + rm $@.new.new && \ + mv $@.new $@ user-manual.pdf: user-manual.xml - $(QUIET_DBLATEX)$(RM) $@+ $@ && \ - $(DBLATEX) -o $@+ $(DBLATEX_COMMON) $< && \ - mv $@+ $@ + $(QUIET_DBLATEX)$(RM) $@.new $@ && \ + $(DBLATEX) -o $@.new $(DBLATEX_COMMON) $< && \ + mv $@.new $@ gitman.texi: $(MAN_XML) cat-texi.perl texi.xsl - $(QUIET_DB2TEXI)$(RM) $@+ $@ && \ - ($(foreach xml,$(sort $(MAN_XML)),xsltproc -o $(xml)+ texi.xsl $(xml) && \ - $(DOCBOOK2X_TEXI) --encoding=UTF-8 --to-stdout $(xml)+ && \ - rm $(xml)+ &&) true) > $@++ && \ - $(PERL_PATH) cat-texi.perl $@ <$@++ >$@+ && \ - rm $@++ && \ - mv $@+ $@ + $(QUIET_DB2TEXI)$(RM) $@.new $@ && \ + ($(foreach xml,$(sort $(MAN_XML)),xsltproc -o $(xml).new texi.xsl $(xml) && \ + $(DOCBOOK2X_TEXI) --encoding=UTF-8 --to-stdout $(xml).new && \ + rm $(xml).new &&) true) > $@.new.new && \ + $(PERL_PATH) cat-texi.perl $@ <$@.new.new >$@.new && \ + rm $@.new.new && \ + mv $@.new $@ gitman.info: gitman.texi $(QUIET_MAKEINFO)$(MAKEINFO) --no-split --no-validate $*.texi $(patsubst %.txt,%.texi,$(MAN_TXT)): %.texi : %.xml - $(QUIET_DB2TEXI)$(RM) $@+ $@ && \ - $(DOCBOOK2X_TEXI) --to-stdout $*.xml >$@+ && \ - mv $@+ $@ + $(QUIET_DB2TEXI)$(RM) $@.new $@ && \ + $(DOCBOOK2X_TEXI) --to-stdout $*.xml >$@.new && \ + mv $@.new $@ howto-index.txt: howto-index.sh $(wildcard howto/*.txt) - $(QUIET_GEN)$(RM) $@+ $@ && \ - '$(SHELL_PATH_SQ)' ./howto-index.sh $(sort $(wildcard howto/*.txt)) >$@+ && \ - mv $@+ $@ + $(QUIET_GEN)$(RM) $@.new $@ && \ + '$(SHELL_PATH_SQ)' ./howto-index.sh $(sort $(wildcard howto/*.txt)) >$@.new && \ + mv $@.new $@ $(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt $(QUIET_ASCIIDOC)$(TXT_TO_HTML) $*.txt @@ -424,10 +424,10 @@ WEBDOC_DEST = /pub/software/scm/git/docs howto/%.html: ASCIIDOC_EXTRA += -a git-relative-html-prefix=../ $(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt - $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ + $(QUIET_ASCIIDOC)$(RM) $@.new $@ && \ sed -e '1,/^$$/d' $< | \ - $(TXT_TO_HTML) - >$@+ && \ - mv $@+ $@ + $(TXT_TO_HTML) - >$@.new && \ + mv $@.new $@ install-webdoc : html '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(WEBDOC_DEST) From 33a39d68b219ac89f4a7832e37476f1deb48cd00 Mon Sep 17 00:00:00 2001 From: Karsten Blees Date: Thu, 9 Apr 2015 16:19:56 +0100 Subject: [PATCH 07/21] gettext: always use UTF-8 on native Windows Git on native Windows exclusively uses UTF-8 for console output (both with mintty and native console windows). Gettext uses setlocale() to determine the output encoding for translated text, however, MSVCRT's setlocale() doesn't support UTF-8. As a result, translated text is encoded in system encoding (GetAPC()), and non-ASCII chars are mangled in console output. Use gettext's bind_textdomain_codeset() to force the encoding to UTF-8 on native Windows. In this developers' setup, HAVE_LIBCHARSET_H is apparently defined, but we *really* want to override the locale_charset() here. Signed-off-by: Karsten Blees --- gettext.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gettext.c b/gettext.c index d4021d690c..d8423e5c41 100644 --- a/gettext.c +++ b/gettext.c @@ -12,7 +12,9 @@ #ifndef NO_GETTEXT # include # include -# ifdef HAVE_LIBCHARSET_H +# ifdef GIT_WINDOWS_NATIVE +# define locale_charset() "UTF-8" +# elif defined HAVE_LIBCHARSET_H # include # else # include From c42c6444e84d47db79f07fbfc223c32e0a85aa95 Mon Sep 17 00:00:00 2001 From: Karsten Blees Date: Mon, 6 Apr 2015 21:37:18 +0200 Subject: [PATCH 08/21] mingw: initialize HOME on startup HOME initialization was historically duplicated in many different places, including /etc/profile, launch scripts such as git-bash.vbs and gitk.cmd, and (although slightly broken) in the git-wrapper. Even unrelated projects such as GitExtensions and TortoiseGit need to implement the same logic to be able to call git directly. Initialize HOME in git's own startup code so that we can eventually retire all the duplicate initialization code. Signed-off-by: Karsten Blees --- compat/mingw.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/compat/mingw.c b/compat/mingw.c index 16e189fe33..f47c083985 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -2553,6 +2553,30 @@ static void setup_windows_environment(void) /* simulate TERM to enable auto-color (see color.c) */ if (!getenv("TERM")) setenv("TERM", "cygwin", 1); + + /* calculate HOME if not set */ + if (!getenv("HOME")) { + /* + * try $HOMEDRIVE$HOMEPATH - the home share may be a network + * location, thus also check if the path exists (i.e. is not + * disconnected) + */ + if ((tmp = getenv("HOMEDRIVE"))) { + struct strbuf buf = STRBUF_INIT; + strbuf_addstr(&buf, tmp); + if ((tmp = getenv("HOMEPATH"))) { + strbuf_addstr(&buf, tmp); + if (is_directory(buf.buf)) + setenv("HOME", buf.buf, 1); + else + tmp = NULL; /* use $USERPROFILE */ + } + strbuf_release(&buf); + } + /* use $USERPROFILE if the home share is not available */ + if (!tmp && (tmp = getenv("USERPROFILE"))) + setenv("HOME", tmp, 1); + } } int handle_long_path(wchar_t *path, int len, int max_path, int expand) From 693d9b6f79b5f9a01fd61f5d40bb72f1e91c12aa Mon Sep 17 00:00:00 2001 From: nalla Date: Thu, 16 Apr 2015 11:45:05 +0100 Subject: [PATCH 09/21] mingw: explicitly `fflush` stdout For performance reasons `stdout` is not unbuffered by default. That leads to problems if after printing to `stdout` a read on `stdin` is performed. For that reason interactive commands like `git clean -i` do not function properly anymore if the `stdout` is not flushed by `fflush(stdout)` before trying to read from `stdin`. In the case of `git clean -i` all reads on `stdin` were preceded by a `fflush(stdout)` call. Signed-off-by: nalla --- builtin/clean.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/builtin/clean.c b/builtin/clean.c index bbcdeb2d9e..4bba03c680 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -577,6 +577,7 @@ static int *list_and_choose(struct menu_opts *opts, struct menu_stuff *stuff) clean_get_color(CLEAN_COLOR_RESET)); } + fflush(stdout); if (strbuf_getline_lf(&choice, stdin) != EOF) { strbuf_trim(&choice); } else { @@ -659,6 +660,7 @@ static int filter_by_patterns_cmd(void) clean_print_color(CLEAN_COLOR_PROMPT); printf(_("Input ignore patterns>> ")); clean_print_color(CLEAN_COLOR_RESET); + fflush(stdout); if (strbuf_getline_lf(&confirm, stdin) != EOF) strbuf_trim(&confirm); else @@ -757,6 +759,7 @@ static int ask_each_cmd(void) qname = quote_path_relative(item->string, NULL, &buf); /* TRANSLATORS: Make sure to keep [y/N] as is */ printf(_("Remove %s [y/N]? "), qname); + fflush(stdout); if (strbuf_getline_lf(&confirm, stdin) != EOF) { strbuf_trim(&confirm); } else { From 5a0fc8f366b8c7617576be409e4afa3f60f679cd Mon Sep 17 00:00:00 2001 From: Karsten Blees Date: Thu, 19 Mar 2015 16:33:44 +0100 Subject: [PATCH 10/21] mingw: Support `git_terminal_prompt` with more terminals The `git_terminal_prompt()` function expects the terminal window to be attached to a Win32 Console. However, this is not the case with terminal windows other than `cmd.exe`'s, e.g. with MSys2's own `mintty`. Non-cmd terminals such as `mintty` still have to have a Win32 Console to be proper console programs, but have to hide the Win32 Console to be able to provide more flexibility (such as being resizeable not only vertically but also horizontally). By writing to that Win32 Console, `git_terminal_prompt()` manages only to send the prompt to nowhere and to wait for input from a Console to which the user has no access. This commit introduces a function specifically to support `mintty` -- or other terminals that are compatible with MSys2's `/dev/tty` emulation. We use the `TERM` environment variable as an indicator for that: if the value starts with "xterm" (such as `mintty`'s "xterm_256color"), we prefer to let `xterm_prompt()` handle the user interaction. The most prominent user of `git_terminal_prompt()` is certainly `git-remote-https.exe`. It is an interesting use case because both `stdin` and `stdout` are redirected when Git calls said executable, yet it still wants to access the terminal. When running inside a `mintty`, the terminal is not accessible to the `git-remote-https.exe` program, though, because it is a MinGW program and the `mintty` terminal is not backed by a Win32 console. To solve that problem, we simply call out to the shell -- which is an *MSys2* program and can therefore access `/dev/tty`. Helped-by: nalla Signed-off-by: Karsten Blees Signed-off-by: Johannes Schindelin --- compat/terminal.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/compat/terminal.c b/compat/terminal.c index fa13ee672d..069f4061ed 100644 --- a/compat/terminal.c +++ b/compat/terminal.c @@ -1,7 +1,12 @@ +#ifndef NO_INTTYPES_H +#include +#endif #include "git-compat-util.h" +#include "run-command.h" #include "compat/terminal.h" #include "sigchain.h" #include "strbuf.h" +#include "cache.h" #if defined(HAVE_DEV_TTY) || defined(GIT_WINDOWS_NATIVE) @@ -91,6 +96,54 @@ static int disable_echo(void) return 0; } +static char *shell_prompt(const char *prompt, int echo) +{ + const char *read_input[] = { + /* Note: call 'bash' explicitly, as 'read -s' is bash-specific */ + "bash", "-c", echo ? + "cat >/dev/tty && read -r line /dev/tty && read -r -s line /dev/tty", + NULL + }; + struct child_process child = CHILD_PROCESS_INIT; + static struct strbuf buffer = STRBUF_INIT; + int prompt_len = strlen(prompt), len = -1, code; + + child.argv = read_input; + child.in = -1; + child.out = -1; + + if (start_command(&child)) + return NULL; + + if (write_in_full(child.in, prompt, prompt_len) != prompt_len) { + error("could not write to prompt script"); + close(child.in); + goto ret; + } + close(child.in); + + strbuf_reset(&buffer); + len = strbuf_read(&buffer, child.out, 1024); + if (len < 0) { + error("could not read from prompt script"); + goto ret; + } + + strbuf_strip_suffix(&buffer, "\n"); + strbuf_strip_suffix(&buffer, "\r"); + +ret: + close(child.out); + code = finish_command(&child); + if (code) { + error("failed to execute prompt script (exit code %d)", code); + return NULL; + } + + return len < 0 ? NULL : buffer.buf; +} + #endif #ifndef FORCE_TEXT @@ -102,6 +155,12 @@ char *git_terminal_prompt(const char *prompt, int echo) static struct strbuf buf = STRBUF_INIT; int r; FILE *input_fh, *output_fh; +#ifdef GIT_WINDOWS_NATIVE + const char *term = getenv("TERM"); + + if (term && starts_with(term, "xterm")) + return shell_prompt(prompt, echo); +#endif input_fh = fopen(INPUT_PATH, "r" FORCE_TEXT); if (!input_fh) From 7f87edc555577b66eb7e5c137e385b1cd1071dc7 Mon Sep 17 00:00:00 2001 From: Karsten Blees Date: Sat, 9 May 2015 02:11:48 +0200 Subject: [PATCH 11/21] compat/terminal.c: only use the Windows console if bash 'read -r' fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Accessing the Windows console through the special CONIN$ / CONOUT$ devices doesn't work properly for non-ASCII usernames an passwords. It also doesn't work for terminal emulators that hide the native console window (such as mintty), and 'TERM=xterm*' is not necessarily a reliable indicator for such terminals. The new shell_prompt() function, on the other hand, works fine for both MSys1 and MSys2, in native console windows as well as mintty, and properly supports Unicode. It just needs bash on the path (for 'read -s', which is bash-specific). On Windows, try to use the shell to read from the terminal. If that fails with ENOENT (i.e. bash was not found), use CONIN/OUT as fallback. Note: To test this, create a UTF-8 credential file with non-ASCII chars, e.g. in git-bash: 'echo url=http://täst.com > cred.txt'. Then in git-cmd, 'git credential fill --- compat/terminal.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/compat/terminal.c b/compat/terminal.c index 069f4061ed..d9d3945afa 100644 --- a/compat/terminal.c +++ b/compat/terminal.c @@ -112,6 +112,7 @@ static char *shell_prompt(const char *prompt, int echo) child.argv = read_input; child.in = -1; child.out = -1; + child.silent_exec_failure = 1; if (start_command(&child)) return NULL; @@ -155,11 +156,14 @@ char *git_terminal_prompt(const char *prompt, int echo) static struct strbuf buf = STRBUF_INIT; int r; FILE *input_fh, *output_fh; -#ifdef GIT_WINDOWS_NATIVE - const char *term = getenv("TERM"); - if (term && starts_with(term, "xterm")) - return shell_prompt(prompt, echo); +#ifdef GIT_WINDOWS_NATIVE + + /* try shell_prompt first, fall back to CONIN/OUT if bash is missing */ + char *result = shell_prompt(prompt, echo); + if (result || errno != ENOENT) + return result; + #endif input_fh = fopen(INPUT_PATH, "r" FORCE_TEXT); From 61340655700fd0a5a4347cbab0941604befb4ae0 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 10 Jan 2017 23:14:20 +0100 Subject: [PATCH 12/21] winansi: simplify loading the GetCurrentConsoleFontEx() function We introduced helper macros to simplify loading functions dynamically. Might just as well use them. Signed-off-by: Johannes Schindelin --- compat/winansi.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/compat/winansi.c b/compat/winansi.c index 11cd9b82cc..efc0abcdac 100644 --- a/compat/winansi.c +++ b/compat/winansi.c @@ -7,6 +7,7 @@ #include #include #include "win32.h" +#include "win32/lazyload.h" static int fd_is_interactive[3] = { 0, 0, 0 }; #define FD_CONSOLE 0x1 @@ -41,26 +42,21 @@ typedef struct _CONSOLE_FONT_INFOEX { #endif #endif -typedef BOOL (WINAPI *PGETCURRENTCONSOLEFONTEX)(HANDLE, BOOL, - PCONSOLE_FONT_INFOEX); - static void warn_if_raster_font(void) { DWORD fontFamily = 0; - PGETCURRENTCONSOLEFONTEX pGetCurrentConsoleFontEx; + DECLARE_PROC_ADDR(kernel32.dll, BOOL, GetCurrentConsoleFontEx, + HANDLE, BOOL, PCONSOLE_FONT_INFOEX); /* don't bother if output was ascii only */ if (!non_ascii_used) return; /* GetCurrentConsoleFontEx is available since Vista */ - pGetCurrentConsoleFontEx = (PGETCURRENTCONSOLEFONTEX) GetProcAddress( - GetModuleHandle("kernel32.dll"), - "GetCurrentConsoleFontEx"); - if (pGetCurrentConsoleFontEx) { + if (INIT_PROC_ADDR(GetCurrentConsoleFontEx)) { CONSOLE_FONT_INFOEX cfi; cfi.cbSize = sizeof(cfi); - if (pGetCurrentConsoleFontEx(console, 0, &cfi)) + if (GetCurrentConsoleFontEx(console, 0, &cfi)) fontFamily = cfi.FontFamily; } else { /* pre-Vista: check default console font in registry */ From 1ce3f5f052addf85b9cbe3a7d270f98feaa09851 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 6 Sep 2016 09:50:33 +0200 Subject: [PATCH 13/21] Unbreak interactive GPG prompt upon signing With the recent update in efee955 (gpg-interface: check gpg signature creation status, 2016-06-17), we ask GPG to send all status updates to stderr, and then catch the stderr in an strbuf. But GPG might fail, and send error messages to stderr. And we simply do not show them to the user. Even worse: this swallows any interactive prompt for a passphrase. And detaches stderr from the tty so that the passphrase cannot be read. So while the first problem could be fixed (by printing the captured stderr upon error), the second problem cannot be easily fixed, and presents a major regression. So let's just revert commit efee9553a4f97b2ecd8f49be19606dd4cf7d9c28. This fixes https://github.com/git-for-windows/git/issues/871 Cc: Michael J Gruber Signed-off-by: Johannes Schindelin --- gpg-interface.c | 8 ++------ t/t7004-tag.sh | 13 ------------- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/gpg-interface.c b/gpg-interface.c index 8ed274533f..24348691f8 100644 --- a/gpg-interface.c +++ b/gpg-interface.c @@ -293,11 +293,9 @@ int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *sig struct child_process gpg = CHILD_PROCESS_INIT; int ret; size_t i, j, bottom; - struct strbuf gpg_status = STRBUF_INIT; argv_array_pushl(&gpg.args, use_format->program, - "--status-fd=2", "-bsau", signing_key, NULL); @@ -309,12 +307,10 @@ int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *sig */ sigchain_push(SIGPIPE, SIG_IGN); ret = pipe_command(&gpg, buffer->buf, buffer->len, - signature, 1024, &gpg_status, 0); + signature, 1024, NULL, 0); sigchain_pop(SIGPIPE); - ret |= !strstr(gpg_status.buf, "\n[GNUPG:] SIG_CREATED "); - strbuf_release(&gpg_status); - if (ret) + if (ret || signature->len == bottom) return error(_("gpg failed to sign the data")); /* Strip CR from the line endings, in case we are on Windows. */ diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh index 0b01862c23..a05df0d7b6 100755 --- a/t/t7004-tag.sh +++ b/t/t7004-tag.sh @@ -1345,12 +1345,6 @@ test_expect_success GPG \ 'test_config user.signingkey BobTheMouse && test_must_fail git tag -s -m tail tag-gpg-failure' -# try to produce invalid signature -test_expect_success GPG \ - 'git tag -s fails if gpg is misconfigured (bad signature format)' \ - 'test_config gpg.program echo && - test_must_fail git tag -s -m tail tag-gpg-failure' - # try to sign with bad user.signingkey test_expect_success GPGSM \ 'git tag -s fails if gpgsm is misconfigured (bad key)' \ @@ -1358,13 +1352,6 @@ test_expect_success GPGSM \ test_config gpg.format x509 && test_must_fail git tag -s -m tail tag-gpg-failure' -# try to produce invalid signature -test_expect_success GPGSM \ - 'git tag -s fails if gpgsm is misconfigured (bad signature format)' \ - 'test_config gpg.x509.program echo && - test_config gpg.format x509 && - test_must_fail git tag -s -m tail tag-gpg-failure' - # try to verify without gpg: rm -rf gpghome From e2184c65e9f169e374937d6920ade29a9bbec56a Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 21 Feb 2017 13:28:58 +0100 Subject: [PATCH 14/21] mingw: ensure valid CTYPE A change between versions 2.4.1 and 2.6.0 of the MSYS2 runtime modified how Cygwin's runtime (and hence Git for Windows' MSYS2 runtime derivative) handles locales: d16a56306d (Consolidate wctomb/mbtowc calls for POSIX-1.2008, 2016-07-20). An unintended side-effect is that "cold-calling" into the POSIX emulation will start with a locale based on the current code page, something that Git for Windows is very ill-prepared for, as it expects to be able to pass a command-line containing non-ASCII characters to the shell without having those characters munged. One symptom of this behavior: when `git clone` or `git fetch` shell out to call `git-upload-pack` with a path that contains non-ASCII characters, the shell tried to interpret the entire command-line (including command-line parameters) as executable path, which obviously must fail. This fixes https://github.com/git-for-windows/git/issues/1036 Signed-off-by: Johannes Schindelin --- compat/mingw.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compat/mingw.c b/compat/mingw.c index f47c083985..2b7514ad8e 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -2577,6 +2577,9 @@ static void setup_windows_environment(void) if (!tmp && (tmp = getenv("USERPROFILE"))) setenv("HOME", tmp, 1); } + + if (!getenv("LC_ALL") && !getenv("LC_CTYPE") && !getenv("LANG")) + setenv("LC_CTYPE", "C", 1); } int handle_long_path(wchar_t *path, int len, int max_path, int expand) From bcaffce850496117ec530f5374a4335df53db9f1 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 21 Feb 2017 20:34:38 +0100 Subject: [PATCH 15/21] mingw: make is_hidden tests in t0001/t5611 more robust We should not actually expect the first `attrib.exe` in the PATH to be the one we are looking for. Or that it is in the PATH, for that matter. Signed-off-by: Johannes Schindelin --- t/t0001-init.sh | 2 +- t/t5611-clone-config.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/t/t0001-init.sh b/t/t0001-init.sh index 0ba28c72a0..44e7e14983 100755 --- a/t/t0001-init.sh +++ b/t/t0001-init.sh @@ -400,7 +400,7 @@ test_expect_success SYMLINKS 're-init to move gitdir symlink' ' # Tests for the hidden file attribute on windows is_hidden () { # Use the output of `attrib`, ignore the absolute path - case "$(attrib "$1")" in *H*?:*) return 0;; esac + case "$("$SYSTEMROOT"/system32/attrib "$1")" in *H*?:*) return 0;; esac return 1 } diff --git a/t/t5611-clone-config.sh b/t/t5611-clone-config.sh index 39329eb7a8..50e2d5fa94 100755 --- a/t/t5611-clone-config.sh +++ b/t/t5611-clone-config.sh @@ -48,7 +48,7 @@ test_expect_success 'clone -c config is available during clone' ' # Tests for the hidden file attribute on windows is_hidden () { # Use the output of `attrib`, ignore the absolute path - case "$(attrib "$1")" in *H*?:*) return 0;; esac + case "$("$SYSTEMROOT"/system32/attrib "$1")" in *H*?:*) return 0;; esac return 1 } From 885e584f2ab6cbcd51a72797fe5605f53ffa29a1 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 5 Oct 2017 11:48:16 +0200 Subject: [PATCH 16/21] diff: munmap() file contents before running external diff When running an external diff from, say, a diff tool, it is safe to assume that we want to write the files in question. On Windows, that means that there cannot be any other process holding an open handle to said files. So let's make sure that `git diff` itself is not holding any open handle to the files in question. This fixes https://github.com/git-for-windows/git/issues/1315 Signed-off-by: Johannes Schindelin --- diff.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/diff.c b/diff.c index dc9965e836..b06759efa4 100644 --- a/diff.c +++ b/diff.c @@ -4136,6 +4136,10 @@ static void run_external_diff(const char *pgm, argv_array_pushf(&env, "GIT_DIFF_PATH_COUNTER=%d", ++o->diff_path_counter); argv_array_pushf(&env, "GIT_DIFF_PATH_TOTAL=%d", q->nr); + if (one && one->should_munmap) + diff_free_filespec_data(one); + if (two && two->should_munmap) + diff_free_filespec_data(two); if (run_command_v_opt_cd_env(argv.argv, RUN_USING_SHELL, NULL, env.argv)) die(_("external diff died, stopping at %s"), name); From 50559878fc7b668c1934087de524be8ee097b5cc Mon Sep 17 00:00:00 2001 From: Sebastian Schuberth Date: Thu, 29 Aug 2013 13:09:27 +0200 Subject: [PATCH 17/21] MinGW: Use MakeMaker to build the Perl libraries This way the libraries get properly installed into the "site_perl" directory and we just have to move them out of the "mingw" directory. Signed-off-by: Sebastian Schuberth --- config.mak.uname | 1 - 1 file changed, 1 deletion(-) diff --git a/config.mak.uname b/config.mak.uname index 1176b6f7a6..170e4f4f2d 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -568,7 +568,6 @@ ifneq (,$(findstring MINGW,$(uname_S))) NO_STRTOUMAX = YesPlease NO_MKDTEMP = YesPlease NO_SVN_TESTS = YesPlease - NO_PERL_MAKEMAKER = YesPlease RUNTIME_PREFIX = YesPlease HAVE_WPGMPTR = YesWeDo NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease From b68e7bb91c10d50eaa93b860bb6c9bfb3bfcdef0 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 20 Feb 2015 14:21:04 +0000 Subject: [PATCH 18/21] Tests: optionally skip redirecting stdin/stdout/stderr There is a really useful debugging technique developed by Sverre Rabbelier that inserts "bash &&" somewhere in the test scripts, letting the developer interact at given points with the current state. Another debugging technique, used a lot by this here coder, is to run certain executables via gdb by guarding a "gdb -args" call in bin-wrappers/git. Both techniques were disabled by 781f76b1(test-lib: redirect stdin of tests). Let's reinstate the ability to run an interactive shell by making the redirection optional: setting the TEST_NO_REDIRECT environment variable will skip the redirection. Signed-off-by: Johannes Schindelin --- t/test-lib.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/t/test-lib.sh b/t/test-lib.sh index 23ec58032f..9925286c7d 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -746,7 +746,12 @@ test_eval_ () { # be _inside_ the block to avoid polluting the "set -x" output # - test_eval_inner_ "$@" &3 2>&4 + if test -n "$TEST_NO_REDIRECT" + then + test_eval_inner_ "$@" + else + test_eval_inner_ "$@" &3 2>&4 + fi { test_eval_ret_=$? if want_trace From cdf913351fe3e4c5bb166e4d03c269c0a79766a8 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 23 Feb 2015 15:55:47 +0000 Subject: [PATCH 19/21] Skip t9020 with MSys2 POSIX-to-Windows path mangling would make it fail. Signed-off-by: Johannes Schindelin --- t/t9020-remote-svn.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/t/t9020-remote-svn.sh b/t/t9020-remote-svn.sh index 6fca08e5e3..76d9be2e1d 100755 --- a/t/t9020-remote-svn.sh +++ b/t/t9020-remote-svn.sh @@ -12,6 +12,12 @@ then test_done fi +if test_have_prereq MINGW +then + skip_all='skipping remote-svn tests for lack of POSIX' + test_done +fi + # Override svnrdump with our simulator PATH="$HOME:$PATH" export PATH PYTHON_PATH GIT_BUILD_DIR From 08007a6ece98a8433284e14feff58891b9ad9981 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 11 Jan 2017 21:08:15 +0100 Subject: [PATCH 20/21] t9116: work around hard-to-debug hangs As of a couple of weeks ago, t9116 hangs sometimes -- but not always! -- when being run in the Git for Windows SDK. The issue seems to be related to redirection via a pipe, but it is really hard to diagnose, what with git.exe (a non-MSYS2 program) calling a Perl script (which is executed by an MSYS2 Perl), piping into another MSYS2 program. As hunting time is scarce these days, simply work around this for now and leave the real diagnosis and resolution for later. Signed-off-by: Johannes Schindelin --- t/t9116-git-svn-log.sh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/t/t9116-git-svn-log.sh b/t/t9116-git-svn-log.sh index 45773ee560..0a9f1ef366 100755 --- a/t/t9116-git-svn-log.sh +++ b/t/t9116-git-svn-log.sh @@ -43,14 +43,18 @@ test_expect_success 'setup repository and import' ' test_expect_success 'run log' " git reset --hard origin/a && - git svn log -r2 origin/trunk | grep ^r2 && - git svn log -r4 origin/trunk | grep ^r4 && - git svn log -r3 | grep ^r3 + git svn log -r2 origin/trunk >out && + grep ^r2 out && + git svn log -r4 origin/trunk >out && + grep ^r4 out && + git svn log -r3 >out && + grep ^r3 out " test_expect_success 'run log against a from trunk' " git reset --hard origin/trunk && - git svn log -r3 origin/a | grep ^r3 + git svn log -r3 origin/a >out && + grep ^r3 out " printf 'r1 \nr2 \nr4 \n' > expected-range-r1-r2-r4 From 0ecb29049df2a53f634e8bed2b1d39258a22bb76 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 11 Jan 2017 21:08:15 +0100 Subject: [PATCH 21/21] t9001: work around hard-to-debug hangs Just like the workaround we added for t9116, t9001.83 hangs sometimes -- but not always! -- when being run in the Git for Windows SDK. The issue seems to be related to redirection via a pipe, but it is really hard to diagnose, what with git.exe (a non-MSYS2 program) calling a Perl script (which is executed by an MSYS2 Perl), piping into another MSYS2 program. As hunting time is scarce these days, simply work around this for now and leave the real diagnosis and resolution for later. Signed-off-by: Johannes Schindelin --- t/t9001-send-email.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index ee1efcc59d..748e263169 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -1180,8 +1180,8 @@ test_expect_success $PREREQ 'in-reply-to but no threading' ' --to=nobody@example.com \ --in-reply-to="" \ --no-thread \ - $patches | - grep "In-Reply-To: " + $patches >out && + grep "In-Reply-To: " out ' test_expect_success $PREREQ 'no in-reply-to and no threading' '