]> git.ipfire.org Git - thirdparty/git.git/commitdiff
terminal: accommodate Git for Windows' default terminal
authorJohannes Schindelin <johannes.schindelin@gmx.de>
Tue, 14 Jan 2020 18:43:48 +0000 (18:43 +0000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 15 Jan 2020 20:06:17 +0000 (12:06 -0800)
Git for Windows' Git Bash runs in MinTTY by default, which does not have
a Win32 Console instance, but uses MSYS2 pseudo terminals instead.

This is a problem, as Git for Windows does not want to use the MSYS2
emulation layer for Git itself, and therefore has no direct way to
interact with that pseudo terminal.

As a workaround, use the `stty` utility (which is included in Git for
Windows, and which *is* an MSYS2 program, so it knows how to deal with
the pseudo terminal).

Note: If Git runs in a regular CMD or PowerShell window, there *is* a
regular Win32 Console to work with. This is not a problem for the MSYS2
`stty`: it copes with this scenario just fine.

Also note that we introduce support for more bits than would be
necessary for a mere `disable_echo()` here, in preparation for the
upcoming `enable_non_canonical()` function.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
compat/terminal.c

index 1fb40b3a0a9950c46f9800eb3d32bb48953cb582..16e9949da10e5d9af64cc251595eb8861888b8ff 100644 (file)
@@ -2,6 +2,8 @@
 #include "compat/terminal.h"
 #include "sigchain.h"
 #include "strbuf.h"
+#include "run-command.h"
+#include "string-list.h"
 
 #if defined(HAVE_DEV_TTY) || defined(GIT_WINDOWS_NATIVE)
 
@@ -64,11 +66,28 @@ static int disable_echo(void)
 #define OUTPUT_PATH "CONOUT$"
 #define FORCE_TEXT "t"
 
+static int use_stty = 1;
+static struct string_list stty_restore = STRING_LIST_INIT_DUP;
 static HANDLE hconin = INVALID_HANDLE_VALUE;
 static DWORD cmode;
 
 static void restore_term(void)
 {
+       if (use_stty) {
+               int i;
+               struct child_process cp = CHILD_PROCESS_INIT;
+
+               if (stty_restore.nr == 0)
+                       return;
+
+               argv_array_push(&cp.args, "stty");
+               for (i = 0; i < stty_restore.nr; i++)
+                       argv_array_push(&cp.args, stty_restore.items[i].string);
+               run_command(&cp);
+               string_list_clear(&stty_restore, 0);
+               return;
+       }
+
        if (hconin == INVALID_HANDLE_VALUE)
                return;
 
@@ -79,6 +98,37 @@ static void restore_term(void)
 
 static int disable_bits(DWORD bits)
 {
+       if (use_stty) {
+               struct child_process cp = CHILD_PROCESS_INIT;
+
+               argv_array_push(&cp.args, "stty");
+
+               if (bits & ENABLE_LINE_INPUT) {
+                       string_list_append(&stty_restore, "icanon");
+                       argv_array_push(&cp.args, "-icanon");
+               }
+
+               if (bits & ENABLE_ECHO_INPUT) {
+                       string_list_append(&stty_restore, "echo");
+                       argv_array_push(&cp.args, "-echo");
+               }
+
+               if (bits & ENABLE_PROCESSED_INPUT) {
+                       string_list_append(&stty_restore, "-ignbrk");
+                       string_list_append(&stty_restore, "intr");
+                       string_list_append(&stty_restore, "^c");
+                       argv_array_push(&cp.args, "ignbrk");
+                       argv_array_push(&cp.args, "intr");
+                       argv_array_push(&cp.args, "");
+               }
+
+               if (run_command(&cp) == 0)
+                       return 0;
+
+               /* `stty` could not be executed; access the Console directly */
+               use_stty = 0;
+       }
+
        hconin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
            FILE_SHARE_READ, NULL, OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL, NULL);