Bazel client: platform-specific JoinPath 

This allows joining paths on "\" instead of "/"
when building for Windows.

See https://github.com/bazelbuild/bazel/issues/2107

--
Change-Id: I417ba40af6530650be2394db4bd445f0883d40e5
Reviewed-on: https://cr.bazel.build/8495
PiperOrigin-RevId: 145961689
MOS_MIGRATED_REVID=145961689
diff --git a/src/main/cpp/util/file.cc b/src/main/cpp/util/file.cc
index 392af37..cae8719 100644
--- a/src/main/cpp/util/file.cc
+++ b/src/main/cpp/util/file.cc
@@ -77,31 +77,6 @@
   return SplitPath(path).second;
 }
 
-string JoinPath(const string &path1, const string &path2) {
-  if (path1.empty()) {
-    // "" + "/bar"
-    return path2;
-  }
-
-  if (path1[path1.size() - 1] == '/') {
-    if (path2.find('/') == 0) {
-      // foo/ + /bar
-      return path1 + path2.substr(1);
-    } else {
-      // foo/ + bar
-      return path1 + path2;
-    }
-  } else {
-    if (path2.find('/') == 0) {
-      // foo + /bar
-      return path1 + path2;
-    } else {
-      // foo + bar
-      return path1 + "/" + path2;
-    }
-  }
-}
-
 class DirectoryTreeWalker : public DirectoryEntryConsumer {
  public:
   DirectoryTreeWalker(vector<string> *files,
diff --git a/src/main/cpp/util/file.h b/src/main/cpp/util/file.h
index efe963c..e3a744f 100644
--- a/src/main/cpp/util/file.h
+++ b/src/main/cpp/util/file.h
@@ -17,6 +17,7 @@
 #include <functional>
 #include <string>
 #include <vector>
+#include "src/main/cpp/util/file_platform.h"
 
 namespace blaze_util {
 
@@ -59,8 +60,6 @@
 // "/" in the path, the result is the same as the input.
 std::string Basename(const std::string &path);
 
-std::string JoinPath(const std::string &path1, const std::string &path2);
-
 // Lists all files in `path` and all of its subdirectories.
 //
 // Does not follow symlinks / junctions.
diff --git a/src/main/cpp/util/file_platform.h b/src/main/cpp/util/file_platform.h
index 600820b..99cf990 100644
--- a/src/main/cpp/util/file_platform.h
+++ b/src/main/cpp/util/file_platform.h
@@ -50,6 +50,8 @@
 // Creates a platform-specific implementation of `IFileMtime`.
 IFileMtime *CreateFileMtime();
 
+std::string JoinPath(const std::string &path1, const std::string &path2);
+
 // Split a path to dirname and basename parts.
 std::pair<std::string, std::string> SplitPath(const std::string &path);
 
diff --git a/src/main/cpp/util/file_posix.cc b/src/main/cpp/util/file_posix.cc
index a1d806a..57c994a 100644
--- a/src/main/cpp/util/file_posix.cc
+++ b/src/main/cpp/util/file_posix.cc
@@ -168,6 +168,35 @@
   return new PosixPipe(fd[0], fd[1]);
 }
 
+string JoinPath(const string &path1, const string &path2) {
+  if (path1.empty()) {
+    // "" + "/bar"
+    return path2;
+  }
+  if (path2.empty()) {
+    // "foo/" + ""
+    return path1;
+  }
+
+  if (path1.back() == '/') {
+    if (path2.front() == '/') {
+      // foo/ + /bar
+      return path1 + path2.substr(1);
+    } else {
+      // foo/ + bar
+      return path1 + path2;
+    }
+  } else {
+    if (path2.front() == '/') {
+      // foo + /bar
+      return path1 + path2;
+    } else {
+      // foo + bar
+      return path1 + "/" + path2;
+    }
+  }
+}
+
 pair<string, string> SplitPath(const string &path) {
   size_t pos = path.rfind('/');
 
diff --git a/src/main/cpp/util/file_windows.cc b/src/main/cpp/util/file_windows.cc
index b1faddd..2deee0b 100644
--- a/src/main/cpp/util/file_windows.cc
+++ b/src/main/cpp/util/file_windows.cc
@@ -323,6 +323,44 @@
        HasDriveSpecifierPrefix(path.c_str() + 4) && IsPathSeparator(path[6]));
 }
 
+string JoinPath(const string& path1, const string& path2) {
+  if (path1.empty()) {
+    // "" + "/bar"
+    return path2;
+  }
+  if (path2.empty()) {
+    // "foo/" + ""
+    return path1;
+  }
+
+  string p1 = path1;
+  if (path1.back() == '/') {
+    p1.pop_back();
+  }
+  string p2 = path2;
+  if (path2.front() == '/') {
+    p2[0] = '\\';
+  }
+
+  if (IsPathSeparator(p1.back())) {
+    if (!p2.empty() && IsPathSeparator(p2.front())) {
+      // foo/ + /bar
+      return p1 + p2.substr(1);
+    } else {
+      // foo/ + bar
+      return p1 + p2;
+    }
+  } else {
+    if (!p2.empty() && IsPathSeparator(p2.front())) {
+      // foo + /bar
+      return p1 + p2;
+    } else {
+      // foo + bar
+      return p1 + "\\" + p2;
+    }
+  }
+}
+
 pair<string, string> SplitPath(const string& path) {
   if (path.empty()) {
     return std::make_pair("", "");