On-the-fly target pattern resolution in SkyQueryEnvironment
Moves pattern resolving logic from TargetPatternFunction.Resolver to
a top level class. Adds a layer of abstraction to the Resolver
implementation enabling it to be backed by either an Environment or
a Graph, for use in SkyFunction evaluation or on-the-fly evaluation,
respectively. Finally, SkyQueryEnvironment#preloadOrThrow now checks
to see if each target pattern exists in the graph, and any that
don't will be resolved on-the-fly.
--
MOS_MIGRATED_REVID=88861201
diff --git a/src/main/java/com/google/devtools/build/lib/query2/AbstractBlazeQueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/query2/AbstractBlazeQueryEnvironment.java
index 96e8509..537738e 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/AbstractBlazeQueryEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/AbstractBlazeQueryEnvironment.java
@@ -26,6 +26,7 @@
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.pkgcache.PackageProvider;
+import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
import com.google.devtools.build.lib.pkgcache.TargetPatternEvaluator;
import com.google.devtools.build.lib.pkgcache.TransitivePackageLoader;
import com.google.devtools.build.lib.query2.engine.QueryEnvironment;
@@ -43,6 +44,8 @@
import java.util.Map;
import java.util.Set;
+import javax.annotation.Nullable;
+
/**
* {@link QueryEnvironment} that can evaluate queries to produce a result, and implements as much
* of QueryEnvironment as possible while remaining mostly agnostic as to the objects being stored.
@@ -92,10 +95,12 @@
PackageProvider packageProvider,
TargetPatternEvaluator targetPatternEvaluator, boolean keepGoing, boolean orderedResults,
List<String> universeScope, int loadingPhaseThreads,
- EventHandler eventHandler, Set<Setting> settings, Iterable<QueryFunction> functions) {
+ EventHandler eventHandler, Set<Setting> settings, Iterable<QueryFunction> functions,
+ @Nullable PathPackageLocator packagePath) {
return newQueryEnvironment(transitivePackageLoader, graphFactory, packageProvider,
targetPatternEvaluator, keepGoing, /*strictScope=*/true, orderedResults,
- universeScope, loadingPhaseThreads, Rule.ALL_LABELS, eventHandler, settings, functions);
+ universeScope, loadingPhaseThreads, Rule.ALL_LABELS, eventHandler, settings, functions,
+ packagePath);
}
public static AbstractBlazeQueryEnvironment<Target> newQueryEnvironment(
@@ -104,15 +109,17 @@
TargetPatternEvaluator targetPatternEvaluator, boolean keepGoing, boolean strictScope,
boolean orderedResults, List<String> universeScope, int loadingPhaseThreads,
Predicate<Label> labelFilter,
- EventHandler eventHandler, Set<Setting> settings, Iterable<QueryFunction> functions) {
+ EventHandler eventHandler, Set<Setting> settings, Iterable<QueryFunction> functions,
+ @Nullable PathPackageLocator packagePath) {
Preconditions.checkNotNull(universeScope);
- return orderedResults || universeScope.isEmpty()
+ return orderedResults || universeScope.isEmpty() || packagePath == null
? new BlazeQueryEnvironment(transitivePackageLoader, packageProvider,
targetPatternEvaluator, keepGoing, strictScope, loadingPhaseThreads,
labelFilter, eventHandler, settings, functions)
: new SkyQueryEnvironment(
keepGoing, strictScope, loadingPhaseThreads, labelFilter, eventHandler, settings,
- functions, targetPatternEvaluator.getOffset(), graphFactory, universeScope);
+ functions, targetPatternEvaluator.getOffset(), graphFactory, universeScope,
+ packagePath);
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/query2/SkyQueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/query2/SkyQueryEnvironment.java
index 4a0dae6..0b01884 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/SkyQueryEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/SkyQueryEnvironment.java
@@ -21,17 +21,21 @@
import com.google.common.collect.Maps;
import com.google.devtools.build.lib.cmdline.ResolvedTargets;
import com.google.devtools.build.lib.cmdline.TargetParsingException;
+import com.google.devtools.build.lib.cmdline.TargetPattern;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.graph.Digraph;
import com.google.devtools.build.lib.packages.NoSuchThingException;
import com.google.devtools.build.lib.packages.Package;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.Target;
+import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
import com.google.devtools.build.lib.pkgcache.TargetPatternEvaluator;
import com.google.devtools.build.lib.query2.engine.QueryEvalResult;
import com.google.devtools.build.lib.query2.engine.QueryException;
import com.google.devtools.build.lib.query2.engine.QueryExpression;
+import com.google.devtools.build.lib.skyframe.GraphBackedRecursivePackageProvider;
import com.google.devtools.build.lib.skyframe.PackageValue;
+import com.google.devtools.build.lib.skyframe.RecursivePackageProviderBackedTargetPatternResolver;
import com.google.devtools.build.lib.skyframe.SkyFunctions;
import com.google.devtools.build.lib.skyframe.TargetPatternValue;
import com.google.devtools.build.lib.skyframe.TransitiveTargetValue;
@@ -69,6 +73,7 @@
private final WalkableGraphFactory graphFactory;
private final List<String> universeScope;
private final String parserPrefix;
+ private final PathPackageLocator pkgPath;
public SkyQueryEnvironment(boolean keepGoing, boolean strictScope, int loadingPhaseThreads,
Predicate<Label> labelFilter,
@@ -76,13 +81,14 @@
Set<Setting> settings,
Iterable<QueryFunction> extraFunctions, String parserPrefix,
WalkableGraphFactory graphFactory,
- List<String> universeScope) {
+ List<String> universeScope, PathPackageLocator pkgPath) {
super(keepGoing, strictScope, labelFilter,
eventHandler,
settings,
extraFunctions);
this.loadingPhaseThreads = loadingPhaseThreads;
this.graphFactory = graphFactory;
+ this.pkgPath = pkgPath;
this.universeScope = Preconditions.checkNotNull(universeScope);
this.parserPrefix = parserPrefix;
Preconditions.checkState(!universeScope.isEmpty(),
@@ -307,20 +313,40 @@
protected Map<String, ResolvedTargets<Target>> preloadOrThrow(Collection<String> patterns)
throws QueryException, TargetParsingException {
- Map<String, ResolvedTargets<Target>> result =
- Maps.newHashMapWithExpectedSize(patterns.size());
+ Map<String, ResolvedTargets<Target>> result = Maps.newHashMapWithExpectedSize(patterns.size());
for (String pattern : patterns) {
SkyKey patternKey = TargetPatternValue.key(pattern,
TargetPatternEvaluator.DEFAULT_FILTERING_POLICY, parserPrefix);
- checkExistence(patternKey);
- TargetPatternValue value = (TargetPatternValue) graph.getValue(patternKey);
- if (value != null) {
- result.put(pattern, value.getTargets());
- } else if (!keepGoing) {
- throw (TargetParsingException) Preconditions.checkNotNull(graph.getException(patternKey),
- pattern);
+
+ TargetPatternValue.TargetPattern targetPattern =
+ ((TargetPatternValue.TargetPattern) patternKey.argument());
+
+ if (graph.exists(patternKey)) {
+ // If the graph already contains a value for this target pattern, use it.
+ TargetPatternValue value = (TargetPatternValue) graph.getValue(patternKey);
+ if (value != null) {
+ result.put(pattern, value.getTargets());
+ } else if (!keepGoing) {
+ throw (TargetParsingException) Preconditions.checkNotNull(graph.getException(patternKey),
+ pattern);
+ } else {
+ result.put(pattern, ResolvedTargets.<Target>builder().setError().build());
+ }
} else {
- result.put(pattern, ResolvedTargets.<Target>builder().setError().build());
+ // If the graph doesn't contain a value for this target pattern, try to directly evaluate
+ // it, by making use of packages already present in the graph.
+ TargetPattern.Parser parser = new TargetPattern.Parser(targetPattern.getOffset());
+ GraphBackedRecursivePackageProvider provider =
+ new GraphBackedRecursivePackageProvider(graph);
+ RecursivePackageProviderBackedTargetPatternResolver resolver =
+ new RecursivePackageProviderBackedTargetPatternResolver(provider, eventHandler,
+ targetPattern.getPolicy(), pkgPath);
+ TargetPattern parsedPattern = parser.parse(targetPattern.getPattern());
+ try {
+ result.put(pattern, parsedPattern.eval(resolver));
+ } catch (InterruptedException e) {
+ throw new QueryException(e.getMessage());
+ }
}
}
return result;