VFS: implement a Windows-specific Path subclass

This change rolls forward commit e0d7a540e3c615c628f63fcaaaba0c47fca2cb25 and
commit 8bb4299b28de14eed9d3b57bcaeb9350c81c7db3, and adds a bugfix:
- FileSystem.PathFactory got a new translatePath
  method that WindowsFileSystem.PathFactory
  overrides to translate absolute Unix paths to
  MSYS-relative paths
- Path.getCachedChildPath calls this translatePath
  method so the child path is registered with the
  correct (translated) parent and under the
  correct name (e.g. "C:" instead of say "c")

Below is the rest of the original change
description:

The new subclass WindowsFileSystem.WindowsPath is
aware of Windows drives.

This change:
- introduces a new factory for Path objects so
  FileSystems can return a custom implementation
  that instantiates filesystem-specific Paths
- implements the WindowsPath subclass of Path that
  is aware of Windows drives
- introduces the bazel.windows_unix_root JVM
  argument that defines the MSYS root, which
  defines the absolute Windows path that is the
  root of all Unix paths that Bazel creates (e.g.
  "/usr/lib" -> "C:/tools/msys64/usr/lib") except
  if the path is of the form "/c/foo" which is
  treated as "C:/foo"
- removes all Windows-specific logic from Path

PathFragment is still aware of drive letters and
it has to remain so because it is unaware of file
systems.

WindowsPath restricts the allowed path strings to
absolute Unix paths where the first segment, if
any, is a volume specifier. From now on if Bazel
attempts to create a WindowsPath from an absolute
Unix path, Bazel will make it relative to
WindowsPath.UNIX_ROOT, unless the first component
is a single-letter name (e.g. "/c/foo" which is
"C:/foo").

Subclassing Path is necessary because a Unix-style
absolute path doesn't sufficiently define a full
Windows path, as it may be relative to any drive.

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

--
MOS_MIGRATED_REVID=137149483
diff --git a/src/test/java/com/google/devtools/build/lib/vfs/PathFragmentTest.java b/src/test/java/com/google/devtools/build/lib/vfs/PathFragmentTest.java
index 2a41b10..c4ac7c1 100644
--- a/src/test/java/com/google/devtools/build/lib/vfs/PathFragmentTest.java
+++ b/src/test/java/com/google/devtools/build/lib/vfs/PathFragmentTest.java
@@ -26,14 +26,12 @@
 import com.google.common.testing.EqualsTester;
 import com.google.devtools.build.lib.testutil.TestUtils;
 import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
 import java.io.File;
 import java.util.Collections;
 import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
 
 /**
  * This class tests the functionality of the PathFragment.
@@ -69,15 +67,16 @@
     InMemoryFileSystem filesystem = new InMemoryFileSystem();
 
     new EqualsTester()
-        .addEqualityGroup(new PathFragment("../relative/path"),
-                          new PathFragment("../relative/path"),
-                          new PathFragment(new File("../relative/path")))
+        .addEqualityGroup(
+            new PathFragment("../relative/path"),
+            new PathFragment("..").getRelative("relative").getRelative("path"),
+            new PathFragment('\0', false, new String[] {"..", "relative", "path"}),
+            new PathFragment(new File("../relative/path")))
         .addEqualityGroup(new PathFragment("something/else"))
         .addEqualityGroup(new PathFragment("/something/else"))
-        .addEqualityGroup(new PathFragment("/"),
-                          new PathFragment("//////"))
-        .addEqualityGroup(new PathFragment(""))
-        .addEqualityGroup(filesystem.getRootDirectory())  // A Path object.
+        .addEqualityGroup(new PathFragment("/"), new PathFragment("//////"))
+        .addEqualityGroup(new PathFragment(""), PathFragment.EMPTY_FRAGMENT)
+        .addEqualityGroup(filesystem.getRootDirectory()) // A Path object.
         .testEquals();
   }