Repository: bazelbuild/bazel
Issue: Windows,Bash detection: do not detect Git Bash
Labels: type: bug
P1
platform: windows

### Description of the problem / feature request:

When `BAZEL_SH` envvar is not defined and Bazel searches for a suitable bash.exe, it should not look for Git Bash nor should it recommend installing it as a Bash implementation.

Git Bash does not support the full set of bintools that MSYS2 Bash does, nor does Git Bash support Pacman to install those tools. Git Bash is therefore unsuitable as a general-purpose Bash for Windows.

Even worse, if you have both Git Bash and MSYS Bash installed, they may collide if you run one's binaries from the other (see repro below).

Bazel should only look for MSYS2 Bash and recommend only that.

### Bugs: what's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.

1. Have both Git Bash and MSYS2 Bash installed, have paths to them that have no space characters:
    ```
    C:\src\tmp>mklink /j C:\git "C:\Program Files\Git"
    Junction created for C:\git <<===>> C:\Program Files\Git
    ```

2. In MSYS2 Bash install "zip" by running `pacman -Syu zip`.

3. Set "BAZEL_SH" envvar to point to Git Bash, put Git then MSYS on the PATH:
    ```
    BAZEL_SH=C:\git\usr\bin\bash.exe
    PATH=C:\git\usr\bin;C:\msys64\usr\bin
    ```

4. Build a genrule that runs `zip`.
    ```
    C:\src\tmp>type BUILD
    genrule(
        name = "foo",
        outs = ["foo.txt"],
        cmd = ("echo \"DEBUG: $$(cygpath -w $$(which bash))\" ; " +
               "echo \"DEBUG: $$(cygpath -w $$(which zip))\" ; " +
               "zip > $@")
    )

    C:\src\tmp>c:\src\bazel-releases\0.16.0\bazel.exe build --verbose_failures //:foo.txt
    INFO: Analysed target //:foo.txt (0 packages loaded).
    INFO: Found 1 target...
    SUBCOMMAND: # //:foo [action 'Executing genrule //:foo']
    cd C:/users/laszlocsomor/_bazel_laszlocsomor/zovul4l7/execroot/__main__
      SET PATH=C:\git\usr\bin;C:\git\bin;C:\git\usr\bin;C:\msys64\usr\bin
      C:/git/usr/bin/bash.exe -c source external/bazel_tools/tools/genrule/genrule-setup.sh; echo "DEBUG: $(cygpath -w $(which bash))" ; echo "DEBUG: $(cygpath -w $(which zip))" ; zip > bazel-out/x64_windows-fastbuild/genfiles/foo.txt
    ERROR: C:/src/tmp/BUILD:107:1: Executing genrule //:foo failed (Exit 127): bash.exe failed: error executing command
      cd C:/users/laszlocsomor/_bazel_laszlocsomor/zovul4l7/execroot/__main__
      SET PATH=C:\git\usr\bin;C:\git\bin;C:\git\usr\bin;C:\msys64\usr\bin
      C:/git/usr/bin/bash.exe -c source external/bazel_tools/tools/genrule/genrule-setup.sh; echo "DEBUG: $(cygpath -w $(which bash))" ; echo "DEBUG: $(cygpath -w $(which zip))" ; zip > bazel-out/x64_windows-fastbuild/genfiles/foo.txt
    DEBUG: C:\git\usr\bin\bash.exe
    DEBUG: C:\msys64\usr\bin\zip.exe
          1 [main] zip (6740) C:\msys64\usr\bin\zip.exe: *** fatal error - cygheap base mismatch detected - 0x180318410/0x1802FF410.
    This problem is probably due to using incompatible versions of the cygwin DLL.
    Search for cygwin1.dll using the Windows Start->Find/Search facility
    and delete all but the most recent version.  The most recent version *should*
    reside in x:\cygwin\bin, where 'x' is the drive on which you have
    installed the cygwin distribution.  Rebooting is also suggested if you
    are unable to find another cygwin DLL.
    Target //:foo.txt failed to build
    INFO: Elapsed time: 1.160s, Critical Path: 0.70s
    INFO: 0 processes.
    FAILED: Build did NOT complete successfully
    ```

### What operating system are you running Bazel on?

Windows 10

### What's the output of `bazel info release`?

```
C:\src\tmp>c:\src\bazel-releases\0.16.0\bazel.exe info release
release 0.16.0
```

Issue comments:

Pull request review comments:

Patch that resolved the issue:
diff --git a/src/main/cpp/blaze_util_windows.cc b/src/main/cpp/blaze_util_windows.cc
index e851ef041a5378..d811a944548df1 100644
--- a/src/main/cpp/blaze_util_windows.cc
+++ b/src/main/cpp/blaze_util_windows.cc
@@ -1413,58 +1413,6 @@ static string GetMsysBash() {
   return string();
 }
 
-// Implements heuristics to discover Git-on-Win installation.
-static string GetBashFromGitOnWin() {
-  HKEY h_GitOnWin_uninstall;
-
-  // Well-known registry key for Git-on-Windows.
-  static constexpr const char key[] =
-      "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Git_is1";
-  if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,    // _In_     HKEY    hKey,
-                    key,                   // _In_opt_ LPCTSTR lpSubKey,
-                    0,                     // _In_     DWORD   ulOptions,
-                    KEY_QUERY_VALUE,       // _In_     REGSAM  samDesired,
-                    &h_GitOnWin_uninstall  // _Out_    PHKEY   phkResult
-                    )) {
-    BAZEL_LOG(INFO) << "Cannot open HKCU\\" << key;
-    return string();
-  }
-  AutoHandle auto_h_GitOnWin_uninstall(h_GitOnWin_uninstall);
-
-  BAZEL_LOG(INFO) << "Getting install location of HKLM\\" << key;
-  BYTE path[REG_VALUE_BUFFER_SIZE];
-  DWORD path_length = sizeof(path);
-  DWORD path_type;
-  if (RegQueryValueEx(h_GitOnWin_uninstall,  // _In_        HKEY    hKey,
-                      "InstallLocation",     // _In_opt_    LPCTSTR lpValueName,
-                      0,                     // _Reserved_  LPDWORD lpReserved,
-                      &path_type,            // _Out_opt_   LPDWORD lpType,
-                      path,                  // _Out_opt_   LPBYTE  lpData,
-                      &path_length           // _Inout_opt_ LPDWORD lpcbData
-                      )) {
-    BAZEL_LOG(ERROR) << "Failed to query InstallLocation of HKLM\\" << key;
-    return string();
-  }
-
-  if (path_length == 0 || path_type != REG_SZ) {
-    BAZEL_LOG(ERROR) << "Zero-length (" << path_length
-                     << ") install location or wrong type (" << path_type
-                     << ")";
-    return string();
-  }
-
-  BAZEL_LOG(INFO) << "Install location of HKLM\\" << key << " is " << path;
-  string path_as_string(path, path + path_length - 1);
-  string bash_exe = path_as_string + "\\usr\\bin\\bash.exe";
-  if (!blaze_util::PathExists(bash_exe)) {
-    BAZEL_LOG(ERROR) << "%s does not exist", bash_exe.c_str();
-    return string();
-  }
-
-  BAZEL_LOG(INFO) << "Detected git-on-Windows bash at " << bash_exe.c_str();
-  return bash_exe;
-}
-
 static string GetBinaryFromPath(const string& binary_name) {
   char found[MAX_PATH];
   string path_list = blaze::GetEnv("PATH");
@@ -1508,11 +1456,6 @@ static string LocateBash() {
     return msys_bash;
   }
 
-  string git_on_win_bash = GetBashFromGitOnWin();
-  if (!git_on_win_bash.empty()) {
-    return git_on_win_bash;
-  }
-
   return GetBinaryFromPath("bash.exe");
 }
 
@@ -1533,17 +1476,13 @@ void DetectBashOrDie() {
     // TODO(bazel-team) should this be printed to stderr? If so, it should use
     // BAZEL_LOG(ERROR)
     printf(
-        "Bazel on Windows requires bash.exe and other Unix tools, but we could "
-        "not find them.\n"
-        "If you do not have them installed, the easiest is to install MSYS2 "
-        "from\n"
+        "Bazel on Windows requires MSYS2 Bash, but we could not find it.\n"
+        "If you do not have it installed, you can install MSYS2 from\n"
         "       http://repo.msys2.org/distrib/msys2-x86_64-latest.exe\n"
-        "or git-on-Windows from\n"
-        "       https://git-scm.com/download/win\n"
         "\n"
-        "If you already have bash.exe installed but Bazel cannot find it,\n"
+        "If you already have it installed but Bazel cannot find it,\n"
         "set BAZEL_SH environment variable to its location:\n"
-        "       set BAZEL_SH=c:\\path\\to\\bash.exe\n");
+        "       set BAZEL_SH=c:\\path\\to\\msys2\\usr\\bin\\bash.exe\n");
     exit(1);
   }
 }


Test patch: