| // Copyright 2020 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.runtime.commands; |
| |
| import com.google.common.base.Preconditions; |
| import com.google.common.collect.Lists; |
| import com.google.devtools.build.lib.buildtool.BuildRequestOptions; |
| import com.google.devtools.build.lib.profiler.Profiler; |
| import com.google.devtools.build.lib.profiler.SilentCloseable; |
| import com.google.devtools.build.lib.runtime.CommandEnvironment; |
| import com.google.devtools.build.lib.runtime.ProjectFileSupport; |
| import com.google.devtools.build.lib.server.FailureDetails.FailureDetail; |
| import com.google.devtools.build.lib.server.FailureDetails.TargetPatterns; |
| import com.google.devtools.build.lib.vfs.FileSystemUtils; |
| import com.google.devtools.build.lib.vfs.Path; |
| import com.google.devtools.common.options.OptionsParsingResult; |
| import java.io.IOException; |
| import java.nio.charset.StandardCharsets; |
| import java.util.List; |
| |
| /** Provides support for reading target patterns from a file or the command-line. */ |
| final class TargetPatternsHelper { |
| |
| private TargetPatternsHelper() {} |
| |
| /** |
| * Reads a list of target patterns, either from the command-line residue or by reading newline |
| * delimited target patterns from the --target_pattern_file flag. If --target_pattern_file is |
| * specified and options contain a residue, or if the file cannot be read, throws {@link |
| * TargetPatternsHelperException}. |
| */ |
| public static List<String> readFrom(CommandEnvironment env, OptionsParsingResult options) |
| throws TargetPatternsHelperException { |
| List<String> targets = options.getResidue(); |
| BuildRequestOptions buildRequestOptions = options.getOptions(BuildRequestOptions.class); |
| if (!targets.isEmpty() && !buildRequestOptions.targetPatternFile.isEmpty()) { |
| throw new TargetPatternsHelperException( |
| "Command-line target pattern and --target_pattern_file cannot both be specified", |
| TargetPatterns.Code.TARGET_PATTERN_FILE_WITH_COMMAND_LINE_PATTERN); |
| } else if (!buildRequestOptions.targetPatternFile.isEmpty()) { |
| // Works for absolute or relative file. |
| Path residuePath = |
| env.getWorkingDirectory().getRelative(buildRequestOptions.targetPatternFile); |
| try { |
| targets = |
| Lists.newArrayList(FileSystemUtils.readLines(residuePath, StandardCharsets.UTF_8)); |
| } catch (IOException e) { |
| throw new TargetPatternsHelperException( |
| "I/O error reading from " + residuePath.getPathString() + ": " + e.getMessage(), |
| TargetPatterns.Code.TARGET_PATTERN_FILE_READ_FAILURE); |
| } |
| } else { |
| try (SilentCloseable closeable = |
| Profiler.instance().profile("ProjectFileSupport.getTargets")) { |
| targets = ProjectFileSupport.getTargets(env.getRuntime().getProjectFileProvider(), options); |
| } |
| } |
| return targets; |
| } |
| |
| /** Thrown when target patterns couldn't be read. */ |
| static class TargetPatternsHelperException extends Exception { |
| private final TargetPatterns.Code detailedCode; |
| |
| private TargetPatternsHelperException(String message, TargetPatterns.Code detailedCode) { |
| super(Preconditions.checkNotNull(message)); |
| this.detailedCode = detailedCode; |
| } |
| |
| FailureDetail getFailureDetail() { |
| return FailureDetail.newBuilder() |
| .setMessage(getMessage()) |
| .setTargetPatterns(TargetPatterns.newBuilder().setCode(detailedCode)) |
| .build(); |
| } |
| } |
| } |