blob: 3d0acf06afb55ae9601cb552838f8d24df9d1ade [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2015 The Bazel Authors. All rights reserved.
Marian Loburbe3171e2015-06-26 16:03:14 +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
Marian Loburbe3171e2015-06-26 16:03:14 +000016import com.google.common.collect.Maps;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000017import com.google.devtools.build.lib.cmdline.Label;
Kristina Chodorow73fa2032015-08-28 17:57:46 +000018import com.google.devtools.build.lib.cmdline.PackageIdentifier;
Marian Loburbe3171e2015-06-26 16:03:14 +000019import com.google.devtools.build.lib.cmdline.ResolvedTargets;
20import com.google.devtools.build.lib.cmdline.TargetParsingException;
Marian Loburbe3171e2015-06-26 16:03:14 +000021import com.google.devtools.build.lib.packages.NoSuchTargetException;
22import com.google.devtools.build.lib.packages.Package;
Marian Loburbe3171e2015-06-26 16:03:14 +000023import com.google.devtools.build.lib.packages.Target;
Mark Schaller6df81792015-12-10 18:47:47 +000024import com.google.devtools.build.lib.util.Preconditions;
Marian Loburbe3171e2015-06-26 16:03:14 +000025import com.google.devtools.build.skyframe.WalkableGraph;
Marian Loburbe3171e2015-06-26 16:03:14 +000026import java.util.HashSet;
27import java.util.Map;
28import java.util.Set;
29
30/**
31 * This class encapsulates logic behind computing final target set based on separate results from a
32 * list of target patterns (eg, //foo:all -//bar/... //foo:test).
33 */
34abstract class TargetPatternsResultBuilder {
35 private Map<PackageIdentifier, Package> packages = null;
36 private boolean hasError = false;
37
38 /**
39 * Sets that there was an error, during evaluation.
40 */
41 public void setError() {
42 hasError = true;
43 }
44
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +000045 /** Returns final set of targets and sets error flag if required. */
46 public ResolvedTargets<Target> build(WalkableGraph walkableGraph)
47 throws TargetParsingException, InterruptedException {
Marian Loburbe3171e2015-06-26 16:03:14 +000048 precomputePackages(walkableGraph);
49 ResolvedTargets.Builder<Target> resolvedTargetsBuilder = buildInternal();
50 if (hasError) {
51 resolvedTargetsBuilder.setError();
52 }
53 return resolvedTargetsBuilder.build();
54 }
55
56 /**
57 * Transforms {@code ResolvedTargets<Label>} to {@code ResolvedTargets<Target>}. Note that this
58 * method is using information about packages, so {@link #precomputePackages} has to be called
59 * before this method.
60 */
61 protected ResolvedTargets.Builder<Target> transformLabelsIntoTargets(
62 ResolvedTargets<Label> resolvedLabels) {
63 // precomputePackages has to be called before this method.
64 ResolvedTargets.Builder<Target> resolvedTargetsBuilder = ResolvedTargets.builder();
65 Preconditions.checkNotNull(packages);
66 for (Label label : resolvedLabels.getTargets()) {
67 resolvedTargetsBuilder.add(getExistingTarget(label));
68 }
69 for (Label label : resolvedLabels.getFilteredTargets()) {
70 resolvedTargetsBuilder.remove(getExistingTarget(label));
71 }
72 return resolvedTargetsBuilder;
73 }
74
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +000075 private void precomputePackages(WalkableGraph walkableGraph) throws InterruptedException {
Marian Loburbe3171e2015-06-26 16:03:14 +000076 Set<PackageIdentifier> packagesToRequest = getPackagesIdentifiers();
77 packages = Maps.newHashMapWithExpectedSize(packagesToRequest.size());
78 for (PackageIdentifier pkgIdentifier : packagesToRequest) {
79 packages.put(pkgIdentifier, findPackageInGraph(pkgIdentifier, walkableGraph));
80 }
81 }
82
83 private Target getExistingTarget(Label label) {
84 Package pkg = Preconditions.checkNotNull(packages.get(label.getPackageIdentifier()), label);
85 try {
86 return pkg.getTarget(label.getName());
87 } catch (NoSuchTargetException e) {
88 // This exception should not raise, because we are processing it during TargetPatternValues
89 // evaluation in SkyframeTargetPatternEvaluator#parseTargetPatternKeys and values with errors
90 // are not added to final result.
91 throw new IllegalStateException(e);
92 }
93 }
94
95 private Set<PackageIdentifier> getPackagesIdentifiers() {
96 Set<PackageIdentifier> packagesIdentifiers = new HashSet<>();
97 for (Label label : getLabels()) {
98 packagesIdentifiers.add(label.getPackageIdentifier());
99 }
100 return packagesIdentifiers;
101 }
102
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000103 private static Package findPackageInGraph(
104 PackageIdentifier pkgIdentifier, WalkableGraph walkableGraph) throws InterruptedException {
Janak Ramakrishnan0a4c6e42015-09-17 00:37:58 +0000105 return Preconditions.checkNotNull(
106 ((PackageValue) walkableGraph.getValue(PackageValue.key(pkgIdentifier))), pkgIdentifier)
107 .getPackage();
Marian Loburbe3171e2015-06-26 16:03:14 +0000108 }
109
110 /**
111 * Adds the result from expansion of positive target pattern (eg, "//foo:all").
112 */
113 abstract void addLabelsOfNegativePattern(ResolvedTargets<Label> labels);
114
115 /**
116 * Adds the result from expansion of negative target pattern (eg, "-//foo:all").
117 */
118 abstract void addLabelsOfPositivePattern(ResolvedTargets<Label> labels);
119
120 /**
121 * Returns {@code ResolvedTargets.Builder<Target>} with final set of targets. Note that this
122 * method doesn't set error flag in result.
123 */
124 abstract ResolvedTargets.Builder<Target> buildInternal() throws TargetParsingException;
125
126 /**
127 * Returns target labels from all individual results.
128 */
129 protected abstract Iterable<Label> getLabels();
130}