blob: 3b4b7687933ea38805ced7e73ee70b0b912bdfbf [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;
17import com.google.common.collect.ImmutableSet;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000018import com.google.devtools.build.lib.cmdline.Label;
Kristina Chodorow73fa2032015-08-28 17:57:46 +000019import com.google.devtools.build.lib.cmdline.PackageIdentifier;
Kristina Chodorowec5c07a2016-01-25 17:12:29 +000020import com.google.devtools.build.lib.cmdline.RepositoryName;
Mark Schaller7b0bc0a2015-06-30 23:57:45 +000021import com.google.devtools.build.lib.cmdline.ResolvedTargets;
22import com.google.devtools.build.lib.cmdline.TargetParsingException;
23import com.google.devtools.build.lib.cmdline.TargetPattern;
24import com.google.devtools.build.lib.cmdline.TargetPatternResolver;
25import com.google.devtools.build.lib.events.Event;
26import com.google.devtools.build.lib.packages.NoSuchPackageException;
27import com.google.devtools.build.lib.packages.NoSuchTargetException;
28import com.google.devtools.build.lib.packages.NoSuchThingException;
29import com.google.devtools.build.lib.packages.Package;
Mark Schaller7b0bc0a2015-06-30 23:57:45 +000030import com.google.devtools.build.lib.packages.Target;
31import com.google.devtools.build.lib.pkgcache.FilteringPolicies;
32import com.google.devtools.build.lib.pkgcache.FilteringPolicy;
33import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
34import com.google.devtools.build.lib.pkgcache.TargetPatternResolverUtil;
Kristina Chodorow734e7f72016-01-29 15:04:31 +000035import com.google.devtools.build.lib.rules.repository.RepositoryDirectoryValue;
Mark Schaller7b0bc0a2015-06-30 23:57:45 +000036import com.google.devtools.build.lib.skyframe.EnvironmentBackedRecursivePackageProvider.MissingDepException;
Janak Ramakrishnan5b5f22a2016-01-07 17:07:29 +000037import com.google.devtools.build.lib.util.BatchCallback;
Janak Ramakrishnan006ab492016-01-07 17:39:41 +000038import com.google.devtools.build.lib.util.BatchCallback.NullCallback;
Mark Schaller6df81792015-12-10 18:47:47 +000039import com.google.devtools.build.lib.util.Preconditions;
Mark Schaller7b0bc0a2015-06-30 23:57:45 +000040import com.google.devtools.build.lib.vfs.Path;
41import com.google.devtools.build.lib.vfs.PathFragment;
42import com.google.devtools.build.lib.vfs.RootedPath;
43import com.google.devtools.build.skyframe.SkyFunction;
44import com.google.devtools.build.skyframe.SkyFunctionException;
45import com.google.devtools.build.skyframe.SkyKey;
46import com.google.devtools.build.skyframe.SkyValue;
Lukacs Berkic7106d42015-10-15 07:45:54 +000047import java.util.ArrayList;
48import java.util.List;
Mark Schaller7b0bc0a2015-06-30 23:57:45 +000049import java.util.concurrent.atomic.AtomicReference;
Mark Schaller7b0bc0a2015-06-30 23:57:45 +000050import javax.annotation.Nullable;
51
52/**
53 * PrepareDepsOfPatternFunction ensures the graph loads targets matching the pattern and its
54 * transitive dependencies.
55 */
56public class PrepareDepsOfPatternFunction implements SkyFunction {
57
58 private final AtomicReference<PathPackageLocator> pkgPath;
59
60 public PrepareDepsOfPatternFunction(AtomicReference<PathPackageLocator> pkgPath) {
61 this.pkgPath = pkgPath;
62 }
63
64 @Nullable
65 @Override
66 public SkyValue compute(SkyKey key, Environment env)
67 throws SkyFunctionException, InterruptedException {
68 TargetPatternValue.TargetPatternKey patternKey =
69 ((TargetPatternValue.TargetPatternKey) key.argument());
Mark Schallerd7311e02015-07-07 16:36:09 +000070
71 // DepsOfPatternPreparer below expects to be able to ignore the filtering policy from the
72 // TargetPatternKey, which should be valid because PrepareDepsOfPatternValue.keys
73 // unconditionally creates TargetPatternKeys with the NO_FILTER filtering policy. (Compare
74 // with SkyframeTargetPatternEvaluator, which can create TargetPatternKeys with other
75 // filtering policies like FILTER_TESTS or FILTER_MANUAL.) This check makes sure that the
76 // key's filtering policy is NO_FILTER as expected.
77 Preconditions.checkState(patternKey.getPolicy().equals(FilteringPolicies.NO_FILTER),
78 patternKey.getPolicy());
79
Nathan Harmata4d89d112016-04-17 02:46:15 +000080 TargetPattern parsedPattern = patternKey.getParsedPattern();
81
82 BlacklistedPackagePrefixesValue blacklist =
83 (BlacklistedPackagePrefixesValue) env.getValue(BlacklistedPackagePrefixesValue.key());
84 if (blacklist == null) {
85 return null;
86 }
87 ImmutableSet<PathFragment> subdirectoriesToExclude =
88 patternKey.getAllSubdirectoriesToExclude(blacklist.getPatterns());
89
90 DepsOfPatternPreparer preparer = new DepsOfPatternPreparer(env, pkgPath.get());
91
Mark Schaller7b0bc0a2015-06-30 23:57:45 +000092 try {
Eric Fellheimer6f8b7ce2016-01-29 00:15:44 +000093 parsedPattern.eval(
Nathan Harmata4d89d112016-04-17 02:46:15 +000094 preparer,
95 subdirectoriesToExclude,
96 NullCallback.<Void>instance(),
97 RuntimeException.class);
Mark Schaller7b0bc0a2015-06-30 23:57:45 +000098 } catch (TargetParsingException e) {
99 throw new PrepareDepsOfPatternFunctionException(e);
100 } catch (MissingDepException e) {
101 // The DepsOfPatternPreparer constructed above might throw MissingDepException to signal
102 // when it has a dependency on a missing Environment value.
103 return null;
104 }
105 return PrepareDepsOfPatternValue.INSTANCE;
106 }
107
108 @Nullable
109 @Override
110 public String extractTag(SkyKey skyKey) {
111 return null;
112 }
113
114 /**
115 * Used to declare all the exception types that can be wrapped in the exception thrown by {@link
116 * PrepareDepsOfPatternFunction#compute}.
117 */
118 private static final class PrepareDepsOfPatternFunctionException extends SkyFunctionException {
119
120 public PrepareDepsOfPatternFunctionException(TargetParsingException e) {
121 super(e, Transience.PERSISTENT);
122 }
123 }
124
125 /**
Ulf Adams3ab82f72015-09-04 12:10:53 +0000126 * A {@link TargetPatternResolver} backed by an {@link
127 * com.google.devtools.build.skyframe.SkyFunction.Environment} whose methods do not actually
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000128 * return resolved targets, but that ensures the graph loads the matching targets <b>and</b> their
129 * transitive dependencies. Its methods may throw {@link MissingDepException} if the package
130 * values this depends on haven't been calculated and added to its environment.
131 */
Nathan Harmata7a5a2362017-03-08 22:42:01 +0000132 static class DepsOfPatternPreparer extends TargetPatternResolver<Void> {
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000133
134 private final EnvironmentBackedRecursivePackageProvider packageProvider;
135 private final Environment env;
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000136 private final PathPackageLocator pkgPath;
137
Mark Schallerd7311e02015-07-07 16:36:09 +0000138 public DepsOfPatternPreparer(Environment env, PathPackageLocator pkgPath) {
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000139 this.env = env;
140 this.packageProvider = new EnvironmentBackedRecursivePackageProvider(env);
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000141 this.pkgPath = pkgPath;
142 }
143
144 @Override
145 public void warn(String msg) {
146 env.getListener().handle(Event.warn(msg));
147 }
148
149 @Override
Lukacs Berki960dc272015-09-24 07:48:36 +0000150 public Void getTargetOrNull(Label label) throws InterruptedException {
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000151 // Note:
152 // This method is used in just one place, TargetPattern.TargetsInPackage#getWildcardConflict.
153 // Returning null tells #getWildcardConflict that there is not a target with a name like
154 // "all" or "all-targets", which means that TargetPattern.TargetsInPackage will end up
155 // calling DepsOfTargetPreparer#getTargetsInPackage.
156 // TODO (bazel-team): Consider replacing this with an isTarget method on the interface.
157 return null;
158 }
159
160 @Override
Lukacs Berki960dc272015-09-24 07:48:36 +0000161 public ResolvedTargets<Void> getExplicitTarget(Label label)
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000162 throws TargetParsingException, InterruptedException {
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000163 try {
164 Target target = packageProvider.getTarget(env.getListener(), label);
Mark Schaller8ff5b3c2015-07-29 17:32:11 +0000165 SkyKey key = TransitiveTraversalValue.key(target.getLabel());
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000166 SkyValue token =
167 env.getValueOrThrow(key, NoSuchPackageException.class, NoSuchTargetException.class);
168 if (token == null) {
169 throw new MissingDepException();
170 }
171 return ResolvedTargets.empty();
172 } catch (NoSuchThingException e) {
173 throw new TargetParsingException(e.getMessage(), e);
174 }
175 }
176
177 @Override
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000178 public ResolvedTargets<Void> getTargetsInPackage(
179 String originalPattern, PackageIdentifier packageIdentifier, boolean rulesOnly)
180 throws TargetParsingException, InterruptedException {
Mark Schallerd7311e02015-07-07 16:36:09 +0000181 FilteringPolicy policy =
182 rulesOnly ? FilteringPolicies.RULES_ONLY : FilteringPolicies.NO_FILTER;
Lukacs Berki10e3b2b2015-09-22 07:58:20 +0000183 return getTargetsInPackage(originalPattern, packageIdentifier, policy);
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000184 }
185
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000186 private ResolvedTargets<Void> getTargetsInPackage(
187 String originalPattern, PackageIdentifier packageIdentifier, FilteringPolicy policy)
188 throws TargetParsingException, InterruptedException {
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000189 try {
Lukacs Berki10e3b2b2015-09-22 07:58:20 +0000190 Package pkg = packageProvider.getPackage(env.getListener(), packageIdentifier);
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000191 ResolvedTargets<Target> packageTargets =
192 TargetPatternResolverUtil.resolvePackageTargets(pkg, policy);
193 ImmutableList.Builder<SkyKey> builder = ImmutableList.builder();
194 for (Target target : packageTargets.getTargets()) {
Mark Schaller8ff5b3c2015-07-29 17:32:11 +0000195 builder.add(TransitiveTraversalValue.key(target.getLabel()));
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000196 }
197 ImmutableList<SkyKey> skyKeys = builder.build();
198 env.getValuesOrThrow(skyKeys, NoSuchPackageException.class, NoSuchTargetException.class);
199 if (env.valuesMissing()) {
200 throw new MissingDepException();
201 }
202 return ResolvedTargets.empty();
203 } catch (NoSuchThingException e) {
204 String message = TargetPatternResolverUtil.getParsingErrorMessage(
205 "package contains errors", originalPattern);
206 throw new TargetParsingException(message, e);
207 }
208 }
209
210 @Override
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000211 public boolean isPackage(PackageIdentifier packageIdentifier) throws InterruptedException {
Lukacs Berki10e3b2b2015-09-22 07:58:20 +0000212 return packageProvider.isPackage(env.getListener(), packageIdentifier);
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000213 }
214
215 @Override
216 public String getTargetKind(Void target) {
217 // Note:
218 // This method is used in just one place, TargetPattern.TargetsInPackage#getWildcardConflict.
219 // Because DepsOfPatternPreparer#getTargetOrNull always returns null, this method is never
220 // called.
221 throw new UnsupportedOperationException();
222 }
223
224 @Override
Janak Ramakrishnan5b5f22a2016-01-07 17:07:29 +0000225 public <E extends Exception> void findTargetsBeneathDirectory(
226 RepositoryName repository,
227 String originalPattern,
228 String directory,
229 boolean rulesOnly,
Janak Ramakrishnan3d9441b2016-01-13 17:38:29 +0000230 ImmutableSet<PathFragment> excludedSubdirectories,
Nathan Harmata7a5a2362017-03-08 22:42:01 +0000231 BatchCallback<Void, E> callback,
232 Class<E> exceptionClass)
Janak Ramakrishnan5b5f22a2016-01-07 17:07:29 +0000233 throws TargetParsingException, E, InterruptedException {
Mark Schallerd7311e02015-07-07 16:36:09 +0000234 FilteringPolicy policy =
235 rulesOnly ? FilteringPolicies.RULES_ONLY : FilteringPolicies.NO_FILTER;
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000236 PathFragment pathFragment = TargetPatternResolverUtil.getPathFragment(directory);
Lukacs Berkic7106d42015-10-15 07:45:54 +0000237 List<Path> roots = new ArrayList<>();
Brian Silvermand7d6d622016-03-17 09:53:39 +0000238 if (repository.isMain()) {
Lukacs Berkic7106d42015-10-15 07:45:54 +0000239 roots.addAll(pkgPath.getPathEntries());
240 } else {
Kristina Chodorow734e7f72016-01-29 15:04:31 +0000241 RepositoryDirectoryValue repositoryValue =
242 (RepositoryDirectoryValue) env.getValue(RepositoryDirectoryValue.key(repository));
Lukacs Berkic7106d42015-10-15 07:45:54 +0000243 if (repositoryValue == null) {
244 throw new MissingDepException();
245 }
246
247 roots.add(repositoryValue.getPath());
248 }
249
250 for (Path root : roots) {
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000251 RootedPath rootedPath = RootedPath.toRootedPath(root, pathFragment);
Janak Ramakrishnan532697f2016-01-20 23:53:44 +0000252 env.getValues(
253 ImmutableList.of(
Janak Ramakrishnan3d9441b2016-01-13 17:38:29 +0000254 PrepareDepsOfTargetsUnderDirectoryValue.key(
Janak Ramakrishnan532697f2016-01-20 23:53:44 +0000255 repository, rootedPath, excludedSubdirectories, policy),
256 CollectPackagesUnderDirectoryValue.key(
257 repository, rootedPath, excludedSubdirectories)));
258 if (env.valuesMissing()) {
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000259 throw new MissingDepException();
260 }
261 }
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000262 }
Mark Schaller7b0bc0a2015-06-30 23:57:45 +0000263 }
264}