diff options
author | 2015-03-17 20:55:30 +0000 | |
---|---|---|
committer | 2015-03-18 13:46:07 +0000 | |
commit | b889cf31f4f84516787faecac04b0c4cb1981bc5 (patch) | |
tree | c9f2455d27a1e33d80ce23aeb6209cf52a32f651 /src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternFunction.java | |
parent | 0942ee952efbc35d5def38216fe70d54a2dcd558 (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.java | 218 |
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 |