aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternFunction.java
diff options
context:
space:
mode:
authorGravatar Mark Schaller <mschaller@google.com>2015-03-17 20:55:30 +0000
committerGravatar Kristina Chodorow <kchodorow@google.com>2015-03-18 13:46:07 +0000
commitb889cf31f4f84516787faecac04b0c4cb1981bc5 (patch)
treec9f2455d27a1e33d80ce23aeb6209cf52a32f651 /src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternFunction.java
parent0942ee952efbc35d5def38216fe70d54a2dcd558 (diff)
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
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternFunction.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternFunction.java218
1 files changed, 12 insertions, 206 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternFunction.java
index b17a2826f6..9322998c13 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternFunction.java
@@ -13,32 +13,15 @@
// limitations under the License.
package com.google.devtools.build.lib.skyframe;
-import com.google.devtools.build.lib.cmdline.LabelValidator;
-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.cmdline.TargetPatternResolver;
-import com.google.devtools.build.lib.events.Event;
-import com.google.devtools.build.lib.packages.NoSuchPackageException;
-import com.google.devtools.build.lib.packages.NoSuchThingException;
-import com.google.devtools.build.lib.packages.Package;
-import com.google.devtools.build.lib.packages.PackageIdentifier;
-import com.google.devtools.build.lib.packages.Target;
-import com.google.devtools.build.lib.pkgcache.FilteringPolicies;
-import com.google.devtools.build.lib.pkgcache.FilteringPolicy;
import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
-import com.google.devtools.build.lib.pkgcache.TargetPatternResolverUtil;
-import com.google.devtools.build.lib.syntax.Label;
-import com.google.devtools.build.lib.vfs.Path;
-import com.google.devtools.build.lib.vfs.PathFragment;
-import com.google.devtools.build.lib.vfs.RootedPath;
+import com.google.devtools.build.lib.skyframe.EnvironmentBackedRecursivePackageProvider.MissingDepException;
import com.google.devtools.build.skyframe.SkyFunction;
import com.google.devtools.build.skyframe.SkyFunctionException;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
-import java.util.ArrayList;
-import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.Nullable;
@@ -60,15 +43,23 @@ public class TargetPatternFunction implements SkyFunction {
InterruptedException {
TargetPatternValue.TargetPattern patternKey =
((TargetPatternValue.TargetPattern) key.argument());
-
TargetPattern.Parser parser = new TargetPattern.Parser(patternKey.getOffset());
try {
- Resolver resolver = new Resolver(env, patternKey.getPolicy(), pkgPath);
+ EnvironmentBackedRecursivePackageProvider provider =
+ new EnvironmentBackedRecursivePackageProvider(env);
+ RecursivePackageProviderBackedTargetPatternResolver resolver =
+ new RecursivePackageProviderBackedTargetPatternResolver(provider, env.getListener(),
+ patternKey.getPolicy(), pkgPath.get());
TargetPattern resolvedPattern = parser.parse(patternKey.getPattern());
return new TargetPatternValue(resolvedPattern.eval(resolver));
} catch (TargetParsingException e) {
throw new TargetPatternFunctionException(e);
- } catch (TargetPatternResolver.MissingDepException e) {
+ } catch (MissingDepException e) {
+ // The EnvironmentBackedRecursivePackageProvider constructed above might throw
+ // MissingDepException to signal when it has a dependency on a missing Environment value.
+ // Note that MissingDepException extends RuntimeException because the methods called
+ // on EnvironmentBackedRecursivePackageProvider all belong to an interface shared with other
+ // implementations that are unconcerned with MissingDepExceptions.
return null;
}
}
@@ -79,192 +70,7 @@ public class TargetPatternFunction implements SkyFunction {
return null;
}
- private static class Resolver implements TargetPatternResolver<Target> {
- private final Environment env;
- private final FilteringPolicy policy;
- private final AtomicReference<PathPackageLocator> pkgPath;
-
- public Resolver(Environment env, FilteringPolicy policy,
- AtomicReference<PathPackageLocator> pkgPath) {
- this.policy = policy;
- this.env = env;
- this.pkgPath = pkgPath;
- }
-
- @Override
- public void warn(String msg) {
- env.getListener().handle(Event.warn(msg));
- }
-
- /**
- * Gets a Package via the Skyframe env. May return a Package that has errors.
- */
- private Package getPackage(PackageIdentifier pkgIdentifier)
- throws MissingDepException, NoSuchThingException {
- SkyKey pkgKey = PackageValue.key(pkgIdentifier);
- Package pkg;
- try {
- PackageValue pkgValue =
- (PackageValue) env.getValueOrThrow(pkgKey, NoSuchPackageException.class);
- if (pkgValue == null) {
- throw new MissingDepException();
- }
- pkg = pkgValue.getPackage();
- } catch (NoSuchPackageException e) {
- pkg = e.getPackage();
- if (pkg == null) {
- throw e;
- }
- }
- return pkg;
- }
-
- @Override
- public Target getTargetOrNull(String targetName) throws InterruptedException,
- MissingDepException {
- try {
- Label label = Label.parseAbsolute(targetName);
- if (!isPackage(label.getPackageName())) {
- return null;
- }
- Package pkg = getPackage(label.getPackageIdentifier());
- return pkg.getTarget(label.getName());
- } catch (Label.SyntaxException | NoSuchThingException e) {
- return null;
- }
- }
-
- @Override
- public ResolvedTargets<Target> getExplicitTarget(String targetName)
- throws TargetParsingException, InterruptedException, MissingDepException {
- Label label = TargetPatternResolverUtil.label(targetName);
- try {
- Package pkg = getPackage(label.getPackageIdentifier());
- Target target = pkg.getTarget(label.getName());
- return policy.shouldRetain(target, true)
- ? ResolvedTargets.of(target)
- : ResolvedTargets.<Target>empty();
- } catch (NoSuchThingException e) {
- throw new TargetParsingException(e.getMessage(), e);
- }
- }
-
- @Override
- public ResolvedTargets<Target> getTargetsInPackage(String originalPattern, String packageName,
- boolean rulesOnly)
- throws TargetParsingException, InterruptedException, MissingDepException {
- FilteringPolicy actualPolicy = rulesOnly
- ? FilteringPolicies.and(FilteringPolicies.RULES_ONLY, policy)
- : policy;
- return getTargetsInPackage(originalPattern, packageName, actualPolicy);
- }
-
- private ResolvedTargets<Target> getTargetsInPackage(String originalPattern, String packageName,
- FilteringPolicy policy)
- throws TargetParsingException, MissingDepException {
- // Normalise, e.g "foo//bar" -> "foo/bar"; "foo/" -> "foo":
- PathFragment packageNameFragment = new PathFragment(packageName);
- packageName = packageNameFragment.toString();
-
- // It's possible for this check to pass, but for
- // Label.validatePackageNameFull to report an error because the
- // package name is illegal. That's a little weird, but we can live with
- // that for now--see test case: testBadPackageNameButGoodEnoughForALabel.
- // (BTW I tried duplicating that validation logic in Label but it was
- // extremely tricky.)
- if (LabelValidator.validatePackageName(packageName) != null) {
- throw new TargetParsingException("'" + packageName + "' is not a valid package name");
- }
- if (!isPackage(packageName)) {
- throw new TargetParsingException(
- TargetPatternResolverUtil.getParsingErrorMessage(
- "no such package '" + packageName + "': BUILD file not found on package path",
- originalPattern));
- }
- try {
- Package pkg = getPackage(
- PackageIdentifier.createInDefaultRepo(packageNameFragment.toString()));
- return TargetPatternResolverUtil.resolvePackageTargets(pkg, policy);
- } catch (NoSuchThingException e) {
- String message = TargetPatternResolverUtil.getParsingErrorMessage(
- "package contains errors", originalPattern);
- throw new TargetParsingException(message, e);
- }
- }
-
- @Override
- public boolean isPackage(String packageName) throws MissingDepException {
- SkyKey packageLookupKey;
- packageLookupKey = PackageLookupValue.key(new PathFragment(packageName));
- PackageLookupValue packageLookupValue = (PackageLookupValue) env.getValue(packageLookupKey);
- if (packageLookupValue == null) {
- throw new MissingDepException();
- }
- return packageLookupValue.packageExists();
- }
-
- @Override
- public String getTargetKind(Target target) {
- return target.getTargetKind();
- }
-
- @Override
- public ResolvedTargets<Target> findTargetsBeneathDirectory(
- String originalPattern, String pathPrefix, boolean rulesOnly)
- throws TargetParsingException, MissingDepException {
- FilteringPolicy actualPolicy = rulesOnly
- ? FilteringPolicies.and(FilteringPolicies.RULES_ONLY, policy)
- : policy;
-
- PathFragment directory = new PathFragment(pathPrefix);
- if (directory.containsUplevelReferences()) {
- throw new TargetParsingException("up-level references are not permitted: '"
- + directory.getPathString() + "'");
- }
- if (!pathPrefix.isEmpty() && (LabelValidator.validatePackageName(pathPrefix) != null)) {
- throw new TargetParsingException("'" + pathPrefix + "' is not a valid package name");
- }
-
- ResolvedTargets.Builder<Target> builder = ResolvedTargets.builder();
-
- List<RecursivePkgValue> lookupValues = new ArrayList<>();
- for (Path root : pkgPath.get().getPathEntries()) {
- SkyKey key = RecursivePkgValue.key(RootedPath.toRootedPath(root, directory));
- RecursivePkgValue lookup = (RecursivePkgValue) env.getValue(key);
- if (lookup != null) {
- lookupValues.add(lookup);
- }
- }
- if (env.valuesMissing()) {
- throw new MissingDepException();
- }
-
- for (RecursivePkgValue value : lookupValues) {
- for (String pkg : value.getPackages()) {
- builder.merge(getTargetsInPackage(originalPattern, pkg, FilteringPolicies.NO_FILTER));
- }
- }
-
- if (builder.isEmpty()) {
- throw new TargetParsingException("no targets found beneath '" + directory + "'");
- }
-
- // Apply the transform after the check so we only return the
- // error if the tree really contains no targets.
- ResolvedTargets<Target> intermediateResult = builder.build();
- ResolvedTargets.Builder<Target> filteredBuilder = ResolvedTargets.builder();
- if (intermediateResult.hasError()) {
- filteredBuilder.setError();
- }
- for (Target target : intermediateResult.getTargets()) {
- if (actualPolicy.shouldRetain(target, false)) {
- filteredBuilder.add(target);
- }
- }
- return filteredBuilder.build();
- }
- }
/**
* Used to declare all the exception types that can be wrapped in the exception thrown by