Fix up dependency between RepositoryDirectoryValue and FileStateValue

In `RepositoryFunction#addExternalFilesDependencies`, we introduce a dependency from `FileStateValue($outputBase/external/foo/$SOME_PATH)` to `RepositoryDirectoryValue(@foo)`, _except_ when `$SOME_PATH` is empty (i.e. the "foo" directory itself), or when `@foo` is a local_repository and $SOME_PATH is "WORKSPACE".

These two exceptions are a bit strange (why would we expect anyone to mess with the external directory? and why should that result in a re-fetch?) and exist only because there is a dependency in the reverse direction (that is, `RepositoryDirectoryValue(@foo)` depends on `FileStateValue($outputBase/external/foo)`, and additionally on `FileStateValue($outputBase/external/foo/WORKSPACE)` if `@foo` is a local_repository).

This CL removes these exceptions. This means that the dependency is always from FileStateValue to RepositoryDirectoryValue. Meaning that if the repo definition changes in any way, we'll refetch the files in the external directory; but if the files in the external directory somehow change from under us, we don't trigger a refetch.

This change will also make our lives easier in the future with the external deps overhaul.

PiperOrigin-RevId: 374830398
diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/LocalRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/rules/repository/LocalRepositoryFunction.java
index cbc5779..7ead489 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/repository/LocalRepositoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/repository/LocalRepositoryFunction.java
@@ -15,20 +15,15 @@
 package com.google.devtools.build.lib.rules.repository;
 
 import com.google.common.collect.ImmutableMap;
-import com.google.devtools.build.lib.actions.FileValue;
 import com.google.devtools.build.lib.analysis.BlazeDirectories;
 import com.google.devtools.build.lib.analysis.RuleDefinition;
 import com.google.devtools.build.lib.events.ExtendedEventHandler.ResolvedEvent;
 import com.google.devtools.build.lib.packages.Rule;
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.devtools.build.lib.vfs.PathFragment;
-import com.google.devtools.build.lib.vfs.RootedPath;
 import com.google.devtools.build.skyframe.SkyFunction.Environment;
-import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
 import com.google.devtools.build.skyframe.SkyKey;
-import java.io.IOException;
 import java.util.Map;
-import javax.annotation.Nullable;
 import net.starlark.java.eval.Starlark;
 
 /**
@@ -51,10 +46,10 @@
       SkyKey key)
       throws InterruptedException, RepositoryFunctionException {
     String userDefinedPath = RepositoryFunction.getPathAttr(rule);
-    PathFragment pathFragment =
-        RepositoryFunction.getTargetPath(userDefinedPath, directories.getWorkspace());
+    Path targetPath = directories.getWorkspace().getRelative(userDefinedPath);
     RepositoryDirectoryValue.Builder result =
-        RepositoryDelegatorFunction.symlink(outputDirectory, pathFragment, userDefinedPath, env);
+        RepositoryDelegatorFunction.symlinkRepoRoot(
+            outputDirectory, targetPath, userDefinedPath, env);
     if (result != null) {
       env.getListener().post(resolve(rule, directories));
     }
@@ -66,34 +61,6 @@
     return LocalRepositoryRule.class;
   }
 
-  @Nullable
-  protected static FileValue getWorkspaceFile(RootedPath directory, Environment env)
-      throws RepositoryFunctionException, InterruptedException {
-    RootedPath workspaceRootedFile;
-    try {
-      workspaceRootedFile = WorkspaceFileHelper.getWorkspaceRootedFile(directory, env);
-      if (workspaceRootedFile == null) {
-        return null;
-      }
-    } catch (IOException e) {
-      throw new RepositoryFunctionException(
-          new IOException(
-              "Could not determine workspace file (\"WORKSPACE.bazel\" or \"WORKSPACE\"): "
-                  + e.getMessage()),
-          Transience.PERSISTENT);
-    }
-    SkyKey workspaceFileKey = FileValue.key(workspaceRootedFile);
-    FileValue value;
-    try {
-      value = (FileValue) env.getValueOrThrow(workspaceFileKey, IOException.class);
-    } catch (IOException e) {
-      throw new RepositoryFunctionException(
-          new IOException("Could not access " + workspaceRootedFile + ": " + e.getMessage()),
-          Transience.PERSISTENT);
-    }
-    return value;
-  }
-
   private static ResolvedEvent resolve(Rule rule, BlazeDirectories directories) {
     String name = rule.getName();
     Object pathObj = rule.getAttr("path");
diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorFunction.java b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorFunction.java
index 99f94e7..945af5a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorFunction.java
@@ -42,8 +42,10 @@
 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.RootedPath;
 import com.google.devtools.build.skyframe.SkyFunction;
+import com.google.devtools.build.skyframe.SkyFunction.Environment;
 import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
@@ -128,8 +130,8 @@
     this.externalPackageHelper = externalPackageHelper;
   }
 
-  public static RepositoryDirectoryValue.Builder symlink(
-      Path source, PathFragment destination, String userDefinedPath, Environment env)
+  public static RepositoryDirectoryValue.Builder symlinkRepoRoot(
+      Path source, Path destination, String userDefinedPath, Environment env)
       throws RepositoryFunctionException, InterruptedException {
     try {
       source.createSymbolicLink(destination);
@@ -142,28 +144,41 @@
               e),
           Transience.TRANSIENT);
     }
-    FileValue repositoryValue = RepositoryFunction.getRepositoryDirectory(source, env);
-    if (repositoryValue == null) {
+
+    // Check that the target directory exists and is a directory.
+    // Note that we have to check `destination` and not `source` here, otherwise we'd have a
+    // circular dependency between SkyValues.
+    RootedPath targetDirRootedPath =
+        RootedPath.toRootedPath(Root.absoluteRoot(destination.getFileSystem()), destination);
+    FileValue targetDirValue;
+    try {
+      targetDirValue =
+          (FileValue) env.getValueOrThrow(FileValue.key(targetDirRootedPath), IOException.class);
+    } catch (IOException e) {
+      throw new RepositoryFunctionException(
+          new IOException("Could not access " + destination + ": " + e.getMessage()),
+          Transience.PERSISTENT);
+    }
+    if (targetDirValue == null) {
       // TODO(bazel-team): If this returns null, we unnecessarily recreate the symlink above on the
       // second execution.
       return null;
     }
 
-    if (!repositoryValue.isDirectory()) {
+    if (!targetDirValue.isDirectory()) {
       throw new RepositoryFunctionException(
           new IOException(
               String.format(
                   "The repository's path is \"%s\" (absolute: \"%s\") "
-                      + "but this directory does not exist.",
+                      + "but it does not exist or is not a directory.",
                   userDefinedPath, destination)),
           Transience.PERSISTENT);
     }
 
     // Check that the repository contains a WORKSPACE file.
-    // It's important to check the real path, otherwise this looks under the "external/[repo]" path
-    // and cause a Skyframe cycle in the lookup.
-    FileValue workspaceFileValue =
-        LocalRepositoryFunction.getWorkspaceFile(repositoryValue.realRootedPath(), env);
+    // Note that we need to do this here since we're not creating a WORKSPACE file ourselves, but
+    // entrusting the entire contents of the repo root to this target directory.
+    FileValue workspaceFileValue = getWorkspaceFile(targetDirRootedPath, env);
     if (workspaceFileValue == null) {
       return null;
     }
@@ -172,10 +187,37 @@
       throw new RepositoryFunctionException(
           new IOException("No WORKSPACE file found in " + source), Transience.PERSISTENT);
     }
-
     return RepositoryDirectoryValue.builder().setPath(source);
   }
 
+  @Nullable
+  private static FileValue getWorkspaceFile(RootedPath directory, Environment env)
+      throws RepositoryFunctionException, InterruptedException {
+    RootedPath workspaceRootedFile;
+    try {
+      workspaceRootedFile = WorkspaceFileHelper.getWorkspaceRootedFile(directory, env);
+      if (workspaceRootedFile == null) {
+        return null;
+      }
+    } catch (IOException e) {
+      throw new RepositoryFunctionException(
+          new IOException(
+              "Could not determine workspace file (\"WORKSPACE.bazel\" or \"WORKSPACE\"): "
+                  + e.getMessage()),
+          Transience.PERSISTENT);
+    }
+    SkyKey workspaceFileKey = FileValue.key(workspaceRootedFile);
+    FileValue value;
+    try {
+      value = (FileValue) env.getValueOrThrow(workspaceFileKey, IOException.class);
+    } catch (IOException e) {
+      throw new RepositoryFunctionException(
+          new IOException("Could not access " + workspaceRootedFile + ": " + e.getMessage()),
+          Transience.PERSISTENT);
+    }
+    return value;
+  }
+
   private void setupRepositoryRoot(Path repoRoot) throws RepositoryFunctionException {
     try {
       repoRoot.deleteTree();
@@ -255,12 +297,6 @@
           return null;
         }
         if (markerHash != null) {
-          // Now that we know that it exists and that we should not fetch unconditionally, we can
-          // declare a Skyframe dependency on the repository root.
-          RepositoryFunction.getRepositoryDirectory(repoRoot, env);
-          if (env.valuesMissing()) {
-            return null;
-          }
           return RepositoryDirectoryValue.builder()
               .setPath(repoRoot)
               .setDigest(markerHash)
@@ -294,13 +330,6 @@
           Transience.TRANSIENT);
     }
 
-    // Declare a Skyframe dependency so that this is re-evaluated when something happens to the
-    // directory.
-    RepositoryFunction.getRepositoryDirectory(repoRoot, env);
-    if (env.valuesMissing()) {
-      return null;
-    }
-
     // Try to build with whatever is on the file system and emit a warning.
     env.getListener()
         .handle(Event.warn(rule.getLocation(),
@@ -400,11 +429,13 @@
       PathFragment sourcePath, Environment env, Path repoRoot, String pathAttr)
       throws RepositoryFunctionException, InterruptedException {
     setupRepositoryRoot(repoRoot);
-    RepositoryDirectoryValue.Builder directoryValue = symlink(repoRoot, sourcePath, pathAttr, env);
+    RepositoryDirectoryValue.Builder directoryValue =
+        symlinkRepoRoot(
+            repoRoot, directories.getWorkspace().getRelative(sourcePath), pathAttr, env);
     if (directoryValue == null) {
       return null;
     }
-    byte[] digest = new byte[] {};
+    byte[] digest = new Fingerprint().addPath(sourcePath).digestAndReset();
     return directoryValue.setDigest(digest).build();
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java
index a5d6c52..4b4f7d2 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java
@@ -34,8 +34,6 @@
 import com.google.devtools.build.lib.packages.Rule;
 import com.google.devtools.build.lib.packages.Type;
 import com.google.devtools.build.lib.repository.ExternalPackageException;
-import com.google.devtools.build.lib.repository.ExternalPackageHelper;
-import com.google.devtools.build.lib.repository.ExternalRuleNotFoundException;
 import com.google.devtools.build.lib.skyframe.ActionEnvironmentFunction;
 import com.google.devtools.build.lib.skyframe.AlreadyReportedException;
 import com.google.devtools.build.lib.skyframe.PackageLookupFunction;
@@ -524,28 +522,6 @@
     }
   }
 
-  /**
-   * Adds the repository's directory to the graph and, if it's a symlink, resolves it to an actual
-   * directory.
-   */
-  @Nullable
-  protected static FileValue getRepositoryDirectory(Path repositoryDirectory, Environment env)
-      throws RepositoryFunctionException, InterruptedException {
-    SkyKey outputDirectoryKey =
-        FileValue.key(
-            RootedPath.toRootedPath(
-                Root.fromPath(repositoryDirectory), PathFragment.EMPTY_FRAGMENT));
-    FileValue value;
-    try {
-      value = (FileValue) env.getValueOrThrow(outputDirectoryKey, IOException.class);
-    } catch (IOException e) {
-      throw new RepositoryFunctionException(
-          new IOException("Could not access " + repositoryDirectory + ": " + e.getMessage()),
-          Transience.PERSISTENT);
-    }
-    return value;
-  }
-
   protected static Path getExternalRepositoryDirectory(BlazeDirectories directories) {
     return directories.getOutputBase().getRelative(LabelConstants.EXTERNAL_REPOSITORY_LOCATION);
   }
@@ -562,11 +538,7 @@
    * encourage nor optimize for since it is not common. So the set of external files is small.
    */
   public static void addExternalFilesDependencies(
-      RootedPath rootedPath,
-      boolean isDirectory,
-      BlazeDirectories directories,
-      Environment env,
-      ExternalPackageHelper externalPackageHelper)
+      RootedPath rootedPath, BlazeDirectories directories, Environment env)
       throws InterruptedException {
     Path externalRepoDir = getExternalRepositoryDirectory(directories);
     PathFragment repositoryPath = rootedPath.asPath().relativeTo(externalRepoDir);
@@ -576,53 +548,8 @@
       return;
     }
     String repositoryName = repositoryPath.getSegment(0);
-
-    try {
-      // Add a dependency to the repository rule. RepositoryDirectoryValue does add this
-      // dependency already but we want to catch RepositoryNotFoundException, so invoke
-      // #getRuleByName
-      // first.
-      Rule rule = externalPackageHelper.getRuleByName(repositoryName, env);
-      if (rule == null) {
-        // Still an override might change the content of the repository.
-        RepositoryDelegatorFunction.REPOSITORY_OVERRIDES.get(env);
-        return;
-      }
-
-      if (isDirectory || repositoryPath.isMultiSegment()) {
-        if (!isDirectory
-            && rule.getRuleClass().equals(LocalRepositoryRule.NAME)
-            && WorkspaceFileHelper.endsWithWorkspaceFileName(repositoryPath)) {
-          // Ignore this, there is a dependency from LocalRepositoryFunction->WORKSPACE file already
-          return;
-        }
-
-        // For all files under the repository directory, depend on the actual RepositoryDirectory
-        // function so we get invalidation when the repository is fetched.
-        // For the repository directory itself, we cannot depends on the RepositoryDirectoryValue
-        // (cycle).
-        env.getValue(
-            RepositoryDirectoryValue.key(
-                RepositoryName.createFromValidStrippedName(repositoryName)));
-      } else {
-        // Invalidate external/<repo> if the repository overrides change.
-        RepositoryDelegatorFunction.REPOSITORY_OVERRIDES.get(env);
-      }
-    } catch (ExternalRuleNotFoundException ex) {
-      // The repository we are looking for does not exist so we should depend on the whole
-      // WORKSPACE file. In that case, the call to RepositoryFunction#getRuleByName(String,
-      // Environment)
-      // already requested all repository functions from the WORKSPACE file from Skyframe as part
-      // of the resolution.
-      //
-      // Alternatively, the repository might still be provided by an override. Therefore, in
-      // any case, register the dependency on the repository overrides.
-      RepositoryDelegatorFunction.REPOSITORY_OVERRIDES.get(env);
-    } catch (ExternalPackageException ex) {
-      // This should never happen.
-      throw new IllegalStateException(
-          "Repository " + repositoryName + " cannot be resolved for path " + rootedPath, ex);
-    }
+    env.getValue(
+        RepositoryDirectoryValue.key(RepositoryName.createFromValidStrippedName(repositoryName)));
   }
 
   /**
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 08aa0e1..8134e2b 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
@@ -51,7 +51,7 @@
     RootedPath dirRootedPath = (RootedPath) skyKey.argument();
 
     try {
-      FileType fileType = externalFilesHelper.maybeHandleExternalFile(dirRootedPath, true, env);
+      FileType fileType = externalFilesHelper.maybeHandleExternalFile(dirRootedPath, env);
       if (env.valuesMissing()) {
         return null;
       }
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 da07b4d..b8d9029 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
@@ -22,7 +22,6 @@
 import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
 import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
-import com.google.devtools.build.lib.repository.ExternalPackageHelper;
 import com.google.devtools.build.lib.rules.repository.RepositoryFunction;
 import com.google.devtools.build.lib.util.Pair;
 import com.google.devtools.build.lib.util.TestType;
@@ -42,7 +41,6 @@
   private final BlazeDirectories directories;
   private final int maxNumExternalFilesToLog;
   private final AtomicInteger numExternalFilesLogged = new AtomicInteger(0);
-  private final ExternalPackageHelper externalPackageHelper;
 
   // These variables are set to true from multiple threads, but only read in the main thread.
   // So volatility or an AtomicBoolean is not needed.
@@ -56,36 +54,27 @@
       ExternalFileAction externalFileAction,
       BlazeDirectories directories,
       int maxNumExternalFilesToLog,
-      ManagedDirectoriesKnowledge managedDirectoriesKnowledge,
-      ExternalPackageHelper externalPackageHelper) {
+      ManagedDirectoriesKnowledge managedDirectoriesKnowledge) {
     this.pkgLocator = pkgLocator;
     this.externalFileAction = externalFileAction;
     this.directories = directories;
     this.maxNumExternalFilesToLog = maxNumExternalFilesToLog;
     this.managedDirectoriesKnowledge = managedDirectoriesKnowledge;
-    this.externalPackageHelper = externalPackageHelper;
   }
 
   public static ExternalFilesHelper create(
       AtomicReference<PathPackageLocator> pkgLocator,
       ExternalFileAction externalFileAction,
       BlazeDirectories directories,
-      ManagedDirectoriesKnowledge managedDirectoriesKnowledge,
-      ExternalPackageHelper externalPackageHelper) {
+      ManagedDirectoriesKnowledge managedDirectoriesKnowledge) {
     return TestType.isInTest()
-        ? createForTesting(
-            pkgLocator,
-            externalFileAction,
-            directories,
-            managedDirectoriesKnowledge,
-            externalPackageHelper)
+        ? createForTesting(pkgLocator, externalFileAction, directories, managedDirectoriesKnowledge)
         : new ExternalFilesHelper(
             pkgLocator,
             externalFileAction,
             directories,
             /*maxNumExternalFilesToLog=*/ 100,
-            managedDirectoriesKnowledge,
-            externalPackageHelper);
+            managedDirectoriesKnowledge);
   }
 
   public static ExternalFilesHelper createForTesting(
@@ -96,36 +85,21 @@
         pkgLocator,
         externalFileAction,
         directories,
-        BazelSkyframeExecutorConstants.EXTERNAL_PACKAGE_HELPER);
-  }
-
-  public static ExternalFilesHelper createForTesting(
-      AtomicReference<PathPackageLocator> pkgLocator,
-      ExternalFileAction externalFileAction,
-      BlazeDirectories directories,
-      ExternalPackageHelper externalPackageHelper) {
-    return createForTesting(
-        pkgLocator,
-        externalFileAction,
-        directories,
-        ManagedDirectoriesKnowledge.NO_MANAGED_DIRECTORIES,
-        externalPackageHelper);
+        ManagedDirectoriesKnowledge.NO_MANAGED_DIRECTORIES);
   }
 
   private static ExternalFilesHelper createForTesting(
       AtomicReference<PathPackageLocator> pkgLocator,
       ExternalFileAction externalFileAction,
       BlazeDirectories directories,
-      ManagedDirectoriesKnowledge managedDirectoriesKnowledge,
-      ExternalPackageHelper externalPackageHelper) {
+      ManagedDirectoriesKnowledge managedDirectoriesKnowledge) {
     return new ExternalFilesHelper(
         pkgLocator,
         externalFileAction,
         directories,
         // These log lines are mostly spam during unit and integration tests.
         /*maxNumExternalFilesToLog=*/ 0,
-        managedDirectoriesKnowledge,
-        externalPackageHelper);
+        managedDirectoriesKnowledge);
   }
 
 
@@ -242,8 +216,7 @@
         externalFileAction,
         directories,
         maxNumExternalFilesToLog,
-        managedDirectoriesKnowledge,
-        externalPackageHelper);
+        managedDirectoriesKnowledge);
   }
 
   public FileType getAndNoteFileType(RootedPath rootedPath) {
@@ -307,8 +280,7 @@
    * a {@link NonexistentImmutableExternalFileException} instead.
    */
   @ThreadSafe
-  FileType maybeHandleExternalFile(
-      RootedPath rootedPath, boolean isDirectory, SkyFunction.Environment env)
+  FileType maybeHandleExternalFile(RootedPath rootedPath, SkyFunction.Environment env)
       throws NonexistentImmutableExternalFileException, IOException, InterruptedException {
     Pair<FileType, RepositoryName> pair = getFileTypeAndRepository(rootedPath);
 
@@ -338,8 +310,7 @@
         Preconditions.checkState(
             externalFileAction == ExternalFileAction.DEPEND_ON_EXTERNAL_PKG_FOR_EXTERNAL_REPO_PATHS,
             externalFileAction);
-        RepositoryFunction.addExternalFilesDependencies(
-            rootedPath, isDirectory, directories, env, externalPackageHelper);
+        RepositoryFunction.addExternalFilesDependencies(rootedPath, directories, env);
         break;
     }
     return fileType;
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 8ece6ee..8205db5 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
@@ -51,7 +51,7 @@
     RootedPath rootedPath = (RootedPath) skyKey.argument();
 
     try {
-      FileType fileType = externalFilesHelper.maybeHandleExternalFile(rootedPath, false, env);
+      FileType fileType = externalFilesHelper.maybeHandleExternalFile(rootedPath, env);
       if (env.valuesMissing()) {
         return null;
       }
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 6a2f6f5..1274a74 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
@@ -468,8 +468,7 @@
             directories,
             managedDirectoriesKnowledge != null
                 ? managedDirectoriesKnowledge
-                : ManagedDirectoriesKnowledge.NO_MANAGED_DIRECTORIES,
-            externalPackageHelper);
+                : ManagedDirectoriesKnowledge.NO_MANAGED_DIRECTORIES);
     this.crossRepositoryLabelViolationStrategy = crossRepositoryLabelViolationStrategy;
     this.buildFilesByPriority = buildFilesByPriority;
     this.externalPackageHelper = externalPackageHelper;
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/packages/AbstractPackageLoader.java b/src/main/java/com/google/devtools/build/lib/skyframe/packages/AbstractPackageLoader.java
index f2830e4..f4eb954 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/packages/AbstractPackageLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/packages/AbstractPackageLoader.java
@@ -153,7 +153,6 @@
     protected final BlazeDirectories directories;
     protected final PathPackageLocator pkgLocator;
     final AtomicReference<PathPackageLocator> pkgLocatorRef;
-    private final ExternalPackageHelper externalPackageHelper;
     private ExternalFileAction externalFileAction;
     protected ExternalFilesHelper externalFilesHelper;
     protected ConfiguredRuleClassProvider ruleClassProvider = getDefaultRuleClassProvider();
@@ -169,7 +168,6 @@
         Path installBase,
         Path outputBase,
         ImmutableList<BuildFileName> buildFilesByPriority,
-        ExternalPackageHelper externalPackageHelper,
         ExternalFileAction externalFileAction) {
       this.workspaceDir = workspaceDir.asPath();
       Path devNull = workspaceDir.getRelative("/dev/null");
@@ -185,7 +183,6 @@
               directories.getOutputBase(), ImmutableList.of(workspaceDir), buildFilesByPriority);
       this.pkgLocatorRef = new AtomicReference<>(pkgLocator);
       this.externalFileAction = externalFileAction;
-      this.externalPackageHelper = externalPackageHelper;
     }
 
     public Builder setRuleClassProvider(ConfiguredRuleClassProvider ruleClassProvider) {
@@ -255,8 +252,7 @@
               pkgLocatorRef,
               externalFileAction,
               directories,
-              ManagedDirectoriesKnowledge.NO_MANAGED_DIRECTORIES,
-              externalPackageHelper);
+              ManagedDirectoriesKnowledge.NO_MANAGED_DIRECTORIES);
       return buildImpl();
     }
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/packages/BazelPackageLoader.java b/src/main/java/com/google/devtools/build/lib/skyframe/packages/BazelPackageLoader.java
index c9b8eb1..cbd5c8a 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/packages/BazelPackageLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/packages/BazelPackageLoader.java
@@ -87,7 +87,6 @@
           installBase,
           outputBase,
           BUILD_FILES_BY_PRIORITY,
-          EXTERNAL_PACKAGE_HELPER,
           ExternalFileAction.DEPEND_ON_EXTERNAL_PKG_FOR_EXTERNAL_REPO_PATHS);
       this.isFetch = isFetch;
     }