Teach skyframe about excluded directories, paths

RecursivePkgFunction now expects both a rooted path to load packages
beneath and a set of paths to exclude. This also augments existing
machinery to deliver this set of paths to exclude.

This leads toward more efficient processing of target patterns in
target pattern sequence evaluation.

--
MOS_MIGRATED_REVID=94020331
diff --git a/src/main/java/com/google/devtools/build/lib/cmdline/TargetPattern.java b/src/main/java/com/google/devtools/build/lib/cmdline/TargetPattern.java
index ead03af..deeec79 100644
--- a/src/main/java/com/google/devtools/build/lib/cmdline/TargetPattern.java
+++ b/src/main/java/com/google/devtools/build/lib/cmdline/TargetPattern.java
@@ -19,6 +19,7 @@
 import com.google.common.base.Preconditions;
 import com.google.common.base.Splitter;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
 import com.google.devtools.build.lib.cmdline.LabelValidator.BadLabelException;
 import com.google.devtools.build.lib.cmdline.LabelValidator.PackageAndTarget;
 
@@ -119,7 +120,20 @@
   /**
    * Evaluates the current target pattern and returns the result.
    */
-  public abstract <T> ResolvedTargets<T> eval(TargetPatternResolver<T> resolver)
+  public <T> ResolvedTargets<T> eval(TargetPatternResolver<T> resolver)
+      throws TargetParsingException, InterruptedException {
+    return eval(resolver, ImmutableSet.<String>of());
+  }
+
+  /**
+   * Evaluates the current target pattern, excluding targets under directories in
+   * {@code excludedSubdirectories}, and returns the result.
+   *
+   * @throws IllegalArgumentException if {@code excludedSubdirectories} is nonempty and this
+   *      pattern does not have type {@code Type.TARGETS_BELOW_DIRECTORY}.
+   */
+  public abstract <T> ResolvedTargets<T> eval(TargetPatternResolver<T> resolver,
+      ImmutableSet<String> excludedSubdirectories)
       throws TargetParsingException, InterruptedException;
 
   /**
@@ -153,8 +167,12 @@
     }
 
     @Override
-    public <T> ResolvedTargets<T> eval(TargetPatternResolver<T> resolver)
+    public <T> ResolvedTargets<T> eval(TargetPatternResolver<T> resolver,
+        ImmutableSet<String> excludedSubdirectories)
         throws TargetParsingException, InterruptedException {
+      Preconditions.checkArgument(excludedSubdirectories.isEmpty(),
+          "Target pattern \"%s\" of type %s cannot be evaluated with excluded subdirectories: %s.",
+          targetName, getType(), excludedSubdirectories);
       return resolver.getExplicitTarget(targetName);
     }
 
@@ -196,8 +214,12 @@
     }
 
     @Override
-    public <T> ResolvedTargets<T> eval(TargetPatternResolver<T> resolver)
+    public <T> ResolvedTargets<T> eval(TargetPatternResolver<T> resolver,
+        ImmutableSet<String> excludedSubdirectories)
         throws TargetParsingException, InterruptedException {
+      Preconditions.checkArgument(excludedSubdirectories.isEmpty(),
+          "Target pattern \"%s\" of type %s cannot be evaluated with excluded subdirectories: %s.",
+          path, getType(), excludedSubdirectories);
       if (resolver.isPackage(path)) {
         // User has specified a package name. lookout for default target.
         return resolver.getExplicitTarget("//" + path);
@@ -268,8 +290,12 @@
     }
 
     @Override
-    public <T> ResolvedTargets<T> eval(TargetPatternResolver<T> resolver)
+    public <T> ResolvedTargets<T> eval(TargetPatternResolver<T> resolver,
+        ImmutableSet<String> excludedSubdirectories)
         throws TargetParsingException, InterruptedException {
+      Preconditions.checkArgument(excludedSubdirectories.isEmpty(),
+          "Target pattern \"%s\" of type %s cannot be evaluated with excluded subdirectories: %s.",
+          originalPattern, getType(), excludedSubdirectories);
       if (checkWildcardConflict) {
         ResolvedTargets<T> targets = getWildcardConflict(resolver);
         if (targets != null) {
@@ -359,9 +385,11 @@
     }
 
     @Override
-    public <T> ResolvedTargets<T> eval(TargetPatternResolver<T> resolver)
+    public <T> ResolvedTargets<T> eval(TargetPatternResolver<T> resolver,
+        ImmutableSet<String> excludedSubdirectories)
         throws TargetParsingException, InterruptedException {
-      return resolver.findTargetsBeneathDirectory(originalPattern, directory, rulesOnly);
+      return resolver.findTargetsBeneathDirectory(originalPattern, directory, rulesOnly,
+          excludedSubdirectories);
     }
 
     @Override