Bazel client, Windows: fix MSYS root retrieval

The file_windows.cc:MsysRoot::Get() function was
incorrectly assuming that bash.exe is usually
under c:\tools\msys64\bin\bash.exe when in reality
it's c:\tools\msys64\usr\bin\bash.exe, so we need
to walk up one more directory.

Unfortunately the test was assuming the same so
the bug wasn't caught.

The new code is a bit more foolproof in that it
looks for an msys-looking final path segment and
assumes that to be the msys root.

Fixes https://github.com/bazelbuild/bazel/issues/2323

--
PiperOrigin-RevId: 143372193
MOS_MIGRATED_REVID=143372193
diff --git a/src/main/cpp/util/file_windows.cc b/src/main/cpp/util/file_windows.cc
index 6ded8c8..608ed99 100644
--- a/src/main/cpp/util/file_windows.cc
+++ b/src/main/cpp/util/file_windows.cc
@@ -164,9 +164,17 @@
     }
     result = value2;
   }
-  // BAZEL_SH is usually "c:\tools\msys64\bin\bash.exe", we need to return
-  // "c:\tools\msys64".
-  return std::make_pair(true, std::move(Dirname(Dirname(result))));
+
+  // BAZEL_SH is usually "c:\tools\msys64\usr\bin\bash.exe", we need to return
+  // "c:\tools\msys64". Look for the rightmost msys-looking component.
+  while (!IsRootDirectory(result) &&
+         Basename(result).find("msys") == string::npos) {
+    result = Dirname(result);
+  }
+  if (IsRootDirectory(result)) {
+    return std::make_pair(false, "");
+  }
+  return std::make_pair(true, std::move(result));
 }
 
 bool AsWindowsPath(const string& path, wstring* result) {
diff --git a/src/test/cpp/util/file_windows_test.cc b/src/test/cpp/util/file_windows_test.cc
index 048d13b..231e21d 100644
--- a/src/test/cpp/util/file_windows_test.cc
+++ b/src/test/cpp/util/file_windows_test.cc
@@ -95,7 +95,7 @@
 }
 
 TEST(FileTest, TestAsWindowsPath) {
-  SetEnvironmentVariableA("BAZEL_SH", "c:\\dummy\\msys\\bin\\bash.exe");
+  SetEnvironmentVariableA("BAZEL_SH", "c:\\msys\\some\\long\\path\\bash.exe");
   std::wstring actual;
 
   ASSERT_TRUE(AsWindowsPath("", &actual));
@@ -120,7 +120,7 @@
   ASSERT_EQ(std::wstring(L"d:\\progra~1\\micros~1"), actual);
 
   ASSERT_TRUE(AsWindowsPath("/foo", &actual));
-  ASSERT_EQ(std::wstring(L"c:\\dummy\\msys\\foo"), actual);
+  ASSERT_EQ(std::wstring(L"c:\\msys\\foo"), actual);
 
   std::wstring wlongpath(L"dummy_long_path\\");
   std::string longpath("dummy_long_path/");