diff options
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/actions/ActionInputHelper.java')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/actions/ActionInputHelper.java | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ActionInputHelper.java b/src/main/java/com/google/devtools/build/lib/actions/ActionInputHelper.java new file mode 100644 index 0000000000..0fed9283b8 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/actions/ActionInputHelper.java @@ -0,0 +1,160 @@ +// Copyright 2014 Google Inc. 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.actions; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.base.Preconditions; +import com.google.common.collect.Collections2; +import com.google.common.collect.Iterables; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * Helper utility to create ActionInput instances. + */ +public final class ActionInputHelper { + private ActionInputHelper() { + } + + @VisibleForTesting + public static Artifact.MiddlemanExpander actionGraphMiddlemanExpander( + final ActionGraph actionGraph) { + return new Artifact.MiddlemanExpander() { + @Override + public void expand(Artifact mm, Collection<? super Artifact> output) { + // Skyframe is stricter in that it checks that "mm" is a input of the action, because + // it cannot expand arbitrary middlemen without access to a global action graph. + // We could check this constraint here too, but it seems unnecessary. This code is + // going away anyway. + Preconditions.checkArgument(mm.isMiddlemanArtifact(), + "%s is not a middleman artifact", mm); + Action middlemanAction = actionGraph.getGeneratingAction(mm); + Preconditions.checkState(middlemanAction != null, mm); + // TODO(bazel-team): Consider expanding recursively or throwing an exception here. + // Most likely, this code will cause silent errors if we ever have a middleman that + // contains a middleman. + if (middlemanAction.getActionType() == Action.MiddlemanType.AGGREGATING_MIDDLEMAN) { + Artifact.addNonMiddlemanArtifacts(middlemanAction.getInputs(), output, + Functions.<Artifact>identity()); + } + + } + }; + } + + /** + * Most ActionInputs are created and never used again. On the off chance that one is, however, we + * implement equality via path comparison. Since file caches are keyed by ActionInput, equality + * checking does come up. + */ + private static class BasicActionInput implements ActionInput { + private final String path; + public BasicActionInput(String path) { + this.path = Preconditions.checkNotNull(path); + } + + @Override + public String getExecPathString() { + return path; + } + + @Override + public int hashCode() { + return path.hashCode(); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (other == null) { + return false; + } + if (!this.getClass().equals(other.getClass())) { + return false; + } + return this.path.equals(((BasicActionInput) other).path); + } + + @Override + public String toString() { + return "BasicActionInput: " + path; + } + } + + /** + * Creates an ActionInput with just the given relative path and no digest. + * + * @param path the relative path of the input. + * @return a ActionInput. + */ + public static ActionInput fromPath(String path) { + return new BasicActionInput(path); + } + + private static final Function<String, ActionInput> FROM_PATH = + new Function<String, ActionInput>() { + @Override + public ActionInput apply(String path) { + return fromPath(path); + } + }; + + /** + * Creates a sequence of {@link ActionInput}s from a sequence of string paths. + */ + public static Collection<ActionInput> fromPaths(Collection<String> paths) { + return Collections2.transform(paths, FROM_PATH); + } + + /** + * Expands middleman artifacts in a sequence of {@link ActionInput}s. + * + * <p>Non-middleman artifacts are returned untouched. + */ + public static List<ActionInput> expandMiddlemen(Iterable<? extends ActionInput> inputs, + Artifact.MiddlemanExpander middlemanExpander) { + + List<ActionInput> result = new ArrayList<>(); + List<Artifact> containedArtifacts = new ArrayList<>(); + for (ActionInput input : inputs) { + if (!(input instanceof Artifact)) { + result.add(input); + continue; + } + containedArtifacts.add((Artifact) input); + } + Artifact.addExpandedArtifacts(containedArtifacts, result, middlemanExpander); + return result; + } + + /** Formatter for execPath String output. Public because Artifact uses it directly. */ + public static final Function<ActionInput, String> EXEC_PATH_STRING_FORMATTER = + new Function<ActionInput, String>() { + @Override + public String apply(ActionInput input) { + return input.getExecPathString(); + } + }; + + public static Iterable<String> toExecPaths(Iterable<? extends ActionInput> artifacts) { + return Iterables.transform(artifacts, EXEC_PATH_STRING_FORMATTER); + } +} |