Rollback of commit b776d6c12e952eb358c1a036cc9d93d8944c4c77.

*** Reason for rollback ***

--
MOS_MIGRATED_REVID=136448178
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/DirectoryListingStateFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/DirectoryListingStateFunction.java
index aa1fe76..307c74b 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/DirectoryListingStateFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/DirectoryListingStateFunction.java
@@ -45,8 +45,10 @@
         return null;
       }
       return DirectoryListingStateValue.create(dirRootedPath);
-    } catch (FileOutsidePackageRootsException e) {
-      throw new DirectoryListingStateFunctionException(e);
+    } catch (ExternalFilesHelper.NonexistentImmutableExternalFileException e) {
+      // DirectoryListingStateValue.key assumes the path exists. This exception here is therefore
+      // indicative of a programming bug.
+      throw new IllegalStateException(dirRootedPath.toString(), e);
     } catch (IOException e) {
       throw new DirectoryListingStateFunctionException(e);
     }
@@ -66,9 +68,5 @@
     public DirectoryListingStateFunctionException(IOException e) {
       super(e, Transience.TRANSIENT);
     }
-
-    public DirectoryListingStateFunctionException(FileOutsidePackageRootsException e) {
-      super(e, Transience.PERSISTENT);
-    }
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ExternalFilesHelper.java b/src/main/java/com/google/devtools/build/lib/skyframe/ExternalFilesHelper.java
index 664cf98..e757c27 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ExternalFilesHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ExternalFilesHelper.java
@@ -26,7 +26,7 @@
 import java.io.IOException;
 import java.util.concurrent.atomic.AtomicReference;
 
-/** Common utilities for dealing with files outside the package roots. */
+/** Common utilities for dealing with paths outside the package roots. */
 public class ExternalFilesHelper {
   private final AtomicReference<PathPackageLocator> pkgLocator;
   private final ExternalFileAction externalFileAction;
@@ -37,23 +37,8 @@
   private boolean anyOutputFilesSeen = false;
   private boolean anyNonOutputExternalFilesSeen = false;
 
-  /**
-   * @param pkgLocator an {@link AtomicReference} to a {@link PathPackageLocator} used to
-   *    determine what files are internal.
-   * @param errorOnExternalFiles If files outside of package paths should be allowed.
-   */
   public ExternalFilesHelper(
-      AtomicReference<PathPackageLocator> pkgLocator, boolean errorOnExternalFiles,
-      BlazeDirectories directories) {
-    this(
-        pkgLocator,
-        errorOnExternalFiles
-            ? ExternalFileAction.ERROR_OUT
-            : ExternalFileAction.DEPEND_ON_EXTERNAL_PKG_FOR_EXTERNAL_REPO_FILES,
-        directories);
-  }
-
-  private ExternalFilesHelper(AtomicReference<PathPackageLocator> pkgLocator,
+      AtomicReference<PathPackageLocator> pkgLocator,
       ExternalFileAction externalFileAction,
       BlazeDirectories directories) {
     this.pkgLocator = pkgLocator;
@@ -61,25 +46,42 @@
     this.directories = directories;
   }
 
-  private enum ExternalFileAction {
-    /** Re-check the files when the WORKSPACE file changes. */
-    DEPEND_ON_EXTERNAL_PKG_FOR_EXTERNAL_REPO_FILES,
-
-    /** Throw an exception if there is an external file. */
-    ERROR_OUT,
-  }
-
-  enum FileType {
-    /** A file inside the package roots or in an external repository. */
-    INTERNAL,
-
-    /** A file outside the package roots about which we may make no other assumptions. */
-    EXTERNAL_MUTABLE,
+  /**
+   * The action to take when an external path is encountered. See {@link FileType} for the
+   * definition of "external".
+   */
+  public enum ExternalFileAction {
+    /**
+     * For paths of type {@link FileType#EXTERNAL_REPO}, introduce a Skyframe dependency on the
+     * 'external' package.
+     *
+     * <p>This is the default for Bazel, since it's required for correctness of the external
+     * repositories feature.
+     */
+    DEPEND_ON_EXTERNAL_PKG_FOR_EXTERNAL_REPO_PATHS,
 
     /**
-     * A file in Bazel's output tree that's a proper output of an action (*not* a source file in an
-     * external repository). Such files are theoretically mutable, but certain Blaze flags may tell
-     * Blaze to assume these files are immutable.
+     * For paths of type {@link FileType#EXTERNAL} or {@link FileType#OUTPUT}, assume the path does
+     * not exist and will never exist.
+     */
+    ASSUME_NON_EXISTENT_AND_IMMUTABLE_FOR_EXTERNAL_PATHS,
+  }
+
+  /** Classification of a path encountered by Bazel. */
+  public enum FileType {
+    /** A path inside the package roots or in an external repository. */
+    INTERNAL,
+
+    /**
+     * A non {@link #EXTERNAL_REPO} path outside the package roots about which we may make no other
+     * assumptions.
+     */
+    EXTERNAL,
+
+    /**
+     * A path in Bazel's output tree that's a proper output of an action (*not* a source file in an
+     * external repository). Such files are theoretically mutable, but certain Bazel flags may tell
+     * Bazel to assume these paths are immutable.
      *
      * <p>Note that {@link ExternalFilesHelper#maybeHandleExternalFile} is only used for {@link
      * FileStateValue} and {@link DirectoryListingStateValue}, and also note that output files do
@@ -93,12 +95,19 @@
     OUTPUT,
 
     /**
-     * A file in the part of Bazel's output tree that contains (/ symlinks to) to external
+     * A path in the part of Bazel's output tree that contains (/ symlinks to) to external
      * repositories.
      */
     EXTERNAL_REPO,
   }
 
+  /**
+   * Thrown by {@link #maybeHandleExternalFile} when an applicable path is processed (see
+   * {@link ExternalFileAction#ASSUME_NON_EXISTENT_AND_IMMUTABLE_FOR_EXTERNAL_PATHS}.
+   */
+  static class NonexistentImmutableExternalFileException extends Exception {
+  }
+
   static class ExternalFilesKnowledge {
     final boolean anyOutputFilesSeen;
     final boolean anyNonOutputExternalFilesSeen;
@@ -134,7 +143,7 @@
     Path outputBase = packageLocator.getOutputBase();
     if (outputBase == null) {
       anyNonOutputExternalFilesSeen = true;
-      return FileType.EXTERNAL_MUTABLE;
+      return FileType.EXTERNAL;
     }
     if (rootedPath.asPath().startsWith(outputBase)) {
       Path externalRepoDir = outputBase.getRelative(Label.EXTERNAL_PACKAGE_NAME);
@@ -147,29 +156,33 @@
       }
     }
     anyNonOutputExternalFilesSeen = true;
-    return FileType.EXTERNAL_MUTABLE;
+    return FileType.EXTERNAL;
   }
 
   /**
-   * If this instance is configured with DEPEND_ON_EXTERNAL_PKG and rootedPath is a file that isn't
-   * under a package root then this adds a dependency on the //external package. If the action is
-   * ERROR_OUT, it will throw an error instead.
+   * If this instance is configured with
+   * {@link ExternalFileAction#DEPEND_ON_EXTERNAL_PKG_FOR_EXTERNAL_REPO_PATHS} and
+   * {@code rootedPath} isn't under a package root then this adds a dependency on the //external
+   * package. If the action is
+   * {@link ExternalFileAction#ASSUME_NON_EXISTENT_AND_IMMUTABLE_FOR_EXTERNAL_PATHS}, it will throw
+   * a {@link NonexistentImmutableExternalFileException} instead.
    */
   @ThreadSafe
   void maybeHandleExternalFile(RootedPath rootedPath, SkyFunction.Environment env)
-      throws IOException, InterruptedException {
+      throws NonexistentImmutableExternalFileException, IOException, InterruptedException {
     FileType fileType = getAndNoteFileType(rootedPath);
     if (fileType == FileType.INTERNAL) {
       return;
     }
-    if (fileType == FileType.OUTPUT || fileType == FileType.EXTERNAL_MUTABLE) {
-      if (externalFileAction == ExternalFileAction.ERROR_OUT) {
-        throw new FileOutsidePackageRootsException(rootedPath);
+    if (fileType == FileType.OUTPUT || fileType == FileType.EXTERNAL) {
+      if (externalFileAction
+          == ExternalFileAction.ASSUME_NON_EXISTENT_AND_IMMUTABLE_FOR_EXTERNAL_PATHS) {
+        throw new NonexistentImmutableExternalFileException();
       }
       return;
     }
     Preconditions.checkState(
-        externalFileAction == ExternalFileAction.DEPEND_ON_EXTERNAL_PKG_FOR_EXTERNAL_REPO_FILES,
+        externalFileAction == ExternalFileAction.DEPEND_ON_EXTERNAL_PKG_FOR_EXTERNAL_REPO_PATHS,
         externalFileAction);
     RepositoryFunction.addExternalFilesDependencies(rootedPath, directories, env);
   }
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 617baad..f06be6b 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
@@ -63,19 +63,7 @@
     // symlink cycle, we want to detect that quickly as it gives a more informative error message
     // than we'd get doing bogus filesystem operations.
     if (!relativePath.equals(PathFragment.EMPTY_FRAGMENT)) {
-      Pair<RootedPath, FileStateValue> resolvedState = null;
-
-      try {
-        resolvedState = resolveFromAncestors(rootedPath, env);
-      } catch (FileOutsidePackageRootsException e) {
-        // When getting a FileOutsidePackageRootsException caused by an external file symlink
-        // somewhere in this file's path, rethrow an exception with this file's path, so the error
-        // message mentions this file instead of the first ancestor path where the external file
-        // error is observed
-        throw new FileFunctionException(
-            new FileOutsidePackageRootsException(rootedPath), Transience.PERSISTENT);
-      }
-
+      Pair<RootedPath, FileStateValue> resolvedState = resolveFromAncestors(rootedPath, env);
       if (resolvedState == null) {
         return null;
       }
@@ -94,15 +82,7 @@
     if (rootedPath.equals(realRootedPath)) {
       fileStateValue = Preconditions.checkNotNull(realFileStateValue, rootedPath);
     } else {
-      try {
-        fileStateValue =
-            (FileStateValue)
-                env.getValueOrThrow(
-                    FileStateValue.key(rootedPath), FileOutsidePackageRootsException.class);
-      } catch (FileOutsidePackageRootsException e) {
-        throw new FileFunctionException(
-            new FileOutsidePackageRootsException(rootedPath), Transience.PERSISTENT);
-      }
+      fileStateValue = (FileStateValue) env.getValue(FileStateValue.key(rootedPath));
       if (fileStateValue == null) {
         return null;
       }
@@ -136,7 +116,7 @@
   @Nullable
   private static Pair<RootedPath, FileStateValue> resolveFromAncestors(
       RootedPath rootedPath, Environment env)
-      throws FileFunctionException, FileOutsidePackageRootsException, InterruptedException {
+      throws FileFunctionException, InterruptedException {
     PathFragment relativePath = rootedPath.getRelativePath();
     RootedPath realRootedPath = rootedPath;
     FileValue parentFileValue = null;
@@ -144,11 +124,7 @@
       RootedPath parentRootedPath = RootedPath.toRootedPath(rootedPath.getRoot(),
           relativePath.getParentDirectory());
 
-      parentFileValue =
-          (FileValue)
-              env.getValueOrThrow(
-                  FileValue.key(parentRootedPath), FileOutsidePackageRootsException.class);
-
+      parentFileValue = (FileValue) env.getValue(FileValue.key(parentRootedPath));
       if (parentFileValue == null) {
         return null;
       }
@@ -164,8 +140,7 @@
     }
     FileStateValue realFileStateValue =
         (FileStateValue)
-            env.getValueOrThrow(
-                FileStateValue.key(realRootedPath), FileOutsidePackageRootsException.class);
+            env.getValue(FileStateValue.key(realRootedPath));
 
     if (realFileStateValue == null) {
       return null;
@@ -281,17 +256,7 @@
       throw new FileFunctionException(Preconditions.checkNotNull(fse, rootedPath));
     }
 
-    try {
-      return resolveFromAncestors(symlinkTargetRootedPath, env);
-    } catch (FileOutsidePackageRootsException e) {
-      // At this point we know this file node is a symlink leading to an external file. Mark the
-      // exception to be a specific SymlinkOutsidePackageRootsException. The error will be bubbled
-      // up further but no path information will be updated again. This allows preserving the
-      // information about the symlink crossing the internal/external boundary.
-      throw new FileFunctionException(
-          new SymlinkOutsidePackageRootsException(rootedPath, symlinkTargetRootedPath),
-          Transience.PERSISTENT);
-    }
+    return resolveFromAncestors(symlinkTargetRootedPath, env);
   }
 
   private static final Predicate<RootedPath> isPathPredicate(final Path path) {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/FileOutsidePackageRootsException.java b/src/main/java/com/google/devtools/build/lib/skyframe/FileOutsidePackageRootsException.java
deleted file mode 100644
index ce9e27c..0000000
--- a/src/main/java/com/google/devtools/build/lib/skyframe/FileOutsidePackageRootsException.java
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2015 The Bazel Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package com.google.devtools.build.lib.skyframe;
-
-import com.google.devtools.build.lib.vfs.RootedPath;
-
-import java.io.IOException;
-
-/**
- * <p>This is an implementation detail of {@link FileFunction} to signal attempt to evaluate a file
- * outside of known/allowed directory structures.
- *
- * <p>Extends {@link IOException} to ensure it is properly handled by consumers of
- * {@link FileValue}.
- */
-// TODO(bazel-team): Don't piggyback on existing handling of IOExceptions and instead implement
-// the desired semantics.
-class FileOutsidePackageRootsException extends IOException {
-
-  /** @param outsidePath the {@link RootedPath} that triggered this exception. */
-  public FileOutsidePackageRootsException(RootedPath outsidePath) {
-    super("Encountered reference to external mutable " + outsidePath);
-  }
-}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/FileStateFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/FileStateFunction.java
index f2dfff8..dece88c 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/FileStateFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/FileStateFunction.java
@@ -50,8 +50,8 @@
         return null;
       }
       return FileStateValue.create(rootedPath, tsgm.get());
-    } catch (FileOutsidePackageRootsException e) {
-      throw new FileStateFunctionException(e);
+    } catch (ExternalFilesHelper.NonexistentImmutableExternalFileException e) {
+      return FileStateValue.NONEXISTENT_FILE_STATE_NODE;
     } catch (IOException e) {
       throw new FileStateFunctionException(e);
     } catch (InconsistentFilesystemException e) {
@@ -76,9 +76,5 @@
     public FileStateFunctionException(InconsistentFilesystemException e) {
       super(e, Transience.TRANSIENT);
     }
-
-    public FileStateFunctionException(FileOutsidePackageRootsException e) {
-      super(e, Transience.PERSISTENT);
-    }
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
index 9db19e5..4573a51 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
@@ -221,8 +221,7 @@
       Iterable<SkyKey> depKeys,
       Environment env,
       boolean packageWasInError)
-      throws InternalInconsistentFilesystemException, FileOutsidePackageRootsException,
-          SymlinkOutsidePackageRootsException, InterruptedException {
+      throws InternalInconsistentFilesystemException, InterruptedException {
     Preconditions.checkState(
         Iterables.all(depKeys, SkyFunctions.isSkyFunction(SkyFunctions.FILE)), depKeys);
     boolean packageShouldBeInError = packageWasInError;
@@ -231,8 +230,6 @@
             FileSymlinkException.class, InconsistentFilesystemException.class).entrySet()) {
       try {
         entry.getValue().get();
-      } catch (FileOutsidePackageRootsException | SymlinkOutsidePackageRootsException e) {
-        throw e;
       } catch (IOException e) {
         maybeThrowFilesystemInconsistency(packageIdentifier, e, packageWasInError);
       } catch (FileSymlinkException e) {
@@ -254,8 +251,7 @@
       Iterable<SkyKey> depKeys,
       Environment env,
       boolean packageWasInError)
-      throws InternalInconsistentFilesystemException, FileOutsidePackageRootsException,
-          SymlinkOutsidePackageRootsException, InterruptedException {
+      throws InternalInconsistentFilesystemException, InterruptedException {
     Preconditions.checkState(
         Iterables.all(depKeys, SkyFunctions.isSkyFunction(SkyFunctions.GLOB)), depKeys);
     boolean packageShouldBeInError = packageWasInError;
@@ -265,8 +261,6 @@
             FileSymlinkException.class, InconsistentFilesystemException.class).entrySet()) {
       try {
         entry.getValue().get();
-      } catch (FileOutsidePackageRootsException | SymlinkOutsidePackageRootsException e) {
-        throw e;
       } catch (IOException | BuildFileNotFoundException e) {
         maybeThrowFilesystemInconsistency(packageIdentifier, e, packageWasInError);
       } catch (FileSymlinkException e) {
@@ -294,8 +288,7 @@
       Map<Label, Path> subincludes,
       PackageIdentifier packageIdentifier,
       boolean containsErrors)
-      throws InternalInconsistentFilesystemException, FileOutsidePackageRootsException,
-          SymlinkOutsidePackageRootsException, InterruptedException {
+      throws InternalInconsistentFilesystemException, InterruptedException {
     boolean packageShouldBeInError = containsErrors;
 
     // TODO(bazel-team): This means that many packages will have to be preprocessed twice. Ouch!
@@ -550,11 +543,6 @@
       throw new PackageFunctionException(
           e.toNoSuchPackageException(),
           e.isTransient() ? Transience.TRANSIENT : Transience.PERSISTENT);
-    } catch (FileOutsidePackageRootsException | SymlinkOutsidePackageRootsException e) {
-      packageFunctionCache.invalidate(packageId);
-      throw new PackageFunctionException(
-          new NoSuchPackageException(packageId, "Encountered file outside package roots", e),
-          Transience.PERSISTENT);
     }
     if (env.valuesMissing()) {
       return null;
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SequencedSkyframeExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SequencedSkyframeExecutor.java
index 3eee0c1..7a45eed 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SequencedSkyframeExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SequencedSkyframeExecutor.java
@@ -44,6 +44,7 @@
 import com.google.devtools.build.lib.skyframe.DirtinessCheckerUtils.ExternalDirtinessChecker;
 import com.google.devtools.build.lib.skyframe.DirtinessCheckerUtils.MissingDiffDirtinessChecker;
 import com.google.devtools.build.lib.skyframe.DirtinessCheckerUtils.UnionDirtinessChecker;
+import com.google.devtools.build.lib.skyframe.ExternalFilesHelper.ExternalFileAction;
 import com.google.devtools.build.lib.skyframe.ExternalFilesHelper.ExternalFilesKnowledge;
 import com.google.devtools.build.lib.skyframe.ExternalFilesHelper.FileType;
 import com.google.devtools.build.lib.skyframe.PackageLookupFunction.CrossRepositoryLabelViolationStrategy;
@@ -123,7 +124,7 @@
         preprocessorFactorySupplier,
         extraSkyFunctions,
         extraPrecomputedValues,
-        false,
+        ExternalFileAction.DEPEND_ON_EXTERNAL_PKG_FOR_EXTERNAL_REPO_PATHS,
         blacklistedPackagePrefixesFile,
         productName,
         crossRepositoryLabelViolationStrategy);
@@ -421,8 +422,8 @@
         externalFilesHelper.cloneWithFreshExternalFilesKnowledge();
     // See the comment for FileType.OUTPUT for why we need to consider output files here.
     EnumSet<FileType> fileTypesToCheck = checkOutputFiles
-        ? EnumSet.of(FileType.EXTERNAL_MUTABLE, FileType.EXTERNAL_REPO, FileType.OUTPUT)
-        : EnumSet.of(FileType.EXTERNAL_MUTABLE, FileType.EXTERNAL_REPO);
+        ? EnumSet.of(FileType.EXTERNAL, FileType.EXTERNAL_REPO, FileType.OUTPUT)
+        : EnumSet.of(FileType.EXTERNAL, FileType.EXTERNAL_REPO);
     Differencer.Diff diff =
         fsvc.getDirtyKeys(
             memoizingEvaluator.getValues(),
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
index ce4c748..146c468 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
@@ -105,6 +105,7 @@
 import com.google.devtools.build.lib.profiler.AutoProfiler;
 import com.google.devtools.build.lib.skyframe.AspectValue.AspectValueKey;
 import com.google.devtools.build.lib.skyframe.DirtinessCheckerUtils.FileDirtinessChecker;
+import com.google.devtools.build.lib.skyframe.ExternalFilesHelper.ExternalFileAction;
 import com.google.devtools.build.lib.skyframe.PackageFunction.CacheEntryWithGlobDeps;
 import com.google.devtools.build.lib.skyframe.PackageLookupFunction.CrossRepositoryLabelViolationStrategy;
 import com.google.devtools.build.lib.skyframe.SkyframeActionExecutor.ActionCompletedReceiver;
@@ -254,7 +255,7 @@
   protected int outputDirtyFiles;
   protected int modifiedFilesDuringPreviousBuild;
   private final Predicate<PathFragment> allowedMissingInputs;
-  private final boolean errorOnExternalFiles;
+  private final ExternalFileAction externalFileAction;
 
   private final ImmutableMap<SkyFunctionName, SkyFunction> extraSkyFunctions;
   private final ImmutableList<PrecomputedValue.Injected> extraPrecomputedValues;
@@ -287,7 +288,7 @@
       Preprocessor.Factory.Supplier preprocessorFactorySupplier,
       ImmutableMap<SkyFunctionName, SkyFunction> extraSkyFunctions,
       ImmutableList<PrecomputedValue.Injected> extraPrecomputedValues,
-      boolean errorOnExternalFiles,
+      ExternalFileAction externalFileAction,
       PathFragment blacklistedPackagePrefixesFile,
       String productName,
       CrossRepositoryLabelViolationStrategy crossRepositoryLabelViolationStrategy) {
@@ -309,7 +310,7 @@
     this.preprocessorFactorySupplier = preprocessorFactorySupplier;
     this.extraSkyFunctions = extraSkyFunctions;
     this.extraPrecomputedValues = extraPrecomputedValues;
-    this.errorOnExternalFiles = errorOnExternalFiles;
+    this.externalFileAction = externalFileAction;
     this.blacklistedPackagePrefixesFile = blacklistedPackagePrefixesFile;
     this.binTools = binTools;
 
@@ -321,7 +322,7 @@
         (ConfiguredRuleClassProvider) ruleClassProvider);
     this.artifactFactory.set(skyframeBuildView.getArtifactFactory());
     this.externalFilesHelper = new ExternalFilesHelper(
-        pkgLocator, this.errorOnExternalFiles, directories);
+        pkgLocator, this.externalFileAction, directories);
     this.productName = productName;
     this.crossRepositoryLabelViolationStrategy = crossRepositoryLabelViolationStrategy;
   }
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SymlinkOutsidePackageRootsException.java b/src/main/java/com/google/devtools/build/lib/skyframe/SymlinkOutsidePackageRootsException.java
deleted file mode 100644
index 3f20ce0..0000000
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SymlinkOutsidePackageRootsException.java
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2016 The Bazel Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package com.google.devtools.build.lib.skyframe;
-
-import com.google.devtools.build.lib.vfs.RootedPath;
-
-import java.io.IOException;
-
-/**
- * <p>This is an implementation detail of {@link FileFunction} to to evaluate a symlink linking to
- * file outside of known/allowed directory structures.
- *
- * <p>Extends {@link IOException} to ensure it is properly handled by consumers of
- * {@link FileValue}.
- */
-class SymlinkOutsidePackageRootsException extends IOException {
-  /**
-   * @param symlinkPath the {@link RootedPath} that links to an outside path.
-   * @param outsidePath the {@link RootedPath} that triggered this exception.
-   */
-  public SymlinkOutsidePackageRootsException(RootedPath symlinkPath, RootedPath outsidePath) {
-    super("Encountered symlink " + symlinkPath + " linking to external mutable " + outsidePath);
-  }
-}
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/ArtifactFunctionTestCase.java b/src/test/java/com/google/devtools/build/lib/skyframe/ArtifactFunctionTestCase.java
index 79e4013..cd017be 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/ArtifactFunctionTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/ArtifactFunctionTestCase.java
@@ -21,6 +21,7 @@
 import com.google.devtools.build.lib.analysis.BlazeDirectories;
 import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
 import com.google.devtools.build.lib.skyframe.ActionLookupValue.ActionLookupKey;
+import com.google.devtools.build.lib.skyframe.ExternalFilesHelper.ExternalFileAction;
 import com.google.devtools.build.lib.skyframe.PackageLookupFunction.CrossRepositoryLabelViolationStrategy;
 import com.google.devtools.build.lib.testutil.TestConstants;
 import com.google.devtools.build.lib.testutil.TestRuleClassProvider;
@@ -73,7 +74,9 @@
     BlazeDirectories directories = new BlazeDirectories(root, root, root,
         TestConstants.PRODUCT_NAME);
     ExternalFilesHelper externalFilesHelper = new ExternalFilesHelper(
-        pkgLocator, false, directories);
+        pkgLocator,
+        ExternalFileAction.DEPEND_ON_EXTERNAL_PKG_FOR_EXTERNAL_REPO_PATHS,
+        directories);
     differencer = new RecordingDifferencer();
     evaluator =
         new InMemoryMemoizingEvaluator(
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/ContainingPackageLookupFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/ContainingPackageLookupFunctionTest.java
index 6c42579..ea1fc81 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/ContainingPackageLookupFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/ContainingPackageLookupFunctionTest.java
@@ -24,6 +24,7 @@
 import com.google.devtools.build.lib.cmdline.PackageIdentifier;
 import com.google.devtools.build.lib.events.NullEventHandler;
 import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
+import com.google.devtools.build.lib.skyframe.ExternalFilesHelper.ExternalFileAction;
 import com.google.devtools.build.lib.skyframe.PackageLookupFunction.CrossRepositoryLabelViolationStrategy;
 import com.google.devtools.build.lib.testutil.FoundationTestCase;
 import com.google.devtools.build.lib.testutil.TestConstants;
@@ -61,8 +62,10 @@
         new AtomicReference<>(new PathPackageLocator(outputBase, ImmutableList.of(rootDirectory)));
     deletedPackages = new AtomicReference<>(ImmutableSet.<PackageIdentifier>of());
     ExternalFilesHelper externalFilesHelper = new ExternalFilesHelper(
-        pkgLocator, false, new BlazeDirectories(rootDirectory, rootDirectory, rootDirectory,
-            TestConstants.PRODUCT_NAME));
+        pkgLocator,
+        ExternalFileAction.DEPEND_ON_EXTERNAL_PKG_FOR_EXTERNAL_REPO_PATHS,
+        new BlazeDirectories(
+            rootDirectory, rootDirectory, rootDirectory, TestConstants.PRODUCT_NAME));
 
     Map<SkyFunctionName, SkyFunction> skyFunctions = new HashMap<>();
     skyFunctions.put(
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/FileFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/FileFunctionTest.java
index 6308953..131dbbb 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/FileFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/FileFunctionTest.java
@@ -40,6 +40,7 @@
 import com.google.devtools.build.lib.events.NullEventHandler;
 import com.google.devtools.build.lib.events.StoredEventHandler;
 import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
+import com.google.devtools.build.lib.skyframe.ExternalFilesHelper.ExternalFileAction;
 import com.google.devtools.build.lib.skyframe.PackageLookupFunction.CrossRepositoryLabelViolationStrategy;
 import com.google.devtools.build.lib.testutil.ManualClock;
 import com.google.devtools.build.lib.testutil.TestConstants;
@@ -113,15 +114,15 @@
   }
 
   private SequentialBuildDriver makeDriver() {
-    return makeDriver(/*errorOnExternalFiles=*/ false);
+    return makeDriver(ExternalFileAction.DEPEND_ON_EXTERNAL_PKG_FOR_EXTERNAL_REPO_PATHS);
   }
 
-  private SequentialBuildDriver makeDriver(boolean errorOnExternalFiles) {
+  private SequentialBuildDriver makeDriver(ExternalFileAction externalFileAction) {
     AtomicReference<PathPackageLocator> pkgLocatorRef = new AtomicReference<>(pkgLocator);
     BlazeDirectories directories =
         new BlazeDirectories(pkgRoot, outputBase, pkgRoot, TestConstants.PRODUCT_NAME);
     ExternalFilesHelper externalFilesHelper =
-        new ExternalFilesHelper(pkgLocatorRef, errorOnExternalFiles, directories);
+        new ExternalFilesHelper(pkgLocatorRef, externalFileAction, directories);
     differencer = new RecordingDifferencer();
     MemoizingEvaluator evaluator =
         new InMemoryMemoizingEvaluator(
@@ -657,99 +658,76 @@
   }
 
   @Test
-  public void testFilesOutsideRootWhenExternalDisallowed() throws Exception {
+  public void testFilesOutsideRootWhenExternalAssumedNonExistentAndImmutable() throws Exception {
     file("/outsideroot");
 
-    SequentialBuildDriver driver = makeDriver(/*errorOnExternalFiles=*/ true);
+    SequentialBuildDriver driver =
+        makeDriver(ExternalFileAction.ASSUME_NON_EXISTENT_AND_IMMUTABLE_FOR_EXTERNAL_PATHS);
     SkyKey key = skyKey("/outsideroot");
     EvaluationResult<SkyValue> result =
         driver.evaluate(
             ImmutableList.of(key), false, DEFAULT_THREAD_COUNT, NullEventHandler.INSTANCE);
 
-    assertTrue(result.hasError());
-    assertThatEvaluationResult(result)
-        .hasErrorEntryForKeyThat(key)
-        .hasExceptionThat()
-        .isInstanceOf(FileOutsidePackageRootsException.class);
-    assertThatEvaluationResult(result)
-        .hasErrorEntryForKeyThat(key)
-        .hasExceptionThat()
-        .hasMessage("Encountered reference to external mutable [/]/[outsideroot]");
+    assertThatEvaluationResult(result).hasNoError();
+    FileValue value = (FileValue) result.get(key);
+    assertThat(value).isNotNull();
+    assertFalse(value.exists());
   }
 
   @Test
-  public void testAbsoluteSymlinksToFilesOutsideRootWhenExternalDisallowed() throws Exception {
+  public void testAbsoluteSymlinksToFilesOutsideRootWhenExternalAssumedNonExistentAndImmutable()
+      throws Exception {
     file("/outsideroot");
     symlink("a", "/outsideroot");
 
-    SequentialBuildDriver driver = makeDriver(/*errorOnExternalFiles=*/ true);
+    SequentialBuildDriver driver =
+        makeDriver(ExternalFileAction.ASSUME_NON_EXISTENT_AND_IMMUTABLE_FOR_EXTERNAL_PATHS);
     SkyKey key = skyKey("a");
     EvaluationResult<SkyValue> result =
         driver.evaluate(
             ImmutableList.of(key), false, DEFAULT_THREAD_COUNT, NullEventHandler.INSTANCE);
 
-    assertTrue(result.hasError());
-    assertThatEvaluationResult(result)
-        .hasErrorEntryForKeyThat(key)
-        .hasExceptionThat()
-        .isInstanceOf(SymlinkOutsidePackageRootsException.class);
-    assertThatEvaluationResult(result)
-        .hasErrorEntryForKeyThat(key)
-        .hasExceptionThat()
-        .hasMessage(
-            "Encountered symlink [/root]/[a] linking to external mutable [/]/[outsideroot]");
+    assertThatEvaluationResult(result).hasNoError();
+    FileValue value = (FileValue) result.get(key);
+    assertThat(value).isNotNull();
+    assertFalse(value.exists());
   }
 
-  /**
-   * A slightly more complicated negative test to ensure that the error message contains the real
-   * symlink and external path instead of the path of the top-level skyframe file node. In other
-   * words, the error is bubbled up to the top-level node, but the error message stops getting
-   * updated once it enters the internal path boundary.
-   */
   @Test
-  public void testAbsoluteSymlinksReferredByInternalFilesToFilesOutsideRootWhenExternalDisallowed()
+  public void testAbsoluteSymlinksReferredByInternalFilesToFilesOutsideRootWhenExternalAssumedNonExistentAndImmutable()
       throws Exception {
     file("/outsideroot/src/foo/bar");
     symlink("/root/src", "/outsideroot/src");
 
-    SequentialBuildDriver driver = makeDriver(/*errorOnExternalFiles=*/ true);
+    SequentialBuildDriver driver =
+        makeDriver(ExternalFileAction.ASSUME_NON_EXISTENT_AND_IMMUTABLE_FOR_EXTERNAL_PATHS);
     SkyKey key = skyKey("/root/src/foo/bar");
     EvaluationResult<SkyValue> result =
         driver.evaluate(
             ImmutableList.of(key), false, DEFAULT_THREAD_COUNT, NullEventHandler.INSTANCE);
 
-    assertTrue(result.hasError());
-    assertThatEvaluationResult(result)
-        .hasErrorEntryForKeyThat(key)
-        .hasExceptionThat()
-        .isInstanceOf(SymlinkOutsidePackageRootsException.class);
-    assertThatEvaluationResult(result)
-        .hasErrorEntryForKeyThat(key)
-        .hasExceptionThat()
-        .hasMessage(
-            "Encountered symlink [/root]/[src] linking to external mutable [/]/[outsideroot/src]");
+    assertThatEvaluationResult(result).hasNoError();
+    FileValue value = (FileValue) result.get(key);
+    assertThat(value).isNotNull();
+    assertFalse(value.exists());
   }
 
   @Test
-  public void testRelativeSymlinksToFilesOutsideRootWhenExternalDisallowed() throws Exception {
+  public void testRelativeSymlinksToFilesOutsideRootWhenExternalAssumedNonExistentAndImmutable()
+      throws Exception {
     file("../outsideroot");
     symlink("a", "../outsideroot");
-    SequentialBuildDriver driver = makeDriver(/*errorOnExternalFiles=*/ true);
+    SequentialBuildDriver driver = 
+        makeDriver(ExternalFileAction.ASSUME_NON_EXISTENT_AND_IMMUTABLE_FOR_EXTERNAL_PATHS);
     SkyKey key = skyKey("a");
     EvaluationResult<SkyValue> result =
         driver.evaluate(
             ImmutableList.of(key), false, DEFAULT_THREAD_COUNT, NullEventHandler.INSTANCE);
 
-    assertTrue(result.hasError());
-    assertThatEvaluationResult(result)
-        .hasErrorEntryForKeyThat(key)
-        .hasExceptionThat()
-        .isInstanceOf(SymlinkOutsidePackageRootsException.class);
-    assertThatEvaluationResult(result)
-        .hasErrorEntryForKeyThat(key)
-        .hasExceptionThat()
-        .hasMessage(
-            "Encountered symlink [/root]/[a] linking to external mutable [/]/[outsideroot]");
+    assertThatEvaluationResult(result).hasNoError();
+    FileValue value = (FileValue) result.get(key);
+    assertThat(value).isNotNull();
+    assertFalse(value.exists());
   }
 
   @Test
@@ -757,13 +735,18 @@
     Path file = file("insideroot");
     symlink("a", file.getPathString());
 
-    SequentialBuildDriver driver = makeDriver(/*allowExternalReferences=*/ false);
+    SequentialBuildDriver driver =
+        makeDriver(ExternalFileAction.ASSUME_NON_EXISTENT_AND_IMMUTABLE_FOR_EXTERNAL_PATHS);
     SkyKey key = skyKey("a");
     EvaluationResult<SkyValue> result =
         driver.evaluate(
             ImmutableList.of(key), false, DEFAULT_THREAD_COUNT, NullEventHandler.INSTANCE);
 
-    assertFalse(result.hasError());
+    assertThatEvaluationResult(result).hasNoError();
+    FileValue value = (FileValue) result.get(key);
+    assertThat(value).isNotNull();
+    assertTrue(value.exists());
+    assertThat(value.realRootedPath().getRelativePath().getPathString()).isEqualTo("insideroot");
   }
 
   @SuppressWarnings({"rawtypes", "unchecked"})
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/FilesetEntryFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/FilesetEntryFunctionTest.java
index e4b5bbe..3b66ae1 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/FilesetEntryFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/FilesetEntryFunctionTest.java
@@ -36,6 +36,7 @@
 import com.google.devtools.build.lib.events.NullEventHandler;
 import com.google.devtools.build.lib.packages.FilesetEntry.SymlinkBehavior;
 import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
+import com.google.devtools.build.lib.skyframe.ExternalFilesHelper.ExternalFileAction;
 import com.google.devtools.build.lib.skyframe.PackageLookupFunction.CrossRepositoryLabelViolationStrategy;
 import com.google.devtools.build.lib.testutil.FoundationTestCase;
 import com.google.devtools.build.lib.testutil.TestConstants;
@@ -83,8 +84,9 @@
     AtomicReference<ImmutableSet<PackageIdentifier>> deletedPackages =
         new AtomicReference<>(ImmutableSet.<PackageIdentifier>of());
     ExternalFilesHelper externalFilesHelper = new ExternalFilesHelper(
-        pkgLocator, false, new BlazeDirectories(outputBase, outputBase, rootDirectory,
-            TestConstants.PRODUCT_NAME));
+        pkgLocator,
+        ExternalFileAction.DEPEND_ON_EXTERNAL_PKG_FOR_EXTERNAL_REPO_PATHS,
+        new BlazeDirectories(outputBase, outputBase, rootDirectory, TestConstants.PRODUCT_NAME));
 
     Map<SkyFunctionName, SkyFunction> skyFunctions = new HashMap<>();
 
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 1ec88f5..e4bf7f1 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
@@ -37,6 +37,7 @@
 import com.google.devtools.build.lib.events.NullEventHandler;
 import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
 import com.google.devtools.build.lib.skyframe.DirtinessCheckerUtils.BasicFilesystemDirtinessChecker;
+import com.google.devtools.build.lib.skyframe.ExternalFilesHelper.ExternalFileAction;
 import com.google.devtools.build.lib.skyframe.PackageLookupFunction.CrossRepositoryLabelViolationStrategy;
 import com.google.devtools.build.lib.testutil.TestConstants;
 import com.google.devtools.build.lib.testutil.TestRuleClassProvider;
@@ -103,7 +104,7 @@
     BlazeDirectories directories = new BlazeDirectories(pkgRoot, pkgRoot, pkgRoot,
         TestConstants.PRODUCT_NAME);
     ExternalFilesHelper externalFilesHelper = new ExternalFilesHelper(
-        pkgLocator, false, directories);
+        pkgLocator, ExternalFileAction.DEPEND_ON_EXTERNAL_PKG_FOR_EXTERNAL_REPO_PATHS, directories);
     skyFunctions.put(SkyFunctions.FILE_STATE, new FileStateFunction(
         new AtomicReference<TimestampGranularityMonitor>(), externalFilesHelper));
     skyFunctions.put(SkyFunctions.FILE, new FileFunction(pkgLocator));
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/GlobFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/GlobFunctionTest.java
index a00dd07..0209343 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/GlobFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/GlobFunctionTest.java
@@ -30,6 +30,7 @@
 import com.google.devtools.build.lib.cmdline.PackageIdentifier;
 import com.google.devtools.build.lib.events.NullEventHandler;
 import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
+import com.google.devtools.build.lib.skyframe.ExternalFilesHelper.ExternalFileAction;
 import com.google.devtools.build.lib.skyframe.GlobValue.InvalidGlobPatternException;
 import com.google.devtools.build.lib.skyframe.PackageLookupFunction.CrossRepositoryLabelViolationStrategy;
 import com.google.devtools.build.lib.testutil.ManualClock;
@@ -123,7 +124,9 @@
     AtomicReference<ImmutableSet<PackageIdentifier>> deletedPackages =
         new AtomicReference<>(ImmutableSet.<PackageIdentifier>of());
     ExternalFilesHelper externalFilesHelper = new ExternalFilesHelper(
-        pkgLocator, false, new BlazeDirectories(root, root, root, TestConstants.PRODUCT_NAME));
+        pkgLocator,
+        ExternalFileAction.DEPEND_ON_EXTERNAL_PKG_FOR_EXTERNAL_REPO_PATHS,
+        new BlazeDirectories(root, root, root, TestConstants.PRODUCT_NAME));
 
     Map<SkyFunctionName, SkyFunction> skyFunctions = new HashMap<>();
     skyFunctions.put(SkyFunctions.GLOB, new GlobFunction(alwaysUseDirListing()));
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/PackageLookupFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/PackageLookupFunctionTest.java
index c200c41..40bebb7 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/PackageLookupFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/PackageLookupFunctionTest.java
@@ -29,6 +29,7 @@
 import com.google.devtools.build.lib.events.NullEventHandler;
 import com.google.devtools.build.lib.packages.RuleClassProvider;
 import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
+import com.google.devtools.build.lib.skyframe.ExternalFilesHelper.ExternalFileAction;
 import com.google.devtools.build.lib.skyframe.PackageLookupFunction.CrossRepositoryLabelViolationStrategy;
 import com.google.devtools.build.lib.skyframe.PackageLookupValue.BuildFileName;
 import com.google.devtools.build.lib.skyframe.PackageLookupValue.ErrorReason;
@@ -75,7 +76,7 @@
         new BlazeDirectories(
             rootDirectory, outputBase, rootDirectory, analysisMock.getProductName());
     ExternalFilesHelper externalFilesHelper = new ExternalFilesHelper(
-        pkgLocator, false, directories);
+        pkgLocator, ExternalFileAction.DEPEND_ON_EXTERNAL_PKG_FOR_EXTERNAL_REPO_PATHS, directories);
 
     Map<SkyFunctionName, SkyFunction> skyFunctions = new HashMap<>();
     skyFunctions.put(
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunctionTest.java
index 4bbad97..b769b6d 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunctionTest.java
@@ -35,6 +35,7 @@
 import com.google.devtools.build.lib.cmdline.PackageIdentifier;
 import com.google.devtools.build.lib.events.NullEventHandler;
 import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
+import com.google.devtools.build.lib.skyframe.ExternalFilesHelper.ExternalFileAction;
 import com.google.devtools.build.lib.skyframe.PackageLookupFunction.CrossRepositoryLabelViolationStrategy;
 import com.google.devtools.build.lib.skyframe.RecursiveFilesystemTraversalValue.ResolvedFile;
 import com.google.devtools.build.lib.skyframe.RecursiveFilesystemTraversalValue.TraversalRequest;
@@ -89,7 +90,7 @@
         new BlazeDirectories(
             rootDirectory, outputBase, rootDirectory, analysisMock.getProductName());
     ExternalFilesHelper externalFilesHelper = new ExternalFilesHelper(
-        pkgLocator, false, directories);
+        pkgLocator, ExternalFileAction.DEPEND_ON_EXTERNAL_PKG_FOR_EXTERNAL_REPO_PATHS, directories);
 
     ConfiguredRuleClassProvider ruleClassProvider = analysisMock.createRuleClassProvider();
     Map<SkyFunctionName, SkyFunction> skyFunctions = new HashMap<>();
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/TimestampBuilderTestCase.java b/src/test/java/com/google/devtools/build/lib/skyframe/TimestampBuilderTestCase.java
index c5d1022..18f0293 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/TimestampBuilderTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/TimestampBuilderTestCase.java
@@ -50,6 +50,7 @@
 import com.google.devtools.build.lib.events.StoredEventHandler;
 import com.google.devtools.build.lib.exec.SingleBuildFileCache;
 import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
+import com.google.devtools.build.lib.skyframe.ExternalFilesHelper.ExternalFileAction;
 import com.google.devtools.build.lib.skyframe.PackageLookupFunction.CrossRepositoryLabelViolationStrategy;
 import com.google.devtools.build.lib.testutil.FoundationTestCase;
 import com.google.devtools.build.lib.testutil.TestConstants;
@@ -151,7 +152,9 @@
     BlazeDirectories directories = new BlazeDirectories(rootDirectory, outputBase, rootDirectory,
         TestConstants.PRODUCT_NAME);
     ExternalFilesHelper externalFilesHelper = new ExternalFilesHelper(
-        pkgLocator, false, directories);
+        pkgLocator,
+        ExternalFileAction.DEPEND_ON_EXTERNAL_PKG_FOR_EXTERNAL_REPO_PATHS,
+        directories);
     differencer = new RecordingDifferencer();
 
     ActionExecutionStatusReporter statusReporter =