Do not necessarily watch for changes under '/'.

Before, we requested the root of external repositories using a Root of '/', which made Bazel climb up the directory tree until '/' when resolving symlinks when statting the locations where remote repositories are fetched. This is something that is not done for the main repository.

For the sake of efficiency and consistency, treat the actual location of external repositories the same as the main repository and do not register paths above their roots in Skyframe.

In addition, special-case the `@bazel_tools` repository so that the aforementioned ascent does not happen for its source (which should happen for every ther local repository).

RELNOTES: None.
PiperOrigin-RevId: 447409159
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/FileFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/FileFunction.java
index 1ba4d52..88128b1 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/FileFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/FileFunction.java
@@ -21,6 +21,7 @@
 import com.google.devtools.build.lib.actions.FileStateType;
 import com.google.devtools.build.lib.actions.FileStateValue;
 import com.google.devtools.build.lib.actions.FileValue;
+import com.google.devtools.build.lib.analysis.BlazeDirectories;
 import com.google.devtools.build.lib.io.FileSymlinkCycleException;
 import com.google.devtools.build.lib.io.FileSymlinkCycleUniquenessFunction;
 import com.google.devtools.build.lib.io.FileSymlinkException;
@@ -30,6 +31,7 @@
 import com.google.devtools.build.lib.util.Pair;
 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.skyframe.SkyFunction;
 import com.google.devtools.build.skyframe.SkyFunctionException;
@@ -49,9 +51,15 @@
  */
 public class FileFunction implements SkyFunction {
   private final AtomicReference<PathPackageLocator> pkgLocator;
+  private final ImmutableList<Root> immutablePaths;
 
-  public FileFunction(AtomicReference<PathPackageLocator> pkgLocator) {
+  public FileFunction(
+      AtomicReference<PathPackageLocator> pkgLocator, BlazeDirectories directories) {
     this.pkgLocator = pkgLocator;
+    this.immutablePaths =
+        ImmutableList.of(
+            Root.fromPath(directories.getOutputBase()),
+            Root.fromPath(directories.getInstallBase()));
   }
 
   private static class SymlinkResolutionState {
@@ -142,7 +150,11 @@
   }
 
   private RootedPath toRootedPath(Path path) {
-    return RootedPath.toRootedPathMaybeUnderRoot(path, pkgLocator.get().getPathEntries());
+    // We check whether the path to be transformed is under the output base or the install base.
+    // These directories are under the control of Bazel and it therefore does not make much sense
+    // to check for changes in them or in their ancestors in the usual Skyframe way.
+    return RootedPath.toRootedPathMaybeUnderRoot(
+        path, Iterables.concat(pkgLocator.get().getPathEntries(), immutablePaths));
   }
 
   /**