Allow BazelPackageLoader to load external repositories.
Also, disallow BazelPackageLoader from fetching missing external repos.

Integration tests for BazelPackageLoader wrt external repos will be left for a follow-up CL.

RELNOTES: None.
PiperOrigin-RevId: 188967694
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 3b83fa8..681e4aa 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
@@ -111,7 +111,7 @@
                     new WorkspaceFileFunction(
                         TestRuleClassProvider.getRuleClassProvider(),
                         TestConstants.PACKAGE_FACTORY_BUILDER_FACTORY_FOR_TESTING
-                            .builder()
+                            .builder(directories)
                             .build(
                                 TestRuleClassProvider.getRuleClassProvider(), root.getFileSystem()),
                         directories))
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 6a8543f..2c0c772 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
@@ -166,7 +166,7 @@
                     new WorkspaceFileFunction(
                         TestRuleClassProvider.getRuleClassProvider(),
                         TestConstants.PACKAGE_FACTORY_BUILDER_FACTORY_FOR_TESTING
-                            .builder()
+                            .builder(directories)
                             .build(TestRuleClassProvider.getRuleClassProvider(), fs),
                         directories))
                 .put(SkyFunctions.EXTERNAL_PACKAGE, new ExternalPackageFunction())
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 0edfea3..a0c16e4 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
@@ -132,10 +132,13 @@
             BazelSkyframeExecutorConstants.BUILD_FILES_BY_PRIORITY));
     skyFunctions.put(SkyFunctions.WORKSPACE_AST,
         new WorkspaceASTFunction(TestRuleClassProvider.getRuleClassProvider()));
-    skyFunctions.put(SkyFunctions.WORKSPACE_FILE,
-        new WorkspaceFileFunction(TestRuleClassProvider.getRuleClassProvider(),
-            TestConstants.PACKAGE_FACTORY_BUILDER_FACTORY_FOR_TESTING.builder().build(
-                TestRuleClassProvider.getRuleClassProvider(), fs),
+    skyFunctions.put(
+        SkyFunctions.WORKSPACE_FILE,
+        new WorkspaceFileFunction(
+            TestRuleClassProvider.getRuleClassProvider(),
+            TestConstants.PACKAGE_FACTORY_BUILDER_FACTORY_FOR_TESTING
+                .builder(directories)
+                .build(TestRuleClassProvider.getRuleClassProvider(), fs),
             directories));
     skyFunctions.put(SkyFunctions.EXTERNAL_PACKAGE, new ExternalPackageFunction());
 
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/RecursivePkgFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/RecursivePkgFunctionTest.java
index ac45a7e..679d276 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/RecursivePkgFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/RecursivePkgFunctionTest.java
@@ -51,6 +51,7 @@
 
   @Before
   public final void createSkyframeExecutor() throws Exception {
+    initializeSkyframeExecutor(/*doPackageLoadingChecks=*/ false);
     skyframeExecutor = getSkyframeExecutor();
   }
 
@@ -63,7 +64,7 @@
 
   private RecursivePkgValue buildRecursivePkgValue(Path root, PathFragment rootRelativePath)
       throws Exception {
-    return buildRecursivePkgValue(root, rootRelativePath, ImmutableSet.<PathFragment>of());
+    return buildRecursivePkgValue(root, rootRelativePath, ImmutableSet.of());
   }
 
   private RecursivePkgValue buildRecursivePkgValue(
@@ -139,8 +140,7 @@
     WalkableGraph graph = Preconditions.checkNotNull(evaluationResult.getWalkableGraph());
     assertThat(
             exists(
-                buildRecursivePkgKey(
-                    rootDirectory, excludedPathFragment, ImmutableSet.<PathFragment>of()),
+                buildRecursivePkgKey(rootDirectory, excludedPathFragment, ImmutableSet.of()),
                 graph))
         .isFalse();
 
@@ -148,8 +148,7 @@
     // because that key was evaluated.
     assertThat(
             exists(
-                buildRecursivePkgKey(
-                    rootDirectory, PathFragment.create("a/c"), ImmutableSet.<PathFragment>of()),
+                buildRecursivePkgKey(rootDirectory, PathFragment.create("a/c"), ImmutableSet.of()),
                 graph))
         .isTrue();
   }
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 3348527..8554b25 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
@@ -220,7 +220,7 @@
                     new WorkspaceFileFunction(
                         TestRuleClassProvider.getRuleClassProvider(),
                         TestConstants.PACKAGE_FACTORY_BUILDER_FACTORY_FOR_TESTING
-                            .builder()
+                            .builder(directories)
                             .build(
                                 TestRuleClassProvider.getRuleClassProvider(),
                                 scratch.getFileSystem()),
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/packages/AbstractPackageLoaderTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/packages/AbstractPackageLoaderTest.java
index 1ac5266..31c25f5 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/packages/AbstractPackageLoaderTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/packages/AbstractPackageLoaderTest.java
@@ -37,28 +37,26 @@
 
 /** Abstract base class of a unit test for a {@link AbstractPackageLoader} implementation. */
 public abstract class AbstractPackageLoaderTest {
-  private Path pkgRoot;
+  private Path workspaceDir;
   protected StoredEventHandler handler;
-  protected PackageLoader pkgLoader;
+  protected FileSystem fs;
+  private Reporter reporter;
 
   @Before
   public final void init() throws Exception {
-    FileSystem fs = new InMemoryFileSystem();
-    pkgRoot = fs.getPath("/").getRelative("pkgRoot");
-    FileSystemUtils.createDirectoryAndParents(pkgRoot);
-    Reporter reporter = new Reporter(new EventBus());
+    fs = new InMemoryFileSystem();
+    workspaceDir = fs.getPath("/workspace/");
+    workspaceDir.createDirectoryAndParents();
+    reporter = new Reporter(new EventBus());
     handler = new StoredEventHandler();
     reporter.addHandler(handler);
-    pkgLoader = makeFreshBuilder(pkgRoot)
-        .useDefaultSkylarkSemantics()
-        .setReporter(reporter)
-        .build();
   }
 
-  protected abstract AbstractPackageLoader.Builder makeFreshBuilder(Path pkgRoot);
+  protected abstract AbstractPackageLoader.Builder newPackageLoaderBuilder(Path workspaceDir);
 
   @Test
   public void simpleNoPackage() throws Exception {
+    PackageLoader pkgLoader = newPackageLoader();
     PackageIdentifier pkgId = PackageIdentifier.createInMainRepo(PathFragment.create("nope"));
     try {
       pkgLoader.loadPackage(pkgId);
@@ -73,6 +71,7 @@
 
   @Test
   public void simpleBadPackage() throws Exception {
+    PackageLoader pkgLoader = newPackageLoader();
     file("bad/BUILD", "invalidBUILDsyntax");
     PackageIdentifier pkgId = PackageIdentifier.createInMainRepo(PathFragment.create("bad"));
     Package badPkg = pkgLoader.loadPackage(pkgId);
@@ -83,18 +82,20 @@
 
   @Test
   public void simpleGoodPackage() throws Exception {
+    PackageLoader pkgLoader = newPackageLoader();
     file("good/BUILD", "sh_library(name = 'good')");
     PackageIdentifier pkgId = PackageIdentifier.createInMainRepo(PathFragment.create("good"));
     Package goodPkg = pkgLoader.loadPackage(pkgId);
     assertThat(goodPkg.containsErrors()).isFalse();
-    assertThat(
-        goodPkg.getTarget("good").getAssociatedRule().getRuleClass()).isEqualTo("sh_library");
+    assertThat(goodPkg.getTarget("good").getAssociatedRule().getRuleClass())
+        .isEqualTo("sh_library");
     assertNoEvents(goodPkg.getEvents());
     assertNoEvents(handler.getEvents());
   }
 
   @Test
   public void simpleMultipleGoodPackage() throws Exception {
+    PackageLoader pkgLoader = newPackageLoader();
     file("good1/BUILD", "sh_library(name = 'good1')");
     file("good2/BUILD", "sh_library(name = 'good2')");
     PackageIdentifier pkgId1 = PackageIdentifier.createInMainRepo(PathFragment.create("good1"));
@@ -114,6 +115,7 @@
 
   @Test
   public void loadPackagesToleratesDuplicates() throws Exception {
+    PackageLoader pkgLoader = newPackageLoader();
     file("good1/BUILD", "sh_library(name = 'good1')");
     PackageIdentifier pkgId = PackageIdentifier.createInMainRepo(PathFragment.create("good1"));
     ImmutableMap<PackageIdentifier, PackageLoader.PackageOrException> pkgs =
@@ -127,29 +129,33 @@
 
   @Test
   public void simpleGoodPackage_Skylark() throws Exception {
-    file("good/good.bzl",
-        "def f(x):",
-        "  native.sh_library(name = x)");
-    file("good/BUILD",
-        "load('//good:good.bzl', 'f')",
-        "f('good')");
+    PackageLoader pkgLoader = newPackageLoader();
+    file("good/good.bzl", "def f(x):", "  native.sh_library(name = x)");
+    file("good/BUILD", "load('//good:good.bzl', 'f')", "f('good')");
     PackageIdentifier pkgId = PackageIdentifier.createInMainRepo(PathFragment.create("good"));
     Package goodPkg = pkgLoader.loadPackage(pkgId);
     assertThat(goodPkg.containsErrors()).isFalse();
-    assertThat(
-        goodPkg.getTarget("good").getAssociatedRule().getRuleClass()).isEqualTo("sh_library");
+    assertThat(goodPkg.getTarget("good").getAssociatedRule().getRuleClass())
+        .isEqualTo("sh_library");
     assertNoEvents(goodPkg.getEvents());
     assertNoEvents(handler.getEvents());
   }
 
   protected Path path(String rootRelativePath) {
-    return pkgRoot.getRelative(PathFragment.create(rootRelativePath));
+    return workspaceDir.getRelative(PathFragment.create(rootRelativePath));
   }
 
   protected Path file(String fileName, String... contents) throws Exception {
     Path path = path(fileName);
-    FileSystemUtils.createDirectoryAndParents(path.getParentDirectory());
+    path.getParentDirectory().createDirectoryAndParents();
     FileSystemUtils.writeContentAsLatin1(path, Joiner.on("\n").join(contents));
     return path;
   }
+
+  protected PackageLoader newPackageLoader() {
+    return newPackageLoaderBuilder(workspaceDir)
+        .useDefaultSkylarkSemantics()
+        .setReporter(reporter)
+        .build();
+  }
 }
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/packages/BUILD b/src/test/java/com/google/devtools/build/lib/skyframe/packages/BUILD
index 105843b..137ae9d 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/packages/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/packages/BUILD
@@ -17,11 +17,14 @@
         "BazelPackageLoaderTest.java",
     ],
     deps = [
+        "//src/main/java/com/google/devtools/build/lib:build-base",
         "//src/main/java/com/google/devtools/build/lib:events",
         "//src/main/java/com/google/devtools/build/lib:packages",
         "//src/main/java/com/google/devtools/build/lib/skyframe/packages",
         "//src/main/java/com/google/devtools/build/lib/vfs",
         "//src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs",
+        "//src/test/java/com/google/devtools/build/lib:analysis_testutil",
+        "//src/test/java/com/google/devtools/build/lib:packages_testutil",
         "//src/test/java/com/google/devtools/build/lib:testutil",
         "//third_party:guava",
         "//third_party:jsr305",
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/packages/BazelPackageLoaderTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/packages/BazelPackageLoaderTest.java
index fb53082..a676586 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/packages/BazelPackageLoaderTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/packages/BazelPackageLoaderTest.java
@@ -16,11 +16,15 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.devtools.build.lib.testutil.MoreAsserts.assertNoEvents;
 
+import com.google.devtools.build.lib.analysis.ServerDirectories;
 import com.google.devtools.build.lib.cmdline.PackageIdentifier;
 import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.packages.Package;
+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 java.io.IOException;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -33,13 +37,47 @@
  */
 @RunWith(JUnit4.class)
 public final class BazelPackageLoaderTest extends AbstractPackageLoaderTest {
+
+  private Path installBase;
+  private Path outputBase;
+
+  @Before
+  public void setUp() throws Exception {
+    installBase = fs.getPath("/installBase/");
+    installBase.createDirectoryAndParents();
+    outputBase = fs.getPath("/outputBase/");
+    outputBase.createDirectoryAndParents();
+    Path embeddedBinaries = ServerDirectories.getEmbeddedBinariesRoot(installBase);
+    embeddedBinaries.createDirectoryAndParents();
+
+    mockEmbeddedTools(embeddedBinaries);
+  }
+
+  private void mockEmbeddedTools(Path embeddedBinaries) throws IOException {
+    Path tools = embeddedBinaries.getRelative("embedded_tools");
+    tools.getRelative("tools/cpp").createDirectoryAndParents();
+    tools.getRelative("tools/osx").createDirectoryAndParents();
+    FileSystemUtils.writeIsoLatin1(tools.getRelative("WORKSPACE"), "");
+    FileSystemUtils.writeIsoLatin1(tools.getRelative("tools/cpp/BUILD"), "");
+    FileSystemUtils.writeIsoLatin1(
+        tools.getRelative("tools/cpp/cc_configure.bzl"),
+        "def cc_configure(*args, **kwargs):",
+        "    pass");
+    FileSystemUtils.writeIsoLatin1(tools.getRelative("tools/osx/BUILD"), "");
+    FileSystemUtils.writeIsoLatin1(
+        tools.getRelative("tools/osx/xcode_configure.bzl"),
+        "def xcode_configure(*args, **kwargs):",
+        "    pass");
+  }
+
   @Override
-  protected BazelPackageLoader.Builder makeFreshBuilder(Path pkgRoot) {
-    return BazelPackageLoader.builder(pkgRoot);
+  protected AbstractPackageLoader.Builder newPackageLoaderBuilder(Path workspaceDir) {
+    return BazelPackageLoader.builder(workspaceDir, installBase, outputBase);
   }
 
   @Test
   public void simpleLocalRepositoryPackage() throws Exception {
+    PackageLoader pkgLoader = newPackageLoader();
     file("WORKSPACE", "local_repository(name = 'r', path='r')");
     file("r/WORKSPACE", "workspace(name = 'r')");
     file("r/good/BUILD", "sh_library(name = 'good')");
@@ -52,4 +90,22 @@
     assertNoEvents(goodPkg.getEvents());
     assertNoEvents(handler.getEvents());
   }
+
+  @Test
+  public void newLocalRepository() throws Exception {
+    PackageLoader pkgLoader = newPackageLoader();
+    file(
+        "WORKSPACE",
+        "new_local_repository(name = 'r', path = '/r', "
+            + "build_file_content = 'sh_library(name = \"good\")')");
+    fs.getPath("/r").createDirectoryAndParents();
+    PackageIdentifier pkgId =
+        PackageIdentifier.create(RepositoryName.create("@r"), PathFragment.create(""));
+    Package goodPkg = pkgLoader.loadPackage(pkgId);
+    assertThat(goodPkg.containsErrors()).isFalse();
+    assertThat(goodPkg.getTarget("good").getAssociatedRule().getRuleClass())
+        .isEqualTo("sh_library");
+    assertNoEvents(goodPkg.getEvents());
+    assertNoEvents(handler.getEvents());
+  }
 }