Add an intermediate SkyFunction for resolving the external package

The WORKSPACE file parsing needs to be separated into several parts
to enable load of labels in the WORKSPACE file.

This change adds an intermediate SkyFunction, ExternalPackageFunction,
that requires all the WORKSPACE file part to be parsed to resolve
//external: labels.

Issue #824 Step 1.

--
MOS_MIGRATED_REVID=113984026
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/ArtifactFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/ArtifactFunctionTest.java
index 4870806..10d05ff 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/ArtifactFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/ArtifactFunctionTest.java
@@ -114,15 +114,20 @@
                 .put(SkyFunctions.FILE, new FileFunction(pkgLocator))
                 .put(SkyFunctions.ARTIFACT, new ArtifactFunction(allowedMissingInputsPredicate))
                 .put(SkyFunctions.ACTION_EXECUTION, new SimpleActionExecutionFunction())
-                .put(SkyFunctions.PACKAGE,
+                .put(
+                    SkyFunctions.PACKAGE,
                     new PackageFunction(null, null, null, null, null, null, null))
                 .put(SkyFunctions.PACKAGE_LOOKUP, new PackageLookupFunction(null))
-                .put(SkyFunctions.WORKSPACE_AST,
+                .put(
+                    SkyFunctions.WORKSPACE_AST,
                     new WorkspaceASTFunction(TestRuleClassProvider.getRuleClassProvider()))
-                .put(SkyFunctions.WORKSPACE_FILE,
-                    new WorkspaceFileFunction(TestRuleClassProvider.getRuleClassProvider(),
+                .put(
+                    SkyFunctions.WORKSPACE_FILE,
+                    new WorkspaceFileFunction(
+                        TestRuleClassProvider.getRuleClassProvider(),
                         new PackageFactory(TestRuleClassProvider.getRuleClassProvider()),
                         new BlazeDirectories(root, root, root)))
+                .put(SkyFunctions.EXTERNAL_PACKAGE, new ExternalPackageFunction())
                 .build(),
             differencer);
     driver = new SequentialBuildDriver(evaluator);
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 7780f7f..ed239f3 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
@@ -130,22 +130,30 @@
         new InMemoryMemoizingEvaluator(
             ImmutableMap.<SkyFunctionName, SkyFunction>builder()
                 .put(SkyFunctions.FILE_STATE, new FileStateFunction(tsgm, externalFilesHelper))
-                .put(SkyFunctions.FILE_SYMLINK_CYCLE_UNIQUENESS,
+                .put(
+                    SkyFunctions.FILE_SYMLINK_CYCLE_UNIQUENESS,
                     new FileSymlinkCycleUniquenessFunction())
-                .put(SkyFunctions.FILE_SYMLINK_INFINITE_EXPANSION_UNIQUENESS,
+                .put(
+                    SkyFunctions.FILE_SYMLINK_INFINITE_EXPANSION_UNIQUENESS,
                     new FileSymlinkInfiniteExpansionUniquenessFunction())
                 .put(SkyFunctions.FILE, new FileFunction(pkgLocatorRef))
-                .put(SkyFunctions.PACKAGE,
+                .put(
+                    SkyFunctions.PACKAGE,
                     new PackageFunction(null, null, null, null, null, null, null))
-                .put(SkyFunctions.PACKAGE_LOOKUP,
-                    new PackageLookupFunction(new AtomicReference<>(
-                        ImmutableSet.<PackageIdentifier>of())))
-                .put(SkyFunctions.WORKSPACE_AST,
+                .put(
+                    SkyFunctions.PACKAGE_LOOKUP,
+                    new PackageLookupFunction(
+                        new AtomicReference<>(ImmutableSet.<PackageIdentifier>of())))
+                .put(
+                    SkyFunctions.WORKSPACE_AST,
                     new WorkspaceASTFunction(TestRuleClassProvider.getRuleClassProvider()))
-                .put(SkyFunctions.WORKSPACE_FILE,
-                    new WorkspaceFileFunction(TestRuleClassProvider.getRuleClassProvider(),
+                .put(
+                    SkyFunctions.WORKSPACE_FILE,
+                    new WorkspaceFileFunction(
+                        TestRuleClassProvider.getRuleClassProvider(),
                         new PackageFactory(TestRuleClassProvider.getRuleClassProvider()),
                         new BlazeDirectories(pkgRoot, outputBase, pkgRoot)))
+                .put(SkyFunctions.EXTERNAL_PACKAGE, new ExternalPackageFunction())
                 .build(),
             differencer);
     PrecomputedValue.BUILD_ID.set(differencer, UUID.randomUUID());
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 3b0380e..95cb020 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
@@ -119,6 +119,7 @@
         new WorkspaceFileFunction(TestRuleClassProvider.getRuleClassProvider(),
             new PackageFactory(TestRuleClassProvider.getRuleClassProvider()),
             new BlazeDirectories(pkgRoot, pkgRoot, pkgRoot)));
+    skyFunctions.put(SkyFunctions.EXTERNAL_PACKAGE, new ExternalPackageFunction());
 
     differencer = new RecordingDifferencer();
     evaluator = new InMemoryMemoizingEvaluator(skyFunctions.build(), differencer);
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 4195a3d..39b038f 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
@@ -97,6 +97,7 @@
             new PackageFactory(
                 ruleClassProvider, new BazelRulesModule().getPackageEnvironmentExtension()),
             directories));
+    skyFunctions.put(SkyFunctions.EXTERNAL_PACKAGE, new ExternalPackageFunction());
     differencer = new RecordingDifferencer();
     evaluator = new InMemoryMemoizingEvaluator(skyFunctions, differencer);
     driver = new SequentialBuildDriver(evaluator);
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 62a375f..5e2ebfd 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
@@ -114,6 +114,7 @@
         new WorkspaceFileFunction(TestRuleClassProvider.getRuleClassProvider(),
             new PackageFactory(TestRuleClassProvider.getRuleClassProvider()),
             new BlazeDirectories(rootDirectory, outputBase, rootDirectory)));
+    skyFunctions.put(SkyFunctions.EXTERNAL_PACKAGE, new ExternalPackageFunction());
 
     progressReceiver = new RecordingEvaluationProgressReceiver();
     differencer = new RecordingDifferencer();
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 995ece5..2218684 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
@@ -155,19 +155,26 @@
             ImmutableMap.<SkyFunctionName, SkyFunction>builder()
                 .put(SkyFunctions.FILE_STATE, new FileStateFunction(tsgm, externalFilesHelper))
                 .put(SkyFunctions.FILE, new FileFunction(pkgLocator))
-                .put(SkyFunctions.ARTIFACT,
+                .put(
+                    SkyFunctions.ARTIFACT,
                     new ArtifactFunction(Predicates.<PathFragment>alwaysFalse()))
-                .put(SkyFunctions.ACTION_EXECUTION,
+                .put(
+                    SkyFunctions.ACTION_EXECUTION,
                     new ActionExecutionFunction(skyframeActionExecutor, tsgm))
-                .put(SkyFunctions.PACKAGE,
+                .put(
+                    SkyFunctions.PACKAGE,
                     new PackageFunction(null, null, null, null, null, null, null))
                 .put(SkyFunctions.PACKAGE_LOOKUP, new PackageLookupFunction(null))
-                .put(SkyFunctions.WORKSPACE_AST,
+                .put(
+                    SkyFunctions.WORKSPACE_AST,
                     new WorkspaceASTFunction(TestRuleClassProvider.getRuleClassProvider()))
-                .put(SkyFunctions.WORKSPACE_FILE,
-                    new WorkspaceFileFunction(TestRuleClassProvider.getRuleClassProvider(),
+                .put(
+                    SkyFunctions.WORKSPACE_FILE,
+                    new WorkspaceFileFunction(
+                        TestRuleClassProvider.getRuleClassProvider(),
                         new PackageFactory(TestRuleClassProvider.getRuleClassProvider()),
                         new BlazeDirectories(rootDirectory, outputBase, rootDirectory)))
+                .put(SkyFunctions.EXTERNAL_PACKAGE, new ExternalPackageFunction())
                 .build(),
             differencer,
             evaluationProgressReceiver);
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunctionTest.java
index 3f7c0d5..0f4ce40 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunctionTest.java
@@ -55,7 +55,8 @@
 @RunWith(JUnit4.class)
 public class WorkspaceFileFunctionTest extends BuildViewTestCase {
 
-  private WorkspaceFileFunction skyFunc;
+  private WorkspaceFileFunction workspaceSkyFunc;
+  private ExternalPackageFunction externalSkyFunc;
   private WorkspaceASTFunction astSkyFunc;
   private FakeFileValue fakeWorkspaceFileValue;
 
@@ -101,12 +102,13 @@
   @Before
   public final void setUp() throws Exception {
     ConfiguredRuleClassProvider ruleClassProvider = TestRuleClassProvider.getRuleClassProvider();
-    skyFunc = 
+    workspaceSkyFunc =
         new WorkspaceFileFunction(
             ruleClassProvider,
-            new PackageFactory(ruleClassProvider,
-                new BazelRulesModule().getPackageEnvironmentExtension()),
+            new PackageFactory(
+                ruleClassProvider, new BazelRulesModule().getPackageEnvironmentExtension()),
             directories);
+    externalSkyFunc = new ExternalPackageFunction();
     astSkyFunc = new WorkspaceASTFunction(ruleClassProvider);
     fakeWorkspaceFileValue = new FakeFileValue();
   }
@@ -140,19 +142,29 @@
     @Override
     public void describeTo(Description description) {}
   }
-  
+
   private SkyFunction.Environment getEnv() {
     SkyFunction.Environment env = Mockito.mock(SkyFunction.Environment.class);
     Mockito.when(env.getValue(Matchers.argThat(new SkyKeyMatchers(SkyFunctions.FILE))))
         .thenReturn(fakeWorkspaceFileValue);
+    Mockito.when(env.getValue(Matchers.argThat(new SkyKeyMatchers(SkyFunctions.WORKSPACE_FILE))))
+        .then(
+            new Answer<SkyValue>() {
+              @Override
+              public SkyValue answer(InvocationOnMock invocation) throws Throwable {
+                SkyKey key = (SkyKey) invocation.getArguments()[0];
+                return workspaceSkyFunc.compute(key, getEnv());
+              }
+            });
     Mockito.when(env.getValue(Matchers.argThat(new SkyKeyMatchers(SkyFunctions.WORKSPACE_AST))))
-    .then(new Answer<SkyValue>() {
-      @Override
-      public SkyValue answer(InvocationOnMock invocation) throws Throwable {
-        SkyKey key = (SkyKey) invocation.getArguments()[0];
-        return astSkyFunc.compute(key, getEnv());
-      }
-    });
+        .then(
+            new Answer<SkyValue>() {
+              @Override
+              public SkyValue answer(InvocationOnMock invocation) throws Throwable {
+                SkyKey key = (SkyKey) invocation.getArguments()[0];
+                return astSkyFunc.compute(key, getEnv());
+              }
+            });
     return env;
   }
 
@@ -160,7 +172,8 @@
   public void testInvalidRepo() throws Exception {
     RootedPath workspacePath = createWorkspaceFile("workspace(name = 'foo$')");
     PackageValue value =
-        (PackageValue) skyFunc.compute(PackageValue.workspaceKey(workspacePath), getEnv());
+        (PackageValue) externalSkyFunc
+            .compute(ExternalPackageFunction.key(workspacePath), getEnv());
     Package pkg = value.getPackage();
     assertTrue(pkg.containsErrors());
     MoreAsserts.assertContainsEvent(pkg.getEvents(), "foo$ is not a legal workspace name");
@@ -171,8 +184,8 @@
     String lines[] = {"bind(name = 'foo/bar',", "actual = '//foo:bar')"};
     RootedPath workspacePath = createWorkspaceFile(lines);
 
-    SkyKey key = PackageValue.workspaceKey(workspacePath);
-    PackageValue value = (PackageValue) skyFunc.compute(key, getEnv());
+    SkyKey key = ExternalPackageFunction.key(workspacePath);
+    PackageValue value = (PackageValue) externalSkyFunc.compute(key, getEnv());
     Package pkg = value.getPackage();
     assertEquals(Label.parseAbsolute("//foo:bar"), getLabelMapping(pkg, "foo/bar"));
     MoreAsserts.assertNoEvents(pkg.getEvents());
@@ -183,8 +196,8 @@
     String lines[] = {"bind(actual = '//foo:bar', name = 'foo/bar')"};
     RootedPath workspacePath = createWorkspaceFile(lines);
 
-    SkyKey key = PackageValue.workspaceKey(workspacePath);
-    PackageValue value = (PackageValue) skyFunc.compute(key, getEnv());
+    SkyKey key = ExternalPackageFunction.key(workspacePath);
+    PackageValue value = (PackageValue) externalSkyFunc.compute(key, getEnv());
     Package pkg = value.getPackage();
     assertEquals(Label.parseAbsolute("//foo:bar"), getLabelMapping(pkg, "foo/bar"));
     MoreAsserts.assertNoEvents(pkg.getEvents());
@@ -197,7 +210,8 @@
     RootedPath workspacePath = createWorkspaceFile(lines);
 
     PackageValue value =
-        (PackageValue) skyFunc.compute(PackageValue.workspaceKey(workspacePath), getEnv());
+        (PackageValue) externalSkyFunc
+            .compute(ExternalPackageFunction.key(workspacePath), getEnv());
     Package pkg = value.getPackage();
     assertTrue(pkg.containsErrors());
     MoreAsserts.assertContainsEvent(pkg.getEvents(), "target names may not contain ':'");
@@ -210,7 +224,8 @@
     RootedPath workspacePath = createWorkspaceFile(lines);
 
     PackageValue value =
-        (PackageValue) skyFunc.compute(PackageValue.workspaceKey(workspacePath), getEnv());
+        (PackageValue) externalSkyFunc
+            .compute(ExternalPackageFunction.key(workspacePath), getEnv());
     Package pkg = value.getPackage();
     assertTrue(pkg.containsErrors());
     MoreAsserts.assertContainsEvent(pkg.getEvents(), "target names may not contain ':'");
@@ -224,7 +239,8 @@
     fakeWorkspaceFileValue.setExists(false);
 
     PackageValue value =
-        (PackageValue) skyFunc.compute(PackageValue.workspaceKey(workspacePath), getEnv());
+        (PackageValue) externalSkyFunc
+            .compute(ExternalPackageFunction.key(workspacePath), getEnv());
     Package pkg = value.getPackage();
     assertFalse(pkg.containsErrors());
     MoreAsserts.assertNoEvents(pkg.getEvents());
@@ -236,8 +252,8 @@
         "L = ['foo', 'bar']", "bind(name = '%s/%s' % (L[0], L[1]),", "actual = '//foo:bar')"};
     RootedPath workspacePath = createWorkspaceFile(lines);
 
-    SkyKey key = PackageValue.workspaceKey(workspacePath);
-    PackageValue value = (PackageValue) skyFunc.compute(key, getEnv());
+    SkyKey key = ExternalPackageFunction.key(workspacePath);
+    PackageValue value = (PackageValue) externalSkyFunc.compute(key, getEnv());
     Package pkg = value.getPackage();
     assertEquals(Label.parseAbsolute("//foo:bar"), getLabelMapping(pkg, "foo/bar"));
     MoreAsserts.assertNoEvents(pkg.getEvents());