Fixed repository.which() on Windows

Also removed previous workaround in cc_configure.bzl

--
Change-Id: I6dcd039fc5e18af8f2d21969641d6bbd05c8badc
Reviewed-on: https://bazel-review.googlesource.com/#/c/4034
MOS_MIGRATED_REVID=127518922
diff --git a/src/main/cpp/blaze_util_mingw.cc b/src/main/cpp/blaze_util_mingw.cc
index 6f0df54..7dd3b93 100644
--- a/src/main/cpp/blaze_util_mingw.cc
+++ b/src/main/cpp/blaze_util_mingw.cc
@@ -510,6 +510,10 @@
 string ListSeparator() { return ";"; }
 
 string ConvertPath(const string& path) {
+  // If the path looks like %USERPROFILE%/foo/bar, don't convert.
+  if (path.empty() || path[0] == '%') {
+    return path;
+  }
   char* wpath = static_cast<char*>(cygwin_create_path(
       CCP_POSIX_TO_WIN_A, static_cast<const void*>(path.c_str())));
   string result(wpath);
@@ -517,6 +521,21 @@
   return result;
 }
 
+// Convert a Unix path list to Windows path list
+string ConvertPathList(const string& path_list) {
+  string w_list = "";
+  int start = 0;
+  int pos;
+  while ((pos = path_list.find(":", start)) != string::npos) {
+    w_list += ConvertPath(path_list.substr(start, pos - start)) + ";";
+    start = pos + 1;
+  }
+  if (start < path_list.size()) {
+    w_list += ConvertPath(path_list.substr(start));
+  }
+  return w_list;
+}
+
 string ConvertPathToPosix(const string& win_path) {
   char* posix_path = static_cast<char*>(cygwin_create_path(
       CCP_WIN_A_TO_POSIX, static_cast<const void*>(win_path.c_str())));
diff --git a/src/main/cpp/blaze_util_platform.h b/src/main/cpp/blaze_util_platform.h
index 71c7a84..c6e1d70 100644
--- a/src/main/cpp/blaze_util_platform.h
+++ b/src/main/cpp/blaze_util_platform.h
@@ -84,6 +84,12 @@
 // is Windows path.
 std::string ConvertPath(const std::string& path);
 
+// Convert a path list from Bazel internal form to underlying OS form.
+// On Unixes this is an identity operation.
+// On Windows, Bazel internal form is cygwin path list, and underlying OS form
+// is Windows path list.
+std::string ConvertPathList(const std::string& path_list);
+
 // Return a string used to separate paths in a list.
 std::string ListSeparator();
 
diff --git a/src/main/cpp/blaze_util_posix.cc b/src/main/cpp/blaze_util_posix.cc
index bc06712..12498c4 100644
--- a/src/main/cpp/blaze_util_posix.cc
+++ b/src/main/cpp/blaze_util_posix.cc
@@ -64,6 +64,8 @@
 
 std::string ConvertPath(const std::string &path) { return path; }
 
+std::string ConvertPathList(const std::string& path_list) { return path_list; }
+
 std::string ListSeparator() { return ":"; }
 
 bool SymlinkDirectories(const string &target, const string &link) {
diff --git a/src/main/cpp/option_processor.cc b/src/main/cpp/option_processor.cc
index 3e2f662..6079ebf 100644
--- a/src/main/cpp/option_processor.cc
+++ b/src/main/cpp/option_processor.cc
@@ -460,7 +460,17 @@
     command_arguments_.push_back("--ignore_client_env");
   } else {
     for (char** env = environ; *env != NULL; env++) {
-      command_arguments_.push_back("--client_env=" + string(*env));
+      string env_str(*env);
+      int pos = env_str.find("=");
+      if (pos != string::npos) {
+        string name = env_str.substr(0, pos);
+        if (name == "PATH" || name == "TMP") {
+          string value = env_str.substr(pos + 1);
+          value = ConvertPathList(value);
+          env_str = name + "=" + value;
+        }
+      }
+      command_arguments_.push_back("--client_env=" + env_str);
     }
   }
   command_arguments_.push_back("--client_cwd=" + blaze::ConvertPath(cwd));
diff --git a/tools/cpp/cc_configure.bzl b/tools/cpp/cc_configure.bzl
index 6eb4c33..feb1583 100644
--- a/tools/cpp/cc_configure.bzl
+++ b/tools/cpp/cc_configure.bzl
@@ -49,24 +49,14 @@
   result = repository_ctx.which(cmd)
   return default if result == None else str(result)
 
-# This functions can only be used on Windows
-def _to_windows_path(repository_ctx, path):
-  """Convert unix path to windows path, also works for path list."""
-  result = repository_ctx.execute(["cygpath", "-w", "-p", path])
-  if result.stderr:
-    fail(result.stderr)
-  return result.stdout.strip()
 
-# This functions can only be used on Windows
-# This function is a workaround since repository_ctx.which doesn't work on Windows for now.
-# TODO(pcloudy): Remove this function once the skylark implemented which function works.
-def _which_windows(repository_ctx, cmd):
-  """run which command to detect a binary location and return a windows path."""
-  result = repository_ctx.execute(["which", cmd])
-  if result.stderr:
-    fail("Cannot find " + cmd + " in PATH.\nPlease make sure "
-         + cmd + " is installed.\n" + result.stderr)
-  return _to_windows_path(repository_ctx, result.stdout.strip())
+def _which_cmd(repository_ctx, cmd):
+  """Find cmd in PATH using repository_ctx.which() and fail if cannot find it."""
+  result = repository_ctx.which(cmd)
+  if result == None:
+    fail("Cannot find " + cmd + " in PATH=%s.\nPlease make sure "
+         + cmd + " is installed.\n" % repository_ctx.os.environ["PATH"])
+  return str(result)
 
 def _get_tool_paths(repository_ctx, darwin, cc):
   """Compute the path to the various tools."""
@@ -344,7 +334,7 @@
 
 def _find_vs_path(repository_ctx):
   """Find Visual Studio install path."""
-  bash_bin = _which_windows(repository_ctx, "bash.exe")
+  bash_bin = _which_cmd(repository_ctx, "bash.exe")
   program_files_dir = repository_ctx.os.environ["ProgramFiles(x86)"]
   if not program_files_dir:
     fail("'ProgramFiles(x86)' environment variable is not set")
@@ -359,9 +349,7 @@
                       "@echo off\n" +
                       "call \"" + vsvars + "\" amd64 \n" +
                       "echo PATH=%PATH%,INCLUDE=%INCLUDE%,LIB=%LIB% \n", True)
-  envs = repository_ctx.execute(["wrapper/get_env.bat"], 600,
-                                # TODO(pcloudy): This should be removed once the environment variable format is fixed
-                                {"PATH": _to_windows_path(repository_ctx, repository_ctx.os.environ["PATH"].strip())}).stdout.strip().split(",")
+  envs = repository_ctx.execute(["wrapper/get_env.bat"]).stdout.strip().split(",")
   env_map = {}
   for env in envs:
     key, value = env.split("=")
@@ -409,7 +397,7 @@
     for f in ["msvc_cl.py", "msvc_link.py"]:
       repository_ctx.symlink(msvc_wrapper.get_child(f), "wrapper/bin/pydir/" + f)
 
-    python_binary = _which_windows(repository_ctx, "python.exe")
+    python_binary = _which_cmd(repository_ctx, "python.exe")
     _tpl(repository_ctx, "wrapper/bin/call_python.bat", {"%{python_binary}": python_binary})
 
     vs_path = _find_vs_path(repository_ctx)
@@ -418,7 +406,7 @@
     include_paths = env["INCLUDE"] + (python_dir + "include")
     lib_paths = env["LIB"] + (python_dir + "libs")
     _tpl(repository_ctx, "wrapper/bin/pydir/msvc_tools.py", {
-        "%{tmp}": _to_windows_path(repository_ctx, repository_ctx.os.environ["TMP"]).replace("\\", "\\\\"),
+        "%{tmp}": repository_ctx.os.environ["TMP"].replace("\\", "\\\\"),
         "%{path}": env["PATH"],
         "%{include}": include_paths,
         "%{lib}": lib_paths,