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/skyframe/FilesystemValueCheckerTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/FilesystemValueCheckerTest.java
index 01ed4fd..851b7a8 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/FilesystemValueCheckerTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/FilesystemValueCheckerTest.java
@@ -50,6 +50,7 @@
 import com.google.devtools.build.lib.vfs.ModifiedFileSet;
 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.RootedPath;
 import com.google.devtools.build.lib.vfs.Symlinks;
 import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
@@ -104,7 +105,7 @@
         new AtomicReference<>(
             new PathPackageLocator(
                 fs.getPath("/output_base"),
-                ImmutableList.of(pkgRoot),
+                ImmutableList.of(Root.fromPath(pkgRoot)),
                 BazelSkyframeExecutorConstants.BUILD_FILES_BY_PRIORITY));
     BlazeDirectories directories =
         new BlazeDirectories(
@@ -157,8 +158,9 @@
     FileSystemUtils.createEmptyFile(path);
     assertEmptyDiff(getDirtyFilesystemKeys(evaluator, checker));
 
-    SkyKey skyKey = FileStateValue.key(
-        RootedPath.toRootedPath(fs.getRootDirectory(), PathFragment.create("foo")));
+    SkyKey skyKey =
+        FileStateValue.key(
+            RootedPath.toRootedPath(Root.fromFileSystemRoot(fs), PathFragment.create("foo")));
     EvaluationResult<SkyValue> result =
         driver.evaluate(
             ImmutableList.of(skyKey),
@@ -209,13 +211,14 @@
     FileSystemUtils.ensureSymbolicLink(sym1, path);
     FileSystemUtils.ensureSymbolicLink(sym2, path);
     SkyKey fooKey =
-        FileValue.key(RootedPath.toRootedPath(fs.getRootDirectory(), PathFragment.create("foo")));
+        FileValue.key(
+            RootedPath.toRootedPath(Root.fromFileSystemRoot(fs), PathFragment.create("foo")));
     RootedPath symlinkRootedPath =
-        RootedPath.toRootedPath(fs.getRootDirectory(), PathFragment.create("bar"));
+        RootedPath.toRootedPath(Root.fromFileSystemRoot(fs), PathFragment.create("bar"));
     SkyKey symlinkKey = FileValue.key(symlinkRootedPath);
     SkyKey symlinkFileStateKey = FileStateValue.key(symlinkRootedPath);
     RootedPath sym1RootedPath =
-        RootedPath.toRootedPath(fs.getRootDirectory(), PathFragment.create("sym1"));
+        RootedPath.toRootedPath(Root.fromFileSystemRoot(fs), PathFragment.create("sym1"));
     SkyKey sym1FileStateKey = FileStateValue.key(sym1RootedPath);
     Iterable<SkyKey> allKeys = ImmutableList.of(symlinkKey, fooKey);
 
@@ -277,10 +280,10 @@
 
     SkyKey key1 =
         FileStateValue.key(
-            RootedPath.toRootedPath(fs.getRootDirectory(), PathFragment.create("foo1")));
+            RootedPath.toRootedPath(Root.fromFileSystemRoot(fs), PathFragment.create("foo1")));
     SkyKey key2 =
         FileStateValue.key(
-            RootedPath.toRootedPath(fs.getRootDirectory(), PathFragment.create("foo2")));
+            RootedPath.toRootedPath(Root.fromFileSystemRoot(fs), PathFragment.create("foo2")));
     Iterable<SkyKey> skyKeys = ImmutableList.of(key1, key2);
     EvaluationResult<SkyValue> result =
         driver.evaluate(
@@ -310,8 +313,9 @@
     path.createSymbolicLink(PathFragment.create("bar"));
 
     fs.readlinkThrowsIoException = true;
-    SkyKey fileKey = FileStateValue.key(
-        RootedPath.toRootedPath(pkgRoot, PathFragment.create("foo")));
+    SkyKey fileKey =
+        FileStateValue.key(
+            RootedPath.toRootedPath(Root.fromPath(pkgRoot), PathFragment.create("foo")));
     EvaluationResult<SkyValue> result =
         driver.evaluate(
             ImmutableList.of(fileKey),
@@ -335,7 +339,7 @@
     FileSystemUtils.ensureSymbolicLink(path1, path2);
     FileSystemUtils.ensureSymbolicLink(path2, path3);
     FileSystemUtils.ensureSymbolicLink(path3, path1);
-    SkyKey fileKey1 = FileValue.key(RootedPath.toRootedPath(pkgRoot, path1));
+    SkyKey fileKey1 = FileValue.key(RootedPath.toRootedPath(Root.fromPath(pkgRoot), path1));
 
     EvaluationResult<SkyValue> result =
         driver.evaluate(
@@ -616,9 +620,12 @@
     Path outputPath = outputDir.getRelative(relPath);
     outputDir.createDirectory();
     ArtifactRoot derivedRoot = ArtifactRoot.asDerivedRoot(fs.getPath("/"), outputDir);
-    return new SpecialArtifact(outputPath, derivedRoot,
-        derivedRoot.getExecPath().getRelative(outputPath.relativeTo(derivedRoot.getPath())),
-        ArtifactOwner.NULL_OWNER, SpecialArtifactType.TREE);
+    return new SpecialArtifact(
+        outputPath,
+        derivedRoot,
+        derivedRoot.getExecPath().getRelative(derivedRoot.getRoot().relativize(outputPath)),
+        ArtifactOwner.NULL_OWNER,
+        SpecialArtifactType.TREE);
   }
 
   @Test
@@ -767,8 +774,10 @@
 
   @Test
   public void testPropagatesRuntimeExceptions() throws Exception {
-    Collection<SkyKey> values = ImmutableList.of(
-        FileValue.key(RootedPath.toRootedPath(pkgRoot, PathFragment.create("foo"))));
+    Collection<SkyKey> values =
+        ImmutableList.of(
+            FileValue.key(
+                RootedPath.toRootedPath(Root.fromPath(pkgRoot), PathFragment.create("foo"))));
     driver.evaluate(
         values, false, SkyframeExecutor.DEFAULT_THREAD_COUNT, NullEventHandler.INSTANCE);
     FilesystemValueChecker checker = new FilesystemValueChecker(null, null);