blob: 638b078e2096ea1f1c32e9c0a9c1b5b6d76ae71a [file] [log] [blame]
// 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.
*
* <p>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.
*
* <p>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<PrepareDepsOfPatternSkyKeyOrException> keys(List<String> patterns,
FilteringPolicy policy, String offset) {
Iterable<TargetPatternSkyKeyOrException> keysMaybe =
TargetPatternValue.keys(patterns, policy, offset);
ImmutableList.Builder<PrepareDepsOfPatternSkyKeyOrException> 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();
}
}
}