| // Copyright 2014 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.config; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.devtools.build.lib.actions.Artifact; |
| import com.google.devtools.build.lib.cmdline.Label; |
| import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; |
| import com.google.devtools.build.lib.util.RegexFilter; |
| import com.google.devtools.build.lib.util.RegexFilter.RegexFilterConverter; |
| import com.google.devtools.common.options.Converter; |
| import com.google.devtools.common.options.OptionsParsingException; |
| import java.io.Serializable; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Objects; |
| |
| /** |
| * Models options that can be added to a command line when a label matches a given {@link |
| * RegexFilter}. |
| */ |
| @AutoCodec |
| public class PerLabelOptions implements Serializable { |
| /** The filter used to match labels */ |
| private final RegexFilter regexFilter; |
| |
| /** The list of options to add when the filter matches a label */ |
| private final List<String> optionsList; |
| |
| /** |
| * Converts a String to a {@link PerLabelOptions} object. The syntax of the |
| * string is {@code regex_filter@option_1,option_2,...,option_n}. Where |
| * regex_filter stands for the String representation of a {@link RegexFilter}, |
| * and {@code option_1} to {@code option_n} stand for arbitrary command line |
| * options. If an option contains a comma it has to be quoted with a |
| * backslash. Options can contain @. Only the first @ is used to split the |
| * string. |
| */ |
| public static class PerLabelOptionsConverter implements Converter<PerLabelOptions> { |
| |
| @Override |
| public PerLabelOptions convert(String input) throws OptionsParsingException { |
| int atIndex = input.indexOf('@'); |
| RegexFilterConverter converter = new RegexFilter.RegexFilterConverter(); |
| if (atIndex < 0) { |
| return new PerLabelOptions(converter.convert(input), ImmutableList.<String> of()); |
| } else { |
| String filterPiece = input.substring(0, atIndex); |
| String optionsPiece = input.substring(atIndex + 1); |
| List<String> optionsList = new ArrayList<>(); |
| for (String option : optionsPiece.split("(?<!\\\\),")) { // Split on ',' but not on '\,' |
| if (option != null && !option.trim().isEmpty()) { |
| optionsList.add(option.replace("\\,", ",")); |
| } |
| } |
| return new PerLabelOptions(converter.convert(filterPiece), optionsList); |
| } |
| } |
| |
| @Override |
| public String getTypeDescription() { |
| return "a comma-separated list of regex expressions with prefix '-' specifying" |
| + " excluded paths followed by an @ and a comma separated list of options"; |
| } |
| } |
| |
| public PerLabelOptions(RegexFilter regexFilter, List<String> optionsList) { |
| this.regexFilter = regexFilter; |
| this.optionsList = optionsList; |
| } |
| |
| /** |
| * @return true if the given label is matched by the {@link RegexFilter}. |
| */ |
| public boolean isIncluded(Label label) { |
| return regexFilter.isIncluded(label.toString()); |
| } |
| |
| /** |
| * @return true if the execution path (which includes the base name of the file) |
| * of the given file is matched by the {@link RegexFilter}. |
| */ |
| public boolean isIncluded(Artifact artifact) { |
| return regexFilter.isIncluded(artifact.getExecPathString()); |
| } |
| |
| /** |
| * Returns the list of options to add to a command line. |
| */ |
| public List<String> getOptions() { |
| return optionsList; |
| } |
| |
| RegexFilter getRegexFilter() { |
| return regexFilter; |
| } |
| |
| @Override |
| public String toString() { |
| return regexFilter + " Options: " + optionsList; |
| } |
| |
| @Override |
| public boolean equals(Object other) { |
| PerLabelOptions otherOptions = |
| other instanceof PerLabelOptions ? (PerLabelOptions) other : null; |
| return this == other || (otherOptions != null && |
| this.regexFilter.equals(otherOptions.regexFilter) && |
| this.optionsList.equals(otherOptions.optionsList)); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(regexFilter, optionsList); |
| } |
| } |