diff options
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/skyframe')
5 files changed, 180 insertions, 53 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternsFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternsFunction.java index bd280dd9cf..6653c48933 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternsFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternsFunction.java @@ -15,6 +15,7 @@ package com.google.devtools.build.lib.skyframe; import com.google.common.base.Preconditions; import com.google.common.base.Predicates; +import com.google.common.collect.ImmutableList; import com.google.devtools.build.lib.cmdline.ResolvedTargets; import com.google.devtools.build.lib.cmdline.TargetParsingException; import com.google.devtools.build.lib.events.Event; @@ -24,6 +25,7 @@ import com.google.devtools.build.lib.packages.NoSuchTargetException; import com.google.devtools.build.lib.pkgcache.ParseFailureListener; import com.google.devtools.build.lib.skyframe.PrepareDepsOfPatternsValue.TargetPatternSequence; import com.google.devtools.build.lib.skyframe.TargetPatternValue.TargetPatternKey; +import com.google.devtools.build.lib.skyframe.TargetPatternValue.TargetPatternSkyKeyOrException; import com.google.devtools.build.lib.syntax.Label; import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyKey; @@ -50,20 +52,32 @@ public class PrepareDepsOfPatternsFunction implements SkyFunction { @Nullable @Override public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException { + EventHandler eventHandler = env.getListener(); + boolean handlerIsParseFailureListener = eventHandler instanceof ParseFailureListener; TargetPatternSequence targetPatternSequence = (TargetPatternSequence) skyKey.argument(); - Iterable<SkyKey> patternSkyKeys = TargetPatternValue.keys(targetPatternSequence.getPatterns(), - targetPatternSequence.getPolicy(), targetPatternSequence.getOffset()); + Iterable<TargetPatternSkyKeyOrException> keysMaybe = + TargetPatternValue.keys(targetPatternSequence.getPatterns(), + targetPatternSequence.getPolicy(), targetPatternSequence.getOffset()); + + ImmutableList.Builder<SkyKey> skyKeyBuilder = ImmutableList.builder(); + for (TargetPatternSkyKeyOrException skyKeyOrException : keysMaybe) { + try { + skyKeyBuilder.add(skyKeyOrException.getSkyKey()); + } catch (TargetParsingException e) { + handleTargetParsingException(eventHandler, handlerIsParseFailureListener, + skyKeyOrException.getOriginalPattern(), e); + } + } + ImmutableList<SkyKey> skyKeys = skyKeyBuilder.build(); + Map<SkyKey, ValueOrException<TargetParsingException>> targetPatternValuesByKey = - env.getValuesOrThrow(patternSkyKeys, TargetParsingException.class); + env.getValuesOrThrow(skyKeys, TargetParsingException.class); if (env.valuesMissing()) { return null; } - EventHandler eventHandler = env.getListener(); - boolean handlerIsParseFailureListener = eventHandler instanceof ParseFailureListener; - ResolvedTargets.Builder<Label> builder = ResolvedTargets.builder(); - for (SkyKey key : patternSkyKeys) { + for (SkyKey key : skyKeys) { try { // The only exception type throwable by TargetPatternFunction is TargetParsingException. // Therefore all ValueOrException values in the map will either be non-null or throw @@ -102,13 +116,18 @@ public class PrepareDepsOfPatternsFunction implements SkyFunction { private static void handleTargetParsingException(EventHandler eventHandler, boolean handlerIsParseFailureListener, SkyKey key, TargetParsingException e) { - TargetPatternKey pattern = (TargetPatternKey) key.argument(); - String rawPattern = pattern.getPattern(); + TargetPatternKey patternKey = (TargetPatternKey) key.argument(); + String rawPattern = patternKey.getPattern(); + handleTargetParsingException(eventHandler, handlerIsParseFailureListener, rawPattern, e); + } + + private static void handleTargetParsingException(EventHandler eventHandler, + boolean handlerIsParseFailureListener, String rawPattern, TargetParsingException e) { String errorMessage = e.getMessage(); eventHandler.handle(Event.error("Skipping '" + rawPattern + "': " + errorMessage)); if (handlerIsParseFailureListener) { ParseFailureListener parseListener = (ParseFailureListener) eventHandler; - parseListener.parsingError(rawPattern, errorMessage); + parseListener.parsingError(rawPattern, errorMessage); } } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternsValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternsValue.java index 88f034cee2..918b31fd15 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternsValue.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternsValue.java @@ -37,8 +37,7 @@ public final class PrepareDepsOfPatternsValue implements SkyValue { } @ThreadSafe - public static SkyKey key(ImmutableList<String> patterns, FilteringPolicy policy, - String offset) { + public static SkyKey key(ImmutableList<String> patterns, FilteringPolicy policy, String offset) { return new SkyKey(SkyFunctions.PREPARE_DEPS_OF_PATTERNS, new TargetPatternSequence(patterns, policy, offset)); } @@ -50,8 +49,8 @@ public final class PrepareDepsOfPatternsValue implements SkyValue { private final FilteringPolicy policy; private final String offset; - public TargetPatternSequence(ImmutableList<String> patterns, - FilteringPolicy policy, String offset) { + private TargetPatternSequence(ImmutableList<String> patterns, FilteringPolicy policy, + String offset) { this.patterns = patterns; this.policy = policy; this.offset = offset; diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeTargetPatternEvaluator.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeTargetPatternEvaluator.java index 979f322b19..d166126038 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeTargetPatternEvaluator.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeTargetPatternEvaluator.java @@ -30,6 +30,7 @@ import com.google.devtools.build.lib.packages.Target; import com.google.devtools.build.lib.pkgcache.FilteringPolicy; import com.google.devtools.build.lib.pkgcache.ParseFailureListener; import com.google.devtools.build.lib.pkgcache.TargetPatternEvaluator; +import com.google.devtools.build.lib.skyframe.TargetPatternValue.TargetPatternSkyKeyOrException; import com.google.devtools.build.lib.syntax.Label; import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.skyframe.ErrorInfo; @@ -99,8 +100,27 @@ final class SkyframeTargetPatternEvaluator implements TargetPatternEvaluator { ResolvedTargets<Target> parseTargetPatternList(String offset, EventHandler eventHandler, List<String> targetPatterns, FilteringPolicy policy, boolean keepGoing) throws InterruptedException, TargetParsingException { - return parseTargetPatternKeys(TargetPatternValue.keys(targetPatterns, policy, offset), - SkyframeExecutor.DEFAULT_THREAD_COUNT, keepGoing, eventHandler); + Iterable<TargetPatternSkyKeyOrException> keysMaybe = + TargetPatternValue.keys(targetPatterns, policy, offset); + + ImmutableList.Builder<SkyKey> builder = ImmutableList.builder(); + for (TargetPatternSkyKeyOrException skyKeyOrException : keysMaybe) { + try { + builder.add(skyKeyOrException.getSkyKey()); + } catch (TargetParsingException e) { + if (!keepGoing) { + throw e; + } + String pattern = skyKeyOrException.getOriginalPattern(); + eventHandler.handle(Event.error("Skipping '" + pattern + "': " + e.getMessage())); + if (eventHandler instanceof ParseFailureListener) { + ((ParseFailureListener) eventHandler).parsingError(pattern, e.getMessage()); + } + } + } + ImmutableList<SkyKey> skyKeys = builder.build(); + return parseTargetPatternKeys(skyKeys, SkyframeExecutor.DEFAULT_THREAD_COUNT, keepGoing, + eventHandler); } private static Map<PackageIdentifier, Package> getPackages( 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 97aef9845f..d805a91695 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 @@ -14,6 +14,7 @@ package com.google.devtools.build.lib.skyframe; import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableSet; import com.google.devtools.build.lib.cmdline.ResolvedTargets; import com.google.devtools.build.lib.cmdline.TargetParsingException; import com.google.devtools.build.lib.cmdline.TargetPattern; @@ -47,16 +48,16 @@ public class TargetPatternFunction implements SkyFunction { InterruptedException { TargetPatternValue.TargetPatternKey patternKey = ((TargetPatternValue.TargetPatternKey) key.argument()); - TargetPattern.Parser parser = new TargetPattern.Parser(patternKey.getOffset()); - ResolvedTargets<Target> resolvedTargets = null; + ResolvedTargets<Target> resolvedTargets; try { EnvironmentBackedRecursivePackageProvider provider = new EnvironmentBackedRecursivePackageProvider(env); RecursivePackageProviderBackedTargetPatternResolver resolver = new RecursivePackageProviderBackedTargetPatternResolver(provider, env.getListener(), patternKey.getPolicy(), pkgPath.get()); - TargetPattern resolvedPattern = parser.parse(patternKey.getPattern()); - resolvedTargets = resolvedPattern.eval(resolver); + TargetPattern parsedPattern = patternKey.getParsedPattern(); + ImmutableSet<String> excludedSubdirectories = patternKey.getExcludedSubdirectories(); + resolvedTargets = parsedPattern.eval(resolver, excludedSubdirectories); } catch (TargetParsingException e) { throw new TargetPatternFunctionException(e); } catch (MissingDepException e) { diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternValue.java index 1463140d3c..1f665e0152 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternValue.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternValue.java @@ -14,9 +14,13 @@ package com.google.devtools.build.lib.skyframe; import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; import com.google.devtools.build.lib.cmdline.ResolvedTargets; import com.google.devtools.build.lib.cmdline.ResolvedTargets.Builder; +import com.google.devtools.build.lib.cmdline.TargetParsingException; +import com.google.devtools.build.lib.cmdline.TargetPattern; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe; import com.google.devtools.build.lib.pkgcache.FilteringPolicies; @@ -31,7 +35,6 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.Objects; @@ -93,42 +96,54 @@ public final class TargetPatternValue implements SkyValue { } /** - * Create a target pattern value key. + * Create a target pattern {@link SkyKey}. Throws {@link TargetParsingException} if the provided + * {@code pattern} cannot be parsed. * - * @param pattern The pattern, eg "-foo/biz...". If the first character is "-", the pattern - * is treated as a negative pattern. + * @param pattern The pattern, eg "-foo/biz...". If the first character is "-", the pattern is + * treated as a negative pattern. * @param policy The filtering policy, eg "only return test targets" * @param offset The offset to apply to relative target patterns. */ @ThreadSafe - public static SkyKey key(String pattern, - FilteringPolicy policy, - String offset) { - return new SkyKey(SkyFunctions.TARGET_PATTERN, - pattern.startsWith("-") - // Don't apply filters to negative patterns. - ? new TargetPatternKey(pattern.substring(1), FilteringPolicies.NO_FILTER, true, offset) - : new TargetPatternKey(pattern, policy, false, offset)); + public static SkyKey key(String pattern, FilteringPolicy policy, String offset) + throws TargetParsingException { + return Iterables.getOnlyElement(keys(ImmutableList.of(pattern), policy, offset)).getSkyKey(); } /** - * Like above, but accepts a collection of target patterns for the same filtering policy. + * Returns an iterable of {@link TargetPatternSkyKeyOrException}, with {@link TargetPatternKey} + * arguments, in the same order as the list of patterns provided as input. If a provided pattern + * fails to parse, the element in the returned iterable corresponding to it will throw when its + * {@link TargetPatternSkyKeyOrException#getSkyKey} method is called. * - * @param patterns The collection of patterns, eg "-foo/biz...". If the first character is "-", - * the pattern is treated as a negative pattern. + * @param patterns The list of patterns, eg "-foo/biz...". If a pattern's first character is "-", + * it is treated as a negative pattern. * @param policy The filtering policy, eg "only return test targets" * @param offset The offset to apply to relative target patterns. */ @ThreadSafe - public static Iterable<SkyKey> keys(Collection<String> patterns, - FilteringPolicy policy, - String offset) { - List<SkyKey> keys = Lists.newArrayListWithCapacity(patterns.size()); + public static Iterable<TargetPatternSkyKeyOrException> keys(List<String> patterns, + FilteringPolicy policy, String offset) { + TargetPattern.Parser parser = new TargetPattern.Parser(offset); + ImmutableList.Builder<TargetPatternSkyKeyOrException> builder = ImmutableList.builder(); for (String pattern : patterns) { - keys.add(key(pattern, policy, offset)); + boolean positive = !pattern.startsWith("-"); + String absoluteValueOfPattern = positive ? pattern : pattern.substring(1); + TargetPattern targetPattern; + try { + targetPattern = parser.parse(absoluteValueOfPattern); + } catch (TargetParsingException e) { + builder.add(new TargetPatternSkyKeyException(e, absoluteValueOfPattern)); + continue; + } + TargetPatternKey targetPatternKey = new TargetPatternKey(targetPattern, + positive ? policy : FilteringPolicies.NO_FILTER, /*isNegative=*/!positive, offset, + ImmutableSet.<String>of()); + SkyKey skyKey = new SkyKey(SkyFunctions.TARGET_PATTERN, targetPatternKey); + builder.add(new TargetPatternSkyKeyValue(skyKey)); } - return keys; - } + return builder.build(); + } public ResolvedTargets<Label> getTargets() { return targets; @@ -136,26 +151,33 @@ public final class TargetPatternValue implements SkyValue { /** * A TargetPatternKey is a tuple of pattern (eg, "foo/..."), filtering policy, a relative pattern - * offset, and whether it is a positive or negative match. + * offset, whether it is a positive or negative match, and a set of excluded subdirectories. */ @ThreadSafe public static class TargetPatternKey implements Serializable { - private final String pattern; + + private final TargetPattern parsedPattern; private final FilteringPolicy policy; private final boolean isNegative; private final String offset; + private final ImmutableSet<String> excludedSubdirectories; - public TargetPatternKey(String pattern, FilteringPolicy policy, - boolean isNegative, String offset) { - this.pattern = Preconditions.checkNotNull(pattern); + public TargetPatternKey(TargetPattern parsedPattern, FilteringPolicy policy, + boolean isNegative, String offset, ImmutableSet<String> excludedSubdirectories) { + this.parsedPattern = Preconditions.checkNotNull(parsedPattern); this.policy = Preconditions.checkNotNull(policy); this.isNegative = isNegative; this.offset = offset; + this.excludedSubdirectories = Preconditions.checkNotNull(excludedSubdirectories); } public String getPattern() { - return pattern; + return parsedPattern.getOriginalPattern(); + } + + public TargetPattern getParsedPattern() { + return parsedPattern; } public boolean isNegative() { @@ -170,14 +192,19 @@ public final class TargetPatternValue implements SkyValue { return offset; } + public ImmutableSet<String> getExcludedSubdirectories() { + return excludedSubdirectories; + } + @Override public String toString() { - return (isNegative ? "-" : "") + pattern; + return (isNegative ? "-" : "") + parsedPattern.getOriginalPattern(); } @Override public int hashCode() { - return Objects.hash(pattern, isNegative, policy, offset); + return Objects.hash(parsedPattern, isNegative, policy, offset, + excludedSubdirectories); } @Override @@ -187,8 +214,69 @@ public final class TargetPatternValue implements SkyValue { } TargetPatternKey other = (TargetPatternKey) obj; - return other.isNegative == this.isNegative && other.pattern.equals(this.pattern) && - other.offset.equals(this.offset) && other.policy.equals(this.policy); + return other.isNegative == this.isNegative && other.parsedPattern.equals(this.parsedPattern) + && other.offset.equals(this.offset) && other.policy.equals(this.policy) + && other.excludedSubdirectories.equals(this.excludedSubdirectories); + } + } + + /** + * Wrapper for a target pattern {@link SkyKey} or the {@link TargetParsingException} thrown when + * trying to compute it. + */ + public interface TargetPatternSkyKeyOrException { + + /** + * Returns the stored {@link SkyKey} or throws {@link TargetParsingException} if one was thrown + * when computing the key. + */ + SkyKey getSkyKey() throws TargetParsingException; + + /** + * Returns the pattern that resulted in the stored {@link SkyKey} or {@link + * TargetParsingException}. + */ + String getOriginalPattern(); + } + + private static final class TargetPatternSkyKeyValue implements TargetPatternSkyKeyOrException { + + private final SkyKey value; + + private TargetPatternSkyKeyValue(SkyKey value) { + this.value = value; + } + + @Override + public SkyKey getSkyKey() throws TargetParsingException { + return value; + } + + @Override + public String getOriginalPattern() { + return ((TargetPatternKey) value.argument()).getPattern(); + } + } + + private static final class TargetPatternSkyKeyException implements + TargetPatternSkyKeyOrException { + + private final TargetParsingException exception; + private final String originalPattern; + + private TargetPatternSkyKeyException(TargetParsingException exception, String originalPattern) { + this.exception = exception; + this.originalPattern = originalPattern; + } + + @Override + public SkyKey getSkyKey() throws TargetParsingException { + throw exception; + } + + @Override + public String getOriginalPattern() { + return originalPattern; } } } |