| // Copyright 2018 The Bazel Authors. All rights reserved. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| package com.google.devtools.build.lib.analysis; | |
| import com.google.common.base.Preconditions; | |
| import com.google.common.collect.HashMultimap; | |
| import com.google.common.collect.ImmutableSet; | |
| import com.google.common.collect.SetMultimap; | |
| import com.google.common.collect.Sets; | |
| import com.google.devtools.build.lib.actions.Artifact; | |
| import com.google.devtools.build.lib.cmdline.Label; | |
| import java.util.HashSet; | |
| import java.util.Set; | |
| /** | |
| * Morally a {@link SetMultimap} from artifacts to the labels that own them, which may not be just | |
| * {@link Artifact#getOwnerLabel} depending on the build. Optimizes for artifacts that are owned by | |
| * their {@link Artifact#getOwnerLabel} by storing them separately. | |
| */ | |
| public class ArtifactsToOwnerLabels { | |
| private final SetMultimap<Artifact, Label> artifactToMultipleOrDifferentOwnerLabels; | |
| private final Set<Artifact> artifactsOwnedOnlyByTheirLabels; | |
| private ArtifactsToOwnerLabels( | |
| SetMultimap<Artifact, Label> artifactToMultipleOrDifferentOwnerLabels, | |
| Set<Artifact> artifactsOwnedOnlyByTheirLabels) { | |
| this.artifactToMultipleOrDifferentOwnerLabels = artifactToMultipleOrDifferentOwnerLabels; | |
| this.artifactsOwnedOnlyByTheirLabels = artifactsOwnedOnlyByTheirLabels; | |
| } | |
| public Set<Label> getOwners(Artifact artifact) { | |
| if (artifactsOwnedOnlyByTheirLabels.contains(artifact)) { | |
| Preconditions.checkState( | |
| !artifactToMultipleOrDifferentOwnerLabels.containsKey(artifact), | |
| "Artifact %s incorrectly in multiple categories", | |
| artifact); | |
| Label ownerLabel = artifact.getOwnerLabel(); | |
| if (ownerLabel == null) { | |
| return ImmutableSet.of(); | |
| } | |
| return ImmutableSet.of(ownerLabel); | |
| } | |
| return Preconditions.checkNotNull( | |
| artifactToMultipleOrDifferentOwnerLabels.get(artifact), artifact); | |
| } | |
| public Set<Artifact> getArtifacts() { | |
| return Sets.union( | |
| artifactsOwnedOnlyByTheirLabels, artifactToMultipleOrDifferentOwnerLabels.keySet()); | |
| } | |
| public Builder toBuilder() { | |
| return new Builder( | |
| HashMultimap.create(artifactToMultipleOrDifferentOwnerLabels), | |
| new HashSet<>(artifactsOwnedOnlyByTheirLabels)); | |
| } | |
| static class Builder { | |
| private final SetMultimap<Artifact, Label> artifactToMultipleOrDifferentOwnerLabels; | |
| private final Set<Artifact> artifactsOwnedOnlyByTheirLabels; | |
| Builder() { | |
| this(HashMultimap.create(), new HashSet<>()); | |
| } | |
| private Builder( | |
| SetMultimap<Artifact, Label> artifactToMultipleOrDifferentOwnerLabels, | |
| Set<Artifact> artifactsOwnedOnlyByTheirLabels) { | |
| this.artifactToMultipleOrDifferentOwnerLabels = artifactToMultipleOrDifferentOwnerLabels; | |
| this.artifactsOwnedOnlyByTheirLabels = artifactsOwnedOnlyByTheirLabels; | |
| } | |
| public Builder addArtifact(Artifact artifact) { | |
| if (artifactToMultipleOrDifferentOwnerLabels.containsKey(artifact)) { | |
| Label ownerLabel = artifact.getOwnerLabel(); | |
| if (ownerLabel != null) { | |
| artifactToMultipleOrDifferentOwnerLabels.put(artifact, artifact.getOwnerLabel()); | |
| } | |
| } else { | |
| artifactsOwnedOnlyByTheirLabels.add(artifact); | |
| } | |
| return this; | |
| } | |
| public Builder addArtifact(Artifact artifact, Label label) { | |
| Preconditions.checkNotNull(label, artifact); | |
| if (label.equals(artifact.getOwnerLabel())) { | |
| addArtifact(artifact); | |
| } else { | |
| artifactToMultipleOrDifferentOwnerLabels.put(artifact, label); | |
| if (artifactsOwnedOnlyByTheirLabels.remove(artifact)) { | |
| // Redoing this call now that we have a mismatched label will force addition into the | |
| // multimap. | |
| addArtifact(artifact); | |
| } | |
| } | |
| return this; | |
| } | |
| ArtifactsToOwnerLabels build() { | |
| return new ArtifactsToOwnerLabels( | |
| artifactToMultipleOrDifferentOwnerLabels, artifactsOwnedOnlyByTheirLabels); | |
| } | |
| } | |
| } |