Introduce Root class.

This class represents a root (such as a package path or an output root) used for file lookups and artifacts. It is meant to be as opaque as possible in order to hide the user's environment from sky keys and sky functions.

Roots are used by RootedPaths and ArtifactRoots.

This CL attempts to make the minimum number of modifications necessary to change RootedPath and ArtifactRoot to use these fields. Deprecated methods and invasive accessors are permitted to minimise the risk of any observable changes.

RELNOTES: None
PiperOrigin-RevId: 182271759
diff --git a/src/test/java/com/google/devtools/build/lib/exec/SpawnInputExpanderTest.java b/src/test/java/com/google/devtools/build/lib/exec/SpawnInputExpanderTest.java
index 9e14fac..f875251 100644
--- a/src/test/java/com/google/devtools/build/lib/exec/SpawnInputExpanderTest.java
+++ b/src/test/java/com/google/devtools/build/lib/exec/SpawnInputExpanderTest.java
@@ -31,6 +31,7 @@
 import com.google.devtools.build.lib.vfs.FileSystemUtils;
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.devtools.build.lib.vfs.PathFragment;
+import com.google.devtools.build.lib.vfs.Root;
 import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
@@ -76,7 +77,9 @@
   @Test
   public void testRunfilesSingleFile() throws Exception {
     Artifact artifact =
-        new Artifact(fs.getPath("/root/dir/file"), ArtifactRoot.asSourceRoot(fs.getPath("/root")));
+        new Artifact(
+            fs.getPath("/root/dir/file"),
+            ArtifactRoot.asSourceRoot(Root.fromPath(fs.getPath("/root"))));
     Runfiles runfiles = new Runfiles.Builder("workspace").addArtifact(artifact).build();
     RunfilesSupplier supplier = new RunfilesSupplierImpl(PathFragment.create("runfiles"), runfiles);
     FakeActionInputFileCache mockCache = new FakeActionInputFileCache();
@@ -91,7 +94,9 @@
   @Test
   public void testRunfilesDirectoryStrict() throws Exception {
     Artifact artifact =
-        new Artifact(fs.getPath("/root/dir/file"), ArtifactRoot.asSourceRoot(fs.getPath("/root")));
+        new Artifact(
+            fs.getPath("/root/dir/file"),
+            ArtifactRoot.asSourceRoot(Root.fromPath(fs.getPath("/root"))));
     Runfiles runfiles = new Runfiles.Builder("workspace").addArtifact(artifact).build();
     RunfilesSupplier supplier = new RunfilesSupplierImpl(PathFragment.create("runfiles"), runfiles);
     FakeActionInputFileCache mockCache = new FakeActionInputFileCache();
@@ -108,7 +113,9 @@
   @Test
   public void testRunfilesDirectoryNonStrict() throws Exception {
     Artifact artifact =
-        new Artifact(fs.getPath("/root/dir/file"), ArtifactRoot.asSourceRoot(fs.getPath("/root")));
+        new Artifact(
+            fs.getPath("/root/dir/file"),
+            ArtifactRoot.asSourceRoot(Root.fromPath(fs.getPath("/root"))));
     Runfiles runfiles = new Runfiles.Builder("workspace").addArtifact(artifact).build();
     RunfilesSupplier supplier = new RunfilesSupplierImpl(PathFragment.create("runfiles"), runfiles);
     FakeActionInputFileCache mockCache = new FakeActionInputFileCache();
@@ -124,9 +131,13 @@
   @Test
   public void testRunfilesTwoFiles() throws Exception {
     Artifact artifact1 =
-        new Artifact(fs.getPath("/root/dir/file"), ArtifactRoot.asSourceRoot(fs.getPath("/root")));
+        new Artifact(
+            fs.getPath("/root/dir/file"),
+            ArtifactRoot.asSourceRoot(Root.fromPath(fs.getPath("/root"))));
     Artifact artifact2 =
-        new Artifact(fs.getPath("/root/dir/baz"), ArtifactRoot.asSourceRoot(fs.getPath("/root")));
+        new Artifact(
+            fs.getPath("/root/dir/baz"),
+            ArtifactRoot.asSourceRoot(Root.fromPath(fs.getPath("/root"))));
     Runfiles runfiles = new Runfiles.Builder("workspace")
         .addArtifact(artifact1)
         .addArtifact(artifact2)
@@ -147,7 +158,9 @@
   @Test
   public void testRunfilesSymlink() throws Exception {
     Artifact artifact =
-        new Artifact(fs.getPath("/root/dir/file"), ArtifactRoot.asSourceRoot(fs.getPath("/root")));
+        new Artifact(
+            fs.getPath("/root/dir/file"),
+            ArtifactRoot.asSourceRoot(Root.fromPath(fs.getPath("/root"))));
     Runfiles runfiles = new Runfiles.Builder("workspace")
         .addSymlink(PathFragment.create("symlink"), artifact).build();
     RunfilesSupplier supplier = new RunfilesSupplierImpl(PathFragment.create("runfiles"), runfiles);
@@ -163,7 +176,9 @@
   @Test
   public void testRunfilesRootSymlink() throws Exception {
     Artifact artifact =
-        new Artifact(fs.getPath("/root/dir/file"), ArtifactRoot.asSourceRoot(fs.getPath("/root")));
+        new Artifact(
+            fs.getPath("/root/dir/file"),
+            ArtifactRoot.asSourceRoot(Root.fromPath(fs.getPath("/root"))));
     Runfiles runfiles = new Runfiles.Builder("workspace")
         .addRootSymlink(PathFragment.create("symlink"), artifact).build();
     RunfilesSupplier supplier = new RunfilesSupplierImpl(PathFragment.create("runfiles"), runfiles);