// Copyright 2015 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.skyframe; import com.google.common.collect.ImmutableList; import com.google.devtools.build.lib.cmdline.TargetParsingException; import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe; import com.google.devtools.build.lib.pkgcache.FilteringPolicy; import com.google.devtools.build.lib.skyframe.TargetPatternValue.TargetPatternKey; import com.google.devtools.build.lib.skyframe.TargetPatternValue.TargetPatternSkyKeyOrException; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; import java.util.List; /** * The value returned by {@link PrepareDepsOfPatternFunction}. Because that function is * invoked only for its side effect (i.e. ensuring the graph contains targets matching the * pattern and its transitive dependencies), this value carries no information. * *

Because the returned value is always the same object, this value and the * {@link PrepareDepsOfPatternFunction} which computes it are incompatible with change pruning. It * should only be requested by consumers who do not require reevaluation when * {@link PrepareDepsOfPatternFunction} is reevaluated. Safe consumers include, e.g., top-level * consumers, and other functions which invoke {@link PrepareDepsOfPatternFunction} solely for its * side-effects. */ public class PrepareDepsOfPatternValue implements SkyValue { public static final PrepareDepsOfPatternValue INSTANCE = new PrepareDepsOfPatternValue(); private PrepareDepsOfPatternValue() { } /** * Returns an iterable of {@link PrepareDepsOfPatternSkyKeyOrException}, with * {@link TargetPatternKey} arguments. If a provided pattern fails to parse, an element in the * returned iterable will throw when its * {@link PrepareDepsOfPatternSkyKeyOrException#getSkyKey} method is called and will return the * failing pattern when its {@link PrepareDepsOfPatternSkyKeyOrException#getOriginalPattern} * method is called. * *

There may be fewer returned elements than patterns provided as input. This function may * combine patterns to return an iterable of SkyKeys that is equivalent but more efficient to * evaluate, and will omit SkyKeys associated with negative patterns. * * @param patterns The list of patterns, e.g. "-foo/biz...". If a pattern's first character is * "-", it is treated as a negative pattern. * @param policy The filtering policy, e.g. "only return test targets" * @param offset The offset to apply to relative target patterns. */ @ThreadSafe public static Iterable keys(List patterns, FilteringPolicy policy, String offset) { Iterable keysMaybe = TargetPatternValue.keys(patterns, policy, offset); ImmutableList.Builder builder = ImmutableList.builder(); for (TargetPatternSkyKeyOrException keyMaybe : keysMaybe) { try { SkyKey skyKey = keyMaybe.getSkyKey(); if (!((TargetPatternKey) skyKey.argument()).isNegative()) { builder.add(new PrepareDepsOfPatternSkyKeyOrExceptionImpl(keyMaybe)); } } catch (TargetParsingException e) { // keyMaybe.getSkyKey() may throw TargetParsingException if its corresponding pattern // failed to parse. If so, wrap the exception-holding TargetPatternSkyKeyOrException and // return it, so that our caller can deal with it. builder.add(new PrepareDepsOfPatternSkyKeyOrExceptionImpl(keyMaybe)); } } return builder.build(); } /** * Wrapper for a prepare deps of pattern {@link SkyKey} or the {@link TargetParsingException} * thrown when trying to create it. */ public interface PrepareDepsOfPatternSkyKeyOrException { /** * Returns the stored {@link SkyKey} or throws {@link TargetParsingException} if one was thrown * when creating the key. */ SkyKey getSkyKey() throws TargetParsingException; /** * Returns the pattern that resulted in the stored {@link SkyKey} or {@link * TargetParsingException}. */ String getOriginalPattern(); } /** * Converts from a {@link TargetPatternSkyKeyOrException} to a * {@link PrepareDepsOfPatternSkyKeyOrException}. */ private static class PrepareDepsOfPatternSkyKeyOrExceptionImpl implements PrepareDepsOfPatternSkyKeyOrException { private final TargetPatternSkyKeyOrException wrapped; private PrepareDepsOfPatternSkyKeyOrExceptionImpl(TargetPatternSkyKeyOrException wrapped) { this.wrapped = wrapped; } @Override public SkyKey getSkyKey() throws TargetParsingException { return new SkyKey(SkyFunctions.PREPARE_DEPS_OF_PATTERN, wrapped.getSkyKey().argument()); } @Override public String getOriginalPattern() { return wrapped.getOriginalPattern(); } } }