blob: 45b71ed7985b3623aa4d5aa93ddcc8bb36c9a8bd [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2015 The Bazel Authors. All rights reserved.
Mark Schaller7b0bc0a2015-06-30 23:57:45 +00002//
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.
14package com.google.devtools.build.lib.skyframe;
15
16import com.google.common.collect.ImmutableList;
janakr5fb2a482018-03-02 17:48:57 -080017import com.google.common.collect.Interner;
wyv630be022021-10-04 07:55:36 -070018import com.google.devtools.build.lib.cmdline.SignedTargetPattern;
Mark Schaller7b0bc0a2015-06-30 23:57:45 +000019import com.google.devtools.build.lib.cmdline.TargetParsingException;
jcatercecb3a82018-05-01 14:37:48 -070020import com.google.devtools.build.lib.cmdline.TargetPattern;
Mark Schallere7e8b2a2015-07-07 19:31:12 +000021import com.google.devtools.build.lib.cmdline.TargetPattern.Type;
janakr5fb2a482018-03-02 17:48:57 -080022import com.google.devtools.build.lib.concurrent.BlazeInterners;
Mark Schaller7b0bc0a2015-06-30 23:57:45 +000023import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
Mark Schallerd7311e02015-07-07 16:36:09 +000024import com.google.devtools.build.lib.pkgcache.FilteringPolicies;
Googler35b92d02020-08-03 07:42:11 -070025import com.google.devtools.build.lib.server.FailureDetails.TargetPatterns;
Mark Schaller7b0bc0a2015-06-30 23:57:45 +000026import com.google.devtools.build.lib.skyframe.TargetPatternValue.TargetPatternKey;
shahan09765a82018-02-27 11:54:45 -080027import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
Googler41797b62021-11-19 12:07:05 -080028import com.google.devtools.build.lib.skyframe.serialization.autocodec.SerializationConstant;
janakra3652a32020-09-10 12:05:20 -070029import com.google.devtools.build.lib.vfs.PathFragment;
janakr5fb2a482018-03-02 17:48:57 -080030import com.google.devtools.build.skyframe.AbstractSkyKey;
31import com.google.devtools.build.skyframe.SkyFunctionName;
Mark Schaller7b0bc0a2015-06-30 23:57:45 +000032import com.google.devtools.build.skyframe.SkyValue;
Mark Schaller7b0bc0a2015-06-30 23:57:45 +000033import 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 Schallerf3ec7c42015-08-21 17:44:41 +000040 * <p>Because the returned value is always equal to objects that share its type, this value and the
Mark Schaller7b0bc0a2015-06-30 23:57:45 +000041 * {@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 */
47public class PrepareDepsOfPatternValue implements SkyValue {
Mark Schallerf3ec7c42015-08-21 17:44:41 +000048 // Note that this value does not guarantee singleton-like reference equality because we use Java
49 // deserialization. Java deserialization can create other instances.
Googler41797b62021-11-19 12:07:05 -080050 @SerializationConstant
Mark Schaller7b0bc0a2015-06-30 23:57:45 +000051 public static final PrepareDepsOfPatternValue INSTANCE = new PrepareDepsOfPatternValue();
52
53 private PrepareDepsOfPatternValue() {
54 }
55
Mark Schallerf3ec7c42015-08-21 17:44:41 +000056 @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 Schaller7b0bc0a2015-06-30 23:57:45 +000066 /**
janakra3652a32020-09-10 12:05:20 -070067 * 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 Schaller7b0bc0a2015-06-30 23:57:45 +000077 *
janakra3652a32020-09-10 12:05:20 -070078 * <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 Schaller7b0bc0a2015-06-30 23:57:45 +000083 *
Mark Schallere7e8b2a2015-07-07 19:31:12 +000084 * @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 Schaller7b0bc0a2015-06-30 23:57:45 +000086 * @param offset The offset to apply to relative target patterns.
87 */
88 @ThreadSafe
nharmatade0c5352017-07-25 17:39:09 +020089 public static PrepareDepsOfPatternSkyKeysAndExceptions keys(
janakra3652a32020-09-10 12:05:20 -070090 List<String> patterns, PathFragment offset) {
nharmatade0c5352017-07-25 17:39:09 +020091 ImmutableList.Builder<PrepareDepsOfPatternSkyKeyValue> resultValuesBuilder =
92 ImmutableList.builder();
93 ImmutableList.Builder<PrepareDepsOfPatternSkyKeyException> resultExceptionsBuilder =
94 ImmutableList.builder();
wyv630be022021-10-04 07:55:36 -070095 TargetPattern.Parser parser = TargetPattern.mainRepoParser(offset);
nharmatade0c5352017-07-25 17:39:09 +020096 ImmutableList.Builder<TargetPatternKey> targetPatternKeysBuilder = ImmutableList.builder();
wyv630be022021-10-04 07:55:36 -070097 for (String pattern : patterns) {
nharmatade0c5352017-07-25 17:39:09 +020098 try {
wyv630be022021-10-04 07:55:36 -070099 targetPatternKeysBuilder.add(
100 TargetPatternValue.key(
101 SignedTargetPattern.parse(pattern, parser), FilteringPolicies.NO_FILTER));
nharmatade0c5352017-07-25 17:39:09 +0200102 } catch (TargetParsingException e) {
wyv630be022021-10-04 07:55:36 -0700103 resultExceptionsBuilder.add(new PrepareDepsOfPatternSkyKeyException(e, pattern));
nharmatade0c5352017-07-25 17:39:09 +0200104 }
105 }
Mark Schallere7e8b2a2015-07-07 19:31:12 +0000106 // 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.
nharmatade0c5352017-07-25 17:39:09 +0200110 Iterable<TargetPatternKey> combinedTargetPatternKeys =
shreyax432b2532019-01-23 11:16:07 -0800111 TargetPatternValue.combineTargetsBelowDirectoryWithNegativePatterns(
112 targetPatternKeysBuilder.build(), /*excludeSingleTargets=*/ false);
nharmatade0c5352017-07-25 17:39:09 +0200113 for (TargetPatternKey targetPatternKey : combinedTargetPatternKeys) {
114 if (targetPatternKey.isNegative()
jcatercecb3a82018-05-01 14:37:48 -0700115 && !targetPatternKey
116 .getParsedPattern()
117 .getType()
118 .equals(TargetPattern.Type.TARGETS_BELOW_DIRECTORY)) {
nharmatade0c5352017-07-25 17:39:09 +0200119 resultExceptionsBuilder.add(
120 new PrepareDepsOfPatternSkyKeyException(
121 new TargetParsingException(
122 "Negative target patterns of types other than \"targets below directory\""
Googler35b92d02020-08-03 07:42:11 -0700123 + " are not permitted.",
124 TargetPatterns.Code.NEGATIVE_TARGET_PATTERN_NOT_ALLOWED),
125 targetPatternKey.toString()));
nharmatade0c5352017-07-25 17:39:09 +0200126 } else {
127 resultValuesBuilder.add(new PrepareDepsOfPatternSkyKeyValue(targetPatternKey));
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000128 }
129 }
nharmatade0c5352017-07-25 17:39:09 +0200130 return new PrepareDepsOfPatternSkyKeysAndExceptions(
131 resultValuesBuilder.build(), resultExceptionsBuilder.build());
Mark Schallere7e8b2a2015-07-07 19:31:12 +0000132 }
133
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000134 /**
nharmatade0c5352017-07-25 17:39:09 +0200135 * A pair of {@link Iterable<PrepareDepsOfPatternSkyKeyValue>} and
136 * {@link Iterable<PrepareDepsOfPatternSkyKeyException>}.
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000137 */
nharmatade0c5352017-07-25 17:39:09 +0200138 public static class PrepareDepsOfPatternSkyKeysAndExceptions {
139 private final Iterable<PrepareDepsOfPatternSkyKeyValue> values;
140 private final Iterable<PrepareDepsOfPatternSkyKeyException> exceptions;
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000141
nharmatade0c5352017-07-25 17:39:09 +0200142 public PrepareDepsOfPatternSkyKeysAndExceptions(
143 Iterable<PrepareDepsOfPatternSkyKeyValue> values,
144 Iterable<PrepareDepsOfPatternSkyKeyException> exceptions) {
145 this.values = values;
146 this.exceptions = exceptions;
147 }
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000148
nharmatade0c5352017-07-25 17:39:09 +0200149 public Iterable<PrepareDepsOfPatternSkyKeyValue> getValues() {
150 return values;
151 }
152
153 public Iterable<PrepareDepsOfPatternSkyKeyException> getExceptions() {
154 return exceptions;
155 }
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000156 }
157
nharmatade0c5352017-07-25 17:39:09 +0200158 /** Represents a {@link TargetParsingException} when parsing a target pattern string. */
159 public static class PrepareDepsOfPatternSkyKeyException {
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000160
Mark Schallere7e8b2a2015-07-07 19:31:12 +0000161 private final TargetParsingException exception;
162 private final String originalPattern;
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000163
Mark Schallere7e8b2a2015-07-07 19:31:12 +0000164 public PrepareDepsOfPatternSkyKeyException(TargetParsingException exception,
165 String originalPattern) {
166 this.exception = exception;
167 this.originalPattern = originalPattern;
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000168 }
169
nharmatade0c5352017-07-25 17:39:09 +0200170 public TargetParsingException getException() {
171 return exception;
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000172 }
173
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000174 public String getOriginalPattern() {
Mark Schallere7e8b2a2015-07-07 19:31:12 +0000175 return originalPattern;
176 }
177 }
178
nharmatade0c5352017-07-25 17:39:09 +0200179 /**
180 * Represents the successful parsing of a target pattern string into a {@link TargetPatternKey}.
181 */
182 public static class PrepareDepsOfPatternSkyKeyValue {
Mark Schallere7e8b2a2015-07-07 19:31:12 +0000183
184 private final TargetPatternKey targetPatternKey;
185
janakr5fb2a482018-03-02 17:48:57 -0800186 PrepareDepsOfPatternSkyKeyValue(TargetPatternKey targetPatternKey) {
Mark Schallere7e8b2a2015-07-07 19:31:12 +0000187 this.targetPatternKey = targetPatternKey;
188 }
189
janakr5fb2a482018-03-02 17:48:57 -0800190 public Key getSkyKey() {
191 return Key.create(targetPatternKey);
Mark Schallere7e8b2a2015-07-07 19:31:12 +0000192 }
193
janakr5fb2a482018-03-02 17:48:57 -0800194 @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 Schaller7b0bc0a2015-06-30 23:57:45 +0000216 }
217 }
218}