Allow globs to be used outside of the skyframe package.

--
MOS_MIGRATED_REVID=93647914
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java
index d0ac469..770899e 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java
@@ -296,16 +296,19 @@
 
     // This may be recreated if we discover inputs.
     PerActionFileCache perActionFileCache = new PerActionFileCache(state.inputArtifactData);
-    ActionExecutionContext actionExecutionContext =
-        skyframeActionExecutor.constructActionExecutionContext(perActionFileCache,
-            metadataHandler, state.expandedMiddlemen);
+    ActionExecutionContext actionExecutionContext = null;
     boolean inputsDiscoveredDuringActionExecution = false;
     Map<Artifact, FileArtifactValue> metadataFoundDuringActionExecution = null;
     try {
       if (action.discoversInputs()) {
         if (!state.hasDiscoveredInputs()) {
-          state.discoveredInputs =
-              skyframeActionExecutor.discoverInputs(action, actionExecutionContext);
+          try {
+            state.discoveredInputs = skyframeActionExecutor.discoverInputs(action,
+                perActionFileCache, metadataHandler, env);
+          } catch (MissingDepException e) {
+            Preconditions.checkState(env.valuesMissing(), action);
+            return null;
+          }
           if (state.discoveredInputs == null) {
             // Action had nothing to tell us about discovered inputs before execution. We'll have to
             // add them afterwards.
@@ -325,20 +328,22 @@
           perActionFileCache = new PerActionFileCache(state.inputArtifactData);
           metadataHandler =
               new ActionMetadataHandler(state.inputArtifactData, action.getOutputs(), tsgm);
-          actionExecutionContext =
-              skyframeActionExecutor.constructActionExecutionContext(perActionFileCache,
-                  metadataHandler, state.expandedMiddlemen);
         }
       }
+      actionExecutionContext =
+          skyframeActionExecutor.constructActionExecutionContext(perActionFileCache,
+              metadataHandler, state.expandedMiddlemen);
       if (!state.hasExecutedAction()) {
         state.value = skyframeActionExecutor.executeAction(action,
             metadataHandler, actionStartTime, actionExecutionContext);
       }
     } finally {
-      try {
-        actionExecutionContext.getFileOutErr().close();
-      } catch (IOException e) {
-        // Nothing we can do here.
+      if (actionExecutionContext != null) {
+        try {
+          actionExecutionContext.getFileOutErr().close();
+        } catch (IOException e) {
+          // Nothing we can do here.
+        }
       }
       if (inputsDiscoveredDuringActionExecution) {
         metadataFoundDuringActionExecution =
@@ -524,6 +529,12 @@
   }
 
   /**
+   * Exception to be thrown if an action is missing Skyframe dependencies that it finds are missing
+   * during execution/input discovery.
+   */
+  public static class MissingDepException extends RuntimeException {}
+
+  /**
    * Should be called once execution is over, and the intra-build cache of in-progress computations
    * should be discarded. If the cache is non-empty (due to an interrupted/failed build), failure to
    * call complete() can both cause a memory leak and incorrect results on the subsequent build.
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ContainingPackageLookupValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/ContainingPackageLookupValue.java
index 16516b5..0383534 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ContainingPackageLookupValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ContainingPackageLookupValue.java
@@ -29,7 +29,7 @@
   public abstract boolean hasContainingPackage();
 
   /** If there is a containing package, returns its name. */
-  abstract PackageIdentifier getContainingPackageName();
+  public abstract PackageIdentifier getContainingPackageName();
 
   /** If there is a containing package, returns its package root */
   public abstract Path getContainingPackageRoot();
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/FileStateValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/FileStateValue.java
index 030b50b..3d06d7c 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/FileStateValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/FileStateValue.java
@@ -13,6 +13,7 @@
 // limitations under the License.
 package com.google.devtools.build.lib.skyframe;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
 import com.google.devtools.build.lib.util.io.TimestampGranularityMonitor;
@@ -49,7 +50,8 @@
  *
  * <p>All subclasses must implement {@link #equals} and {@link #hashCode} properly.
  */
-abstract class FileStateValue implements SkyValue {
+@VisibleForTesting
+public abstract class FileStateValue implements SkyValue {
 
   static final FileStateValue DIRECTORY_FILE_STATE_NODE = DirectoryFileStateValue.INSTANCE;
   static final FileStateValue NONEXISTENT_FILE_STATE_NODE = NonexistentFileStateValue.INSTANCE;
@@ -92,8 +94,9 @@
         + "neither a file nor directory nor symlink.");
   }
 
+  @VisibleForTesting
   @ThreadSafe
-  static SkyKey key(RootedPath rootedPath) {
+  public static SkyKey key(RootedPath rootedPath) {
     return new SkyKey(SkyFunctions.FILE_STATE, rootedPath);
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/GlobValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/GlobValue.java
index 6de0fbd..c93370c 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/GlobValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/GlobValue.java
@@ -25,12 +25,10 @@
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
 
-/**
- * A value corresponding to a glob.
- */
+/** A value corresponding to a glob. */
 @Immutable
 @ThreadSafe
-final class GlobValue implements SkyValue {
+public final class GlobValue implements SkyValue {
 
   static final GlobValue EMPTY = new GlobValue(
       NestedSetBuilder.<PathFragment>emptySet(Order.STABLE_ORDER));
@@ -44,7 +42,7 @@
   /**
    * Returns glob matches.
    */
-  NestedSet<PathFragment> getMatches() {
+  public NestedSet<PathFragment> getMatches() {
     return matches;
   }
 
@@ -75,7 +73,8 @@
    * @throws InvalidGlobPatternException if the pattern is not valid.
    */
   @ThreadSafe
-  static SkyKey key(PackageIdentifier packageId, String pattern, boolean excludeDirs)
+  public static SkyKey key(PackageIdentifier packageId, String pattern, boolean excludeDirs,
+      PathFragment subdir)
       throws InvalidGlobPatternException {
     if (pattern.indexOf('?') != -1) {
       throw new InvalidGlobPatternException(pattern, "wildcard ? forbidden");
@@ -86,7 +85,7 @@
       throw new InvalidGlobPatternException(pattern, error);
     }
 
-    return internalKey(packageId, PathFragment.EMPTY_FRAGMENT, pattern, excludeDirs);
+    return internalKey(packageId, subdir, pattern, excludeDirs);
   }
 
   /**
@@ -116,7 +115,7 @@
    * An exception that indicates that a glob pattern is syntactically invalid.
    */
   @ThreadSafe
-  static final class InvalidGlobPatternException extends Exception {
+  public static final class InvalidGlobPatternException extends Exception {
     private final String pattern;
 
     InvalidGlobPatternException(String pattern, String error) {
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 7f2f224..8b354cd 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
@@ -293,7 +293,7 @@
       boolean excludeDirs = globPattern.getSecond();
       SkyKey globSkyKey;
       try {
-        globSkyKey = GlobValue.key(packageId, pattern, excludeDirs);
+        globSkyKey = GlobValue.key(packageId, pattern, excludeDirs, PathFragment.EMPTY_FRAGMENT);
       } catch (InvalidGlobPatternException e) {
         // Globs that make it to pkg.getGlobPatterns() should already be filtered for errors.
         throw new IllegalStateException(e);
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java
index 4000d0b..9b986c1 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java
@@ -65,6 +65,7 @@
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import com.google.devtools.build.lib.vfs.Symlinks;
+import com.google.devtools.build.skyframe.SkyFunction.Environment;
 import com.google.protobuf.ByteString;
 
 import java.io.IOException;
@@ -517,8 +518,16 @@
    * <p>This method is just a wrapper around {@link Action#discoverInputs} that properly processes
    * any ActionExecutionException thrown before rethrowing it to the caller.
    */
-  Collection<Artifact> discoverInputs(Action action, ActionExecutionContext actionExecutionContext)
+  Collection<Artifact> discoverInputs(Action action, PerActionFileCache graphFileCache,
+      MetadataHandler metadataHandler, Environment env)
       throws ActionExecutionException, InterruptedException {
+    ActionExecutionContext actionExecutionContext =
+        ActionExecutionContext.forInputDiscovery(
+            executorEngine,
+            new DelegatingPairFileCache(graphFileCache, perBuildFileCache),
+            metadataHandler,
+            actionLogBufferPathGenerator.generate(),
+            env);
     try {
       return action.discoverInputs(actionExecutionContext);
     } catch (ActionExecutionException e) {