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/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;