| // Copyright 2019 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.outputfilter; |
| |
| import com.google.common.base.Joiner; |
| import com.google.common.collect.ImmutableSortedSet; |
| import com.google.devtools.build.lib.cmdline.Label; |
| import com.google.devtools.build.lib.events.OutputFilter; |
| import com.google.devtools.build.lib.events.OutputFilter.RegexOutputFilter; |
| import com.google.devtools.common.options.EnumConverter; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.SortedSet; |
| import java.util.regex.Pattern; |
| |
| /** |
| * Implementation of various settings for the {@code --auto_output_filter} |
| * option. |
| * |
| * <p>Note that any actions owned by the system owner (typically just the build info |
| * action) are treated specially: They are not filtered out by these auto filters. |
| */ |
| public enum AutoOutputFilter { |
| /** |
| * Generates an empty output filter (i.e. one that matches everything). |
| */ |
| NONE { |
| @Override |
| public OutputFilter getFilter(Iterable<Label> targets) { |
| return OutputFilter.OUTPUT_EVERYTHING; |
| } |
| }, |
| |
| /** |
| * Generates an output filter that matches nothing. |
| */ |
| ALL { |
| @Override |
| public OutputFilter getFilter(Iterable<Label> targets) { |
| return OutputFilter.OUTPUT_NOTHING; |
| } |
| }, |
| |
| /** |
| * Generates an output filter that matches all targets that are in the same |
| * package as a target on the command line. {@code //java/foo} and |
| * {@code //javatests/foo} are treated like a single package. |
| */ |
| PACKAGES { |
| @Override |
| public OutputFilter getFilter(Iterable<Label> targets) { |
| Pattern pattern = Pattern.compile(SYSTEM_ACTION_REGEX + "|" |
| + "^//" + getPkgRegex(getPackages(targets)) + ":"); |
| return RegexOutputFilter.forPattern(pattern); |
| } |
| }, |
| |
| /** |
| * Generates an output filter that matches all targets that are in the same |
| * package or in a subpackage of a target on the command line. |
| * {@code //java/foo} and {@code //javatests/foo} are treated like a single |
| * package. |
| */ |
| SUBPACKAGES { |
| @Override |
| public OutputFilter getFilter(Iterable<Label> targets) { |
| List<String> packages = new ArrayList<>(); |
| |
| String previous = null; |
| for (String pkg : getPackages(targets)) { |
| if (previous != null && pkg.startsWith(previous + "/")) { |
| // We already have a super-package in the list, so this package does |
| // not need to be added. |
| continue; |
| } |
| packages.add(pkg); |
| previous = pkg; |
| } |
| |
| Pattern pattern = Pattern.compile(SYSTEM_ACTION_REGEX + "|" |
| + "^//" + getPkgRegex(packages) + "[/:]"); |
| return RegexOutputFilter.forPattern(pattern); |
| } |
| }; |
| |
| /** An empty pattern */ |
| private static final String SYSTEM_ACTION_NAME = "(unknown)"; |
| private static final String SYSTEM_ACTION_REGEX = SYSTEM_ACTION_NAME; |
| |
| /** Returns an output filter regex for a set of requested targets. */ |
| public abstract OutputFilter getFilter(Iterable<Label> targets); |
| |
| /** |
| * Returns the package names of a some targets as an alphabetically sorted list. If there are |
| * targets under {@code //java/...} or {@code //javatests/...}, a string starting with |
| * "java(tests)?" is added instead. |
| */ |
| protected SortedSet<String> getPackages(Iterable<Label> targets) { |
| ImmutableSortedSet.Builder<String> packages = ImmutableSortedSet.naturalOrder(); |
| for (Label label : targets) { |
| String name = label.getPackageName(); |
| // Treat //java/foo and //javatests/foo as one package |
| if (name.startsWith("java/") || name.startsWith("javatests/")) { |
| name = "java(tests)?" + name.substring(name.indexOf('/')); |
| } |
| packages.add(name); |
| } |
| return packages.build(); |
| } |
| |
| /** |
| * Builds a regular expression that matches one of several strings. Characters |
| * that have a special meaning in regular expressions will not be escaped. |
| */ |
| protected String getPkgRegex(Iterable<String> strings) { |
| return "(" + Joiner.on('|').join(strings) + ")"; |
| } |
| |
| /** |
| * A converter for the {@code --auto_output_filter} option. |
| */ |
| public static class Converter extends EnumConverter<AutoOutputFilter> { |
| public Converter() { |
| super(AutoOutputFilter.class, "automatic output filter"); |
| } |
| } |
| } |