Remove remaining vestiges of "scoping" in InMemoryFileSystem.

RELNOTES: None
PiperOrigin-RevId: 211832580
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileSystem.java b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileSystem.java
index 99eea3a..6be1345 100644
--- a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileSystem.java
+++ b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileSystem.java
@@ -50,7 +50,6 @@
 @ThreadSafe
 public class InMemoryFileSystem extends FileSystem {
 
-  private final PathFragment scopeRoot;
   protected final Clock clock;
 
   // The root inode (a directory).
@@ -60,8 +59,7 @@
   private static final int MAX_TRAVERSALS = 256;
 
   /**
-   * Creates a new InMemoryFileSystem with scope checking disabled (all paths are considered to be
-   * within scope) and a default clock.
+   * Creates a new InMemoryFileSystem with default clock and given hash function.
    *
    * @param hashFunction the function to use for calculating digests.
    */
@@ -70,19 +68,16 @@
   }
 
   /**
-   * Creates a new InMemoryFileSystem with scope checking disabled (all paths are considered to be
-   * within scope).
+   * Creates a new InMemoryFileSystem with the given clock and hash function.
    */
   public InMemoryFileSystem(Clock clock, DigestHashFunction hashFunction) {
     super(hashFunction);
     this.clock = clock;
     this.rootInode = newRootInode(clock);
-    this.scopeRoot = null;
   }
 
   /**
-   * Creates a new InMemoryFileSystem with scope checking disabled (all paths are considered to be
-   * within scope) and a default clock.
+   * Creates a new InMemoryFileSystem with default clock and hash function.
    */
   @VisibleForTesting
   public InMemoryFileSystem() {
@@ -90,24 +85,11 @@
   }
 
   /**
-   * Creates a new InMemoryFileSystem with scope checking disabled (all
-   * paths are considered to be within scope).
+   * Creates a new InMemoryFileSystem.
    */
   @VisibleForTesting
   public InMemoryFileSystem(Clock clock) {
-    this(clock, (PathFragment) null);
-  }
-
-  /**
-   * Creates a new InMemoryFileSystem with scope checking bound to scopeRoot, i.e. any path that's
-   * not below scopeRoot is considered to be out of scope.
-   */
-  @VisibleForTesting
-  public InMemoryFileSystem(Clock clock, PathFragment scopeRoot) {
-    super(DigestHashFunction.DEFAULT_HASH_FOR_TESTS);
-    this.scopeRoot = scopeRoot;
-    this.clock = clock;
-    this.rootInode = newRootInode(clock);
+    this(clock, DigestHashFunction.DEFAULT_HASH_FOR_TESTS);
   }
 
   private static InMemoryDirectoryInfo newRootInode(Clock clock) {
@@ -118,29 +100,6 @@
   }
 
   /**
-   * Returns true if the given path is within this file system's scope, false otherwise.
-   *
-   * @param parentDepth the number of segments in the path's parent directory (only meaningful for
-   *     paths that begin with ".."). The parent directory itself is assumed to be in scope.
-   * @param normalizedPath input path, expected to be normalized such that all ".." and "." segments
-   *     are removed (with the exception of a possible prefix sequence of contiguous ".." segments)
-   */
-  private boolean inScope(int parentDepth, PathFragment normalizedPath) {
-    if (scopeRoot == null) {
-      return true;
-    } else if (normalizedPath.isAbsolute()) {
-      return normalizedPath.startsWith(scopeRoot);
-    } else {
-      // Efficiency note: we're not accounting for "/scope/root/../root" paths here, i.e. paths
-      // that appear to go out of scope but ultimately stay within scope. This may result in
-      // unnecessary re-delegation back into the same FS. we're choosing to forgo that
-      // optimization under the assumption that such scenarios are rare and unimportant to
-      // overall performance. We can always enhance this if needed.
-      return parentDepth - leadingParentReferences(normalizedPath) >= scopeRoot.segmentCount();
-    }
-  }
-
-  /**
    * Given a path that's normalized (no ".." or "." segments), except for a possible prefix sequence
    * of contiguous ".." segments, returns the size of that prefix sequence.
    *
@@ -352,21 +311,10 @@
    * <p>If 'create' is false, the inode must exist; otherwise, it will be created and added to its
    * parent directory, which must exist.
    *
-   * <p>Iff the given path escapes this file system's scope, a Error.ENOENT exception is thrown.
    *
    * <p>May fail with ENOTDIR, ENOENT, EACCES, ELOOP.
    */
   private synchronized InMemoryContentInfo pathWalk(Path path, boolean create) throws IOException {
-    // Implementation note: This is where we check for out-of-scope symlinks and
-    // trigger re-delegation to another file system accordingly. This code handles
-    // both absolute and relative symlinks. Some assumptions we make: First, only
-    // symlink targets as read from getNormalizedLinkContent() can escape our scope.
-    // This is because Path objects are all canonicalized (see {@link Path#getRelative},
-    // etc.) and symlink target segments that get added to the stack are in-scope by
-    // definition. Second, symlink targets with relative segments must have the form
-    // [".."]*[standard segment]+, i.e. only the ".." non-standard segment is allowed
-    // and it may only appear as part of a contiguous prefix sequence.
-
     Stack<String> stack = new Stack<>();
     for (Path p = path; !isRootDirectory(p); p = p.getParentDirectory()) {
       String name = baseNameOrWindowsDrive(p);
@@ -374,25 +322,19 @@
     }
 
     InMemoryContentInfo inode = rootInode;
-    int parentDepth = -1;
     int traversals = 0;
 
     while (!stack.isEmpty()) {
       traversals++;
 
       String name = stack.pop();
-      parentDepth += name.equals("..") ? -1 : 1;
 
       // ENOENT on last segment with 'create' => create a new file.
       InMemoryContentInfo child = directoryLookup(inode, name, create && stack.isEmpty(), path);
       if (child.isSymbolicLink()) {
         PathFragment linkTarget = ((InMemoryLinkInfo) child).getNormalizedLinkContent();
-        if (!inScope(parentDepth, linkTarget)) {
-          throw Error.ENOENT.exception(path);
-        }
         if (linkTarget.isAbsolute()) {
           inode = rootInode;
-          parentDepth = -1;
         }
         if (traversals > MAX_TRAVERSALS) {
           throw Error.ELOOP.exception(path);
@@ -431,12 +373,9 @@
   }
 
   /**
-   * Helper method for stat, scopeLimitedStat: lock the internal state and return the
-   * path's (no symlink-followed) stat if the path's parent directory is within scope,
-   * else return an "out of scope" reference to the path's parent directory (which will
-   * presumably be re-delegated to another FS).
+   * Helper method for stat and inodeStat: return the path's (no symlink-followed) stat.
    */
-  private synchronized InMemoryContentInfo getNoFollowStatOrOutOfScopeParent(Path path)
+  private synchronized InMemoryContentInfo noFollowStat(Path path)
       throws IOException  {
     InMemoryDirectoryInfo dirInfo = getDirectory(path.getParentDirectory());
     return directoryLookup(dirInfo, baseNameOrWindowsDrive(path), /*create=*/ false, path);
@@ -449,15 +388,7 @@
    */
   @Override
   public FileStatus stat(Path path, boolean followSymlinks) throws IOException {
-    if (followSymlinks) {
-      return scopeLimitedStat(path, true);
-    } else {
-      if (isRootDirectory(path)) {
-        return rootInode;
-      } else {
-        return getNoFollowStatOrOutOfScopeParent(path);
-      }
-    }
+    return inodeStat(path, followSymlinks);
   }
 
   @Override
@@ -477,19 +408,14 @@
   }
 
   /**
-   * Version of stat that returns an inode if the input path stays entirely within this file
-   * system's scope, otherwise throws.
+   * Version of stat that returns an inode of the input path.
    */
-  protected InMemoryContentInfo scopeLimitedStat(Path path, boolean followSymlinks)
+  protected InMemoryContentInfo inodeStat(Path path, boolean followSymlinks)
       throws IOException {
     if (followSymlinks) {
       return pathWalk(path, false);
     } else {
-      if (isRootDirectory(path)) {
-        return rootInode;
-      } else {
-        return getNoFollowStatOrOutOfScopeParent(path);
-      }
+      return isRootDirectory(path) ? rootInode : noFollowStat(path);
     }
   }
 
@@ -510,7 +436,7 @@
   protected PathFragment resolveOneLink(Path path) throws IOException {
     // Beware, this seemingly simple code belies the complex specification of
     // FileSystem.resolveOneLink().
-    InMemoryContentInfo status = scopeLimitedStat(path, false);
+    InMemoryContentInfo status = inodeStat(path, false);
     return status.isSymbolicLink() ? ((InMemoryLinkInfo) status).getLinkContent() : null;
   }
 
@@ -562,21 +488,21 @@
 
   @Override
   protected boolean isReadable(Path path) throws IOException {
-    InMemoryContentInfo status = scopeLimitedStat(path, true);
+    InMemoryContentInfo status = inodeStat(path, true);
     return status.isReadable();
   }
 
   @Override
   protected void setReadable(Path path, boolean readable) throws IOException {
     synchronized (this) {
-      InMemoryContentInfo status = scopeLimitedStat(path, true);
+      InMemoryContentInfo status = inodeStat(path, true);
       status.setReadable(readable);
     }
   }
 
   @Override
   protected boolean isWritable(Path path) throws IOException {
-    InMemoryContentInfo status = scopeLimitedStat(path, true);
+    InMemoryContentInfo status = inodeStat(path, true);
     return status.isWritable();
   }
 
@@ -584,14 +510,14 @@
   public void setWritable(Path path, boolean writable) throws IOException {
     InMemoryContentInfo status;
     synchronized (this) {
-      status = scopeLimitedStat(path, true);
+      status = inodeStat(path, true);
       status.setWritable(writable);
     }
   }
 
   @Override
   protected boolean isExecutable(Path path) throws IOException {
-    InMemoryContentInfo status = scopeLimitedStat(path, true);
+    InMemoryContentInfo status = inodeStat(path, true);
     return status.isExecutable();
   }
 
@@ -599,7 +525,7 @@
   protected void setExecutable(Path path, boolean executable)
       throws IOException {
     synchronized (this) {
-      InMemoryContentInfo status = scopeLimitedStat(path, true);
+      InMemoryContentInfo status = inodeStat(path, true);
       status.setExecutable(executable);
     }
   }
@@ -686,7 +612,7 @@
 
   @Override
   protected PathFragment readSymbolicLink(Path path) throws IOException {
-    InMemoryContentInfo status = scopeLimitedStat(path, false);
+    InMemoryContentInfo status = inodeStat(path, false);
     if (status.isSymbolicLink()) {
       Preconditions.checkState(status instanceof InMemoryLinkInfo);
       return ((InMemoryLinkInfo) status).getLinkContent();
@@ -749,7 +675,7 @@
   @Override
   public void setLastModifiedTime(Path path, long newTime) throws IOException {
     synchronized (this) {
-      InMemoryContentInfo status = scopeLimitedStat(path, true);
+      InMemoryContentInfo status = inodeStat(path, true);
       status.setLastModifiedTime(newTime == -1L ? clock.currentTimeMillis() : newTime);
     }
   }
@@ -757,7 +683,7 @@
   @Override
   protected InputStream getInputStream(Path path) throws IOException {
     synchronized (this) {
-      InMemoryContentInfo status = scopeLimitedStat(path, true);
+      InMemoryContentInfo status = inodeStat(path, true);
       if (status.isDirectory()) {
         throw Error.EISDIR.exception(path);
       }
@@ -772,7 +698,7 @@
   @Override
   public byte[] getxattr(Path path, String name) throws IOException {
     synchronized (this) {
-      InMemoryContentInfo status = scopeLimitedStat(path, true);
+      InMemoryContentInfo status = inodeStat(path, true);
       if (status.isDirectory()) {
         throw Error.EISDIR.exception(path);
       }
@@ -787,7 +713,7 @@
   @Override
   protected byte[] getFastDigest(Path path) throws IOException {
     synchronized (this) {
-      InMemoryContentInfo status = scopeLimitedStat(path, true);
+      InMemoryContentInfo status = inodeStat(path, true);
       if (status.isDirectory()) {
         throw Error.EISDIR.exception(path);
       }
diff --git a/src/test/java/com/google/devtools/build/lib/pkgcache/IOExceptionsTest.java b/src/test/java/com/google/devtools/build/lib/pkgcache/IOExceptionsTest.java
index de8e71b..7273270 100644
--- a/src/test/java/com/google/devtools/build/lib/pkgcache/IOExceptionsTest.java
+++ b/src/test/java/com/google/devtools/build/lib/pkgcache/IOExceptionsTest.java
@@ -28,7 +28,6 @@
 import com.google.devtools.build.lib.vfs.FileSystem;
 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.inmemoryfs.InMemoryFileSystem;
 import com.google.devtools.build.skyframe.EvaluationResult;
@@ -48,8 +47,6 @@
 @RunWith(JUnit4.class)
 public class IOExceptionsTest extends PackageLoadingTestCase {
 
-  private static final String FS_ROOT = "/fsg";
-
   private static final Function<Path, String> NULL_FUNCTION = new Function<Path, String>() {
     @Override
     @Nullable
@@ -82,7 +79,7 @@
 
   @Override
   protected FileSystem createFileSystem() {
-    return new InMemoryFileSystem(BlazeClock.instance(), PathFragment.create(FS_ROOT)) {
+    return new InMemoryFileSystem(BlazeClock.instance()) {
       @Override
       public FileStatus stat(Path path, boolean followSymlinks) throws IOException {
         String crash = crashMessage.apply(path);
diff --git a/src/test/java/com/google/devtools/build/lib/pkgcache/TargetPatternEvaluatorIOTest.java b/src/test/java/com/google/devtools/build/lib/pkgcache/TargetPatternEvaluatorIOTest.java
index f2a7233..2ab8977 100644
--- a/src/test/java/com/google/devtools/build/lib/pkgcache/TargetPatternEvaluatorIOTest.java
+++ b/src/test/java/com/google/devtools/build/lib/pkgcache/TargetPatternEvaluatorIOTest.java
@@ -22,7 +22,6 @@
 import com.google.devtools.build.lib.vfs.FileSystem;
 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.inmemoryfs.InMemoryContentInfo;
 import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
 import java.io.IOException;
@@ -57,7 +56,7 @@
 
   @Override
   protected FileSystem createFileSystem() {
-    return new InMemoryFileSystem(BlazeClock.instance(), PathFragment.create(FS_ROOT)) {
+    return new InMemoryFileSystem(BlazeClock.instance()) {
       @Override
       public FileStatus stat(Path path, boolean followSymlinks) throws IOException {
         FileStatus defaultResult = super.stat(path, followSymlinks);