Damien Martin-Guillerez | f88f4d8 | 2015-09-25 13:56:55 +0000 | [diff] [blame] | 1 | // Copyright 2015 The Bazel Authors. All rights reserved. |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | package com.google.devtools.build.lib.skyframe; |
| 15 | |
| 16 | import com.google.common.collect.ImmutableList; |
janakr | 5fb2a48 | 2018-03-02 17:48:57 -0800 | [diff] [blame] | 17 | import com.google.common.collect.Interner; |
wyv | 630be02 | 2021-10-04 07:55:36 -0700 | [diff] [blame] | 18 | import com.google.devtools.build.lib.cmdline.SignedTargetPattern; |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 19 | import com.google.devtools.build.lib.cmdline.TargetParsingException; |
jcater | cecb3a8 | 2018-05-01 14:37:48 -0700 | [diff] [blame] | 20 | import com.google.devtools.build.lib.cmdline.TargetPattern; |
Mark Schaller | e7e8b2a | 2015-07-07 19:31:12 +0000 | [diff] [blame] | 21 | import com.google.devtools.build.lib.cmdline.TargetPattern.Type; |
janakr | 5fb2a48 | 2018-03-02 17:48:57 -0800 | [diff] [blame] | 22 | import com.google.devtools.build.lib.concurrent.BlazeInterners; |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 23 | import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe; |
Mark Schaller | d7311e0 | 2015-07-07 16:36:09 +0000 | [diff] [blame] | 24 | import com.google.devtools.build.lib.pkgcache.FilteringPolicies; |
Googler | 35b92d0 | 2020-08-03 07:42:11 -0700 | [diff] [blame] | 25 | import com.google.devtools.build.lib.server.FailureDetails.TargetPatterns; |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 26 | import com.google.devtools.build.lib.skyframe.TargetPatternValue.TargetPatternKey; |
shahan | 09765a8 | 2018-02-27 11:54:45 -0800 | [diff] [blame] | 27 | import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; |
Googler | 41797b6 | 2021-11-19 12:07:05 -0800 | [diff] [blame] | 28 | import com.google.devtools.build.lib.skyframe.serialization.autocodec.SerializationConstant; |
janakr | a3652a3 | 2020-09-10 12:05:20 -0700 | [diff] [blame] | 29 | import com.google.devtools.build.lib.vfs.PathFragment; |
janakr | 5fb2a48 | 2018-03-02 17:48:57 -0800 | [diff] [blame] | 30 | import com.google.devtools.build.skyframe.AbstractSkyKey; |
| 31 | import com.google.devtools.build.skyframe.SkyFunctionName; |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 32 | import com.google.devtools.build.skyframe.SkyValue; |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 33 | import java.util.List; |
| 34 | |
| 35 | /** |
| 36 | * The value returned by {@link PrepareDepsOfPatternFunction}. Because that function is |
| 37 | * invoked only for its side effect (i.e. ensuring the graph contains targets matching the |
| 38 | * pattern and its transitive dependencies), this value carries no information. |
| 39 | * |
Mark Schaller | f3ec7c4 | 2015-08-21 17:44:41 +0000 | [diff] [blame] | 40 | * <p>Because the returned value is always equal to objects that share its type, this value and the |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 41 | * {@link PrepareDepsOfPatternFunction} which computes it are incompatible with change pruning. It |
| 42 | * should only be requested by consumers who do not require reevaluation when |
| 43 | * {@link PrepareDepsOfPatternFunction} is reevaluated. Safe consumers include, e.g., top-level |
| 44 | * consumers, and other functions which invoke {@link PrepareDepsOfPatternFunction} solely for its |
| 45 | * side-effects. |
| 46 | */ |
| 47 | public class PrepareDepsOfPatternValue implements SkyValue { |
Mark Schaller | f3ec7c4 | 2015-08-21 17:44:41 +0000 | [diff] [blame] | 48 | // Note that this value does not guarantee singleton-like reference equality because we use Java |
| 49 | // deserialization. Java deserialization can create other instances. |
Googler | 41797b6 | 2021-11-19 12:07:05 -0800 | [diff] [blame] | 50 | @SerializationConstant |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 51 | public static final PrepareDepsOfPatternValue INSTANCE = new PrepareDepsOfPatternValue(); |
| 52 | |
| 53 | private PrepareDepsOfPatternValue() { |
| 54 | } |
| 55 | |
Mark Schaller | f3ec7c4 | 2015-08-21 17:44:41 +0000 | [diff] [blame] | 56 | @Override |
| 57 | public boolean equals(Object o) { |
| 58 | return o instanceof PrepareDepsOfPatternValue; |
| 59 | } |
| 60 | |
| 61 | @Override |
| 62 | public int hashCode() { |
| 63 | return 42; |
| 64 | } |
| 65 | |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 66 | /** |
janakr | a3652a3 | 2020-09-10 12:05:20 -0700 | [diff] [blame] | 67 | * Returns a {@link PrepareDepsOfPatternSkyKeysAndExceptions}, containing {@link |
| 68 | * PrepareDepsOfPatternSkyKeyValue} and {@link PrepareDepsOfPatternSkyKeyException} instances that |
| 69 | * have {@link TargetPatternKey} arguments. Negative target patterns of type other than {@link |
| 70 | * Type#TARGETS_BELOW_DIRECTORY} are not permitted. If a provided pattern fails to parse or is |
| 71 | * negative but not a {@link Type#TARGETS_BELOW_DIRECTORY}, there will be a corresponding {@link |
| 72 | * PrepareDepsOfPatternSkyKeyException} in the iterable returned by {@link |
| 73 | * PrepareDepsOfPatternSkyKeysAndExceptions#getExceptions} whose {@link |
| 74 | * PrepareDepsOfPatternSkyKeyException#getException} and {@link |
| 75 | * PrepareDepsOfPatternSkyKeyException#getOriginalPattern} methods return the {@link |
| 76 | * TargetParsingException} and original pattern, respectively. |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 77 | * |
janakr | a3652a3 | 2020-09-10 12:05:20 -0700 | [diff] [blame] | 78 | * <p>There may be fewer returned elements in {@link |
| 79 | * PrepareDepsOfPatternSkyKeysAndExceptions#getValues} than patterns provided as input. This |
| 80 | * function will combine negative {@link Type#TARGETS_BELOW_DIRECTORY} patterns with preceding |
| 81 | * patterns to return an iterable of SkyKeys that avoids loading excluded directories during |
| 82 | * evaluation. |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 83 | * |
Mark Schaller | e7e8b2a | 2015-07-07 19:31:12 +0000 | [diff] [blame] | 84 | * @param patterns The list of patterns, e.g. [//foo/..., -//foo/biz/...]. If a pattern's first |
| 85 | * character is "-", it is treated as a negative pattern. |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 86 | * @param offset The offset to apply to relative target patterns. |
| 87 | */ |
| 88 | @ThreadSafe |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 89 | public static PrepareDepsOfPatternSkyKeysAndExceptions keys( |
janakr | a3652a3 | 2020-09-10 12:05:20 -0700 | [diff] [blame] | 90 | List<String> patterns, PathFragment offset) { |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 91 | ImmutableList.Builder<PrepareDepsOfPatternSkyKeyValue> resultValuesBuilder = |
| 92 | ImmutableList.builder(); |
| 93 | ImmutableList.Builder<PrepareDepsOfPatternSkyKeyException> resultExceptionsBuilder = |
| 94 | ImmutableList.builder(); |
wyv | 630be02 | 2021-10-04 07:55:36 -0700 | [diff] [blame] | 95 | TargetPattern.Parser parser = TargetPattern.mainRepoParser(offset); |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 96 | ImmutableList.Builder<TargetPatternKey> targetPatternKeysBuilder = ImmutableList.builder(); |
wyv | 630be02 | 2021-10-04 07:55:36 -0700 | [diff] [blame] | 97 | for (String pattern : patterns) { |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 98 | try { |
wyv | 630be02 | 2021-10-04 07:55:36 -0700 | [diff] [blame] | 99 | targetPatternKeysBuilder.add( |
| 100 | TargetPatternValue.key( |
| 101 | SignedTargetPattern.parse(pattern, parser), FilteringPolicies.NO_FILTER)); |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 102 | } catch (TargetParsingException e) { |
wyv | 630be02 | 2021-10-04 07:55:36 -0700 | [diff] [blame] | 103 | resultExceptionsBuilder.add(new PrepareDepsOfPatternSkyKeyException(e, pattern)); |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 104 | } |
| 105 | } |
Mark Schaller | e7e8b2a | 2015-07-07 19:31:12 +0000 | [diff] [blame] | 106 | // This code path is evaluated only for query universe preloading, and the quadratic cost of |
| 107 | // the code below (i.e. for each pattern, consider each later pattern as a candidate for |
| 108 | // subdirectory exclusion) is only acceptable because all the use cases for query universe |
| 109 | // preloading involve short (<10 items) pattern sequences. |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 110 | Iterable<TargetPatternKey> combinedTargetPatternKeys = |
shreyax | 432b253 | 2019-01-23 11:16:07 -0800 | [diff] [blame] | 111 | TargetPatternValue.combineTargetsBelowDirectoryWithNegativePatterns( |
| 112 | targetPatternKeysBuilder.build(), /*excludeSingleTargets=*/ false); |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 113 | for (TargetPatternKey targetPatternKey : combinedTargetPatternKeys) { |
| 114 | if (targetPatternKey.isNegative() |
jcater | cecb3a8 | 2018-05-01 14:37:48 -0700 | [diff] [blame] | 115 | && !targetPatternKey |
| 116 | .getParsedPattern() |
| 117 | .getType() |
| 118 | .equals(TargetPattern.Type.TARGETS_BELOW_DIRECTORY)) { |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 119 | resultExceptionsBuilder.add( |
| 120 | new PrepareDepsOfPatternSkyKeyException( |
| 121 | new TargetParsingException( |
| 122 | "Negative target patterns of types other than \"targets below directory\"" |
Googler | 35b92d0 | 2020-08-03 07:42:11 -0700 | [diff] [blame] | 123 | + " are not permitted.", |
| 124 | TargetPatterns.Code.NEGATIVE_TARGET_PATTERN_NOT_ALLOWED), |
| 125 | targetPatternKey.toString())); |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 126 | } else { |
| 127 | resultValuesBuilder.add(new PrepareDepsOfPatternSkyKeyValue(targetPatternKey)); |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 128 | } |
| 129 | } |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 130 | return new PrepareDepsOfPatternSkyKeysAndExceptions( |
| 131 | resultValuesBuilder.build(), resultExceptionsBuilder.build()); |
Mark Schaller | e7e8b2a | 2015-07-07 19:31:12 +0000 | [diff] [blame] | 132 | } |
| 133 | |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 134 | /** |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 135 | * A pair of {@link Iterable<PrepareDepsOfPatternSkyKeyValue>} and |
| 136 | * {@link Iterable<PrepareDepsOfPatternSkyKeyException>}. |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 137 | */ |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 138 | public static class PrepareDepsOfPatternSkyKeysAndExceptions { |
| 139 | private final Iterable<PrepareDepsOfPatternSkyKeyValue> values; |
| 140 | private final Iterable<PrepareDepsOfPatternSkyKeyException> exceptions; |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 141 | |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 142 | public PrepareDepsOfPatternSkyKeysAndExceptions( |
| 143 | Iterable<PrepareDepsOfPatternSkyKeyValue> values, |
| 144 | Iterable<PrepareDepsOfPatternSkyKeyException> exceptions) { |
| 145 | this.values = values; |
| 146 | this.exceptions = exceptions; |
| 147 | } |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 148 | |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 149 | public Iterable<PrepareDepsOfPatternSkyKeyValue> getValues() { |
| 150 | return values; |
| 151 | } |
| 152 | |
| 153 | public Iterable<PrepareDepsOfPatternSkyKeyException> getExceptions() { |
| 154 | return exceptions; |
| 155 | } |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 156 | } |
| 157 | |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 158 | /** Represents a {@link TargetParsingException} when parsing a target pattern string. */ |
| 159 | public static class PrepareDepsOfPatternSkyKeyException { |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 160 | |
Mark Schaller | e7e8b2a | 2015-07-07 19:31:12 +0000 | [diff] [blame] | 161 | private final TargetParsingException exception; |
| 162 | private final String originalPattern; |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 163 | |
Mark Schaller | e7e8b2a | 2015-07-07 19:31:12 +0000 | [diff] [blame] | 164 | public PrepareDepsOfPatternSkyKeyException(TargetParsingException exception, |
| 165 | String originalPattern) { |
| 166 | this.exception = exception; |
| 167 | this.originalPattern = originalPattern; |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 168 | } |
| 169 | |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 170 | public TargetParsingException getException() { |
| 171 | return exception; |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 172 | } |
| 173 | |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 174 | public String getOriginalPattern() { |
Mark Schaller | e7e8b2a | 2015-07-07 19:31:12 +0000 | [diff] [blame] | 175 | return originalPattern; |
| 176 | } |
| 177 | } |
| 178 | |
nharmata | de0c535 | 2017-07-25 17:39:09 +0200 | [diff] [blame] | 179 | /** |
| 180 | * Represents the successful parsing of a target pattern string into a {@link TargetPatternKey}. |
| 181 | */ |
| 182 | public static class PrepareDepsOfPatternSkyKeyValue { |
Mark Schaller | e7e8b2a | 2015-07-07 19:31:12 +0000 | [diff] [blame] | 183 | |
| 184 | private final TargetPatternKey targetPatternKey; |
| 185 | |
janakr | 5fb2a48 | 2018-03-02 17:48:57 -0800 | [diff] [blame] | 186 | PrepareDepsOfPatternSkyKeyValue(TargetPatternKey targetPatternKey) { |
Mark Schaller | e7e8b2a | 2015-07-07 19:31:12 +0000 | [diff] [blame] | 187 | this.targetPatternKey = targetPatternKey; |
| 188 | } |
| 189 | |
janakr | 5fb2a48 | 2018-03-02 17:48:57 -0800 | [diff] [blame] | 190 | public Key getSkyKey() { |
| 191 | return Key.create(targetPatternKey); |
Mark Schaller | e7e8b2a | 2015-07-07 19:31:12 +0000 | [diff] [blame] | 192 | } |
| 193 | |
janakr | 5fb2a48 | 2018-03-02 17:48:57 -0800 | [diff] [blame] | 194 | @AutoCodec |
| 195 | static class Key extends AbstractSkyKey<TargetPatternKey> { |
| 196 | private static final Interner<Key> interner = BlazeInterners.newWeakInterner(); |
| 197 | |
| 198 | private Key(TargetPatternKey arg) { |
| 199 | super(arg); |
| 200 | } |
| 201 | |
| 202 | @AutoCodec.VisibleForSerialization |
| 203 | @AutoCodec.Instantiator |
| 204 | static Key create(TargetPatternKey arg) { |
| 205 | return interner.intern(new Key(arg)); |
| 206 | } |
| 207 | |
| 208 | TargetPatternKey getTargetPatternKey() { |
| 209 | return arg; |
| 210 | } |
| 211 | |
| 212 | @Override |
| 213 | public SkyFunctionName functionName() { |
| 214 | return SkyFunctions.PREPARE_DEPS_OF_PATTERN; |
| 215 | } |
Mark Schaller | 7b0bc0a | 2015-06-30 23:57:45 +0000 | [diff] [blame] | 216 | } |
| 217 | } |
| 218 | } |