Add the --experimental_disable_external package command line option that (unsurprisingly) disables the //external package

This has the side effect of allowing labels in the unnamed package to start
with "external" (e.g. //:external/foo/bar)

RELNOTES: None.
PiperOrigin-RevId: 296237592
diff --git a/src/test/java/com/google/devtools/build/lib/packages/SkylarkSemanticsConsistencyTest.java b/src/test/java/com/google/devtools/build/lib/packages/SkylarkSemanticsConsistencyTest.java
index b13f2dc..743d169 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/SkylarkSemanticsConsistencyTest.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/SkylarkSemanticsConsistencyTest.java
@@ -121,6 +121,7 @@
         // <== Add new options here in alphabetic order ==>
         "--debug_depset_depth=" + rand.nextBoolean(),
         "--experimental_action_args=" + rand.nextBoolean(),
+        "--experimental_disable_external_package=" + rand.nextBoolean(),
         "--experimental_sibling_repository_layout=" + rand.nextBoolean(),
         "--experimental_allow_incremental_repository_updates=" + rand.nextBoolean(),
         "--experimental_aspect_output_propagation=" + rand.nextBoolean(),
@@ -175,6 +176,7 @@
         // <== Add new options here in alphabetic order ==>
         .debugDepsetDepth(rand.nextBoolean())
         .experimentalActionArgs(rand.nextBoolean())
+        .experimentalDisableExternalPackage(rand.nextBoolean())
         .experimentalSiblingRepositoryLayout(rand.nextBoolean())
         .experimentalAllowIncrementalRepositoryUpdates(rand.nextBoolean())
         .experimentalAspectOutputPropagation(rand.nextBoolean())
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 ea3efbf..d173a20 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
@@ -391,7 +391,7 @@
   public void testAbsoluteSymlinkToExternal() throws Exception {
     String externalPath =
         outputBase
-            .getRelative(LabelConstants.EXTERNAL_PACKAGE_NAME)
+            .getRelative(LabelConstants.EXTERNAL_REPOSITORY_LOCATION)
             .getRelative("a/b")
             .getPathString();
     symlink("a", externalPath);
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 69e78aa..02b80ad 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
@@ -35,6 +35,7 @@
 import com.google.devtools.build.lib.packages.Rule;
 import com.google.devtools.build.lib.packages.WorkspaceFileValue;
 import com.google.devtools.build.lib.packages.WorkspaceFileValue.WorkspaceFileKey;
+import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
 import com.google.devtools.build.lib.rules.repository.ManagedDirectoriesKnowledge;
 import com.google.devtools.build.lib.rules.repository.ManagedDirectoriesKnowledgeImpl;
 import com.google.devtools.build.lib.rules.repository.ManagedDirectoriesKnowledgeImpl.ManagedDirectoriesListener;
@@ -53,7 +54,6 @@
 import com.google.devtools.build.skyframe.SkyFunction;
 import com.google.devtools.build.skyframe.SkyFunctionName;
 import com.google.devtools.build.skyframe.SkyKey;
-import com.google.devtools.build.skyframe.SkyValue;
 import java.io.IOException;
 import java.util.Objects;
 import java.util.Set;
@@ -66,8 +66,6 @@
 import org.junit.runners.JUnit4;
 import org.mockito.Mockito;
 import org.mockito.hamcrest.MockitoHamcrest;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
 
 /**
  * Test for {@link WorkspaceFileFunction}.
@@ -107,6 +105,11 @@
     }
 
     @Override
+    public boolean isFile() {
+      return exists;
+    }
+
+    @Override
     public ImmutableList<RootedPath> logicalChainDuringResolution() {
       throw new UnsupportedOperationException();
     }
@@ -183,46 +186,50 @@
   }
 
   private SkyFunction.Environment getEnv() throws InterruptedException {
+    PathPackageLocator locator = Mockito.mock(PathPackageLocator.class);
+    Mockito.when(locator.getPathEntries())
+        .thenReturn(ImmutableList.of(Root.fromPath(directories.getWorkspace())));
+
     SkyFunction.Environment env = Mockito.mock(SkyFunction.Environment.class);
     Mockito.when(env.getValue(MockitoHamcrest.argThat(new SkyKeyMatchers(FileValue.FILE))))
-        .thenReturn(fakeWorkspaceFileValue);
+        .then(
+            invocation -> {
+              SkyKey key = (SkyKey) invocation.getArguments()[0];
+              String path = ((RootedPath) key.argument()).getRootRelativePath().getPathString();
+              FakeFileValue result = new FakeFileValue();
+              result.setExists(path.equals("WORKSPACE"));
+              return result;
+            });
     Mockito.when(
             env.getValue(
                 MockitoHamcrest.argThat(new SkyKeyMatchers(WorkspaceFileValue.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());
-              }
+            invocation -> {
+              SkyKey key = (SkyKey) invocation.getArguments()[0];
+              return workspaceSkyFunc.compute(key, getEnv());
             });
     Mockito.when(
             env.getValue(MockitoHamcrest.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());
-              }
+            invocation -> {
+              SkyKey key = (SkyKey) invocation.getArguments()[0];
+              return astSkyFunc.compute(key, getEnv());
             });
     Mockito.when(
             env.getValue(MockitoHamcrest.argThat(new SkyKeyMatchers(SkyFunctions.PRECOMPUTED))))
         .then(
-            new Answer<SkyValue>() {
-              @Override
-              public SkyValue answer(InvocationOnMock invocation) throws Throwable {
-                SkyKey key = (SkyKey) invocation.getArguments()[0];
-                if (key.equals(PrecomputedValue.STARLARK_SEMANTICS.getKeyForTesting())) {
-                  return new PrecomputedValue(StarlarkSemantics.DEFAULT_SEMANTICS);
-                } else if (key.equals(
-                    RepositoryDelegatorFunction.RESOLVED_FILE_INSTEAD_OF_WORKSPACE
-                        .getKeyForTesting())) {
-                  return new PrecomputedValue(Optional.<RootedPath>absent());
-                } else {
-                  return null;
-                }
+            invocation -> {
+              SkyKey key = (SkyKey) invocation.getArguments()[0];
+              if (key.equals(PrecomputedValue.STARLARK_SEMANTICS.getKeyForTesting())) {
+                return new PrecomputedValue(StarlarkSemantics.DEFAULT_SEMANTICS);
+              } else if (key.equals(
+                  RepositoryDelegatorFunction.RESOLVED_FILE_INSTEAD_OF_WORKSPACE
+                      .getKeyForTesting())) {
+                return new PrecomputedValue(Optional.<RootedPath>absent());
+              } else if (key.equals(PrecomputedValue.PATH_PACKAGE_LOCATOR.getKeyForTesting())) {
+                return new PrecomputedValue(locator);
+              } else {
+                return null;
               }
             });
     return env;
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceNameFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceNameFunctionTest.java
index b290e8d..4d68c18 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceNameFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceNameFunctionTest.java
@@ -68,12 +68,10 @@
     reporter.removeHandler(failFastHandler);
     scratch.deleteFile("WORKSPACE");
     FileSystemUtils.ensureSymbolicLink(scratch.resolve("WORKSPACE"), "WORKSPACE");
-    // Transitive errors from WorkspaceNameValue should manifest themselves as
-    // NoSuchPackageExceptions.
     assertThatEvaluationResult(eval())
         .hasErrorEntryForKeyThat(key)
         .hasExceptionThat()
-        .isInstanceOf(NoSuchPackageException.class);
+        .isInstanceOf(FileSymlinkCycleException.class);
   }
 
   @Test