blob: 428743236c96506b33c6550844cc0b3d90747ff0 [file] [log] [blame]
// Copyright 2018 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;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.eventbus.EventBus;
import com.google.devtools.build.lib.analysis.NoBuildEvent;
import com.google.devtools.build.lib.analysis.NoBuildRequestFinishedEvent;
import com.google.devtools.build.lib.buildeventstream.BuildEventId;
import com.google.devtools.build.lib.query2.CommonQueryOptions;
import com.google.devtools.build.lib.query2.QueryOutputEvent;
import com.google.devtools.build.lib.util.ExitCode;
import com.google.devtools.build.lib.vfs.Path;
import java.io.IOException;
import java.io.OutputStream;
/** Helper for interfacing with the BEP from the `query`, `cquery`, and `aquery` commands. */
public interface QueryBEPHelper extends AutoCloseable {
OutputStream getOutputStreamForQueryOutput();
void afterQueryOutputIsWritten();
@Override
void close() throws IOException;
static BuildEventId getBuildEventIdOfQueryOutputEvent() {
return QueryOutputEvent.BUILD_EVENT_ID;
}
static QueryBEPHelper create(
CommandEnvironment env, CommonQueryOptions commonQueryOptions) throws IOException {
if (commonQueryOptions.uploadQueryOutputUsingBEP) {
Path queryOutputFilePath = env.getOutputBase().getChild("tmp_query_output");
OutputStream queryOutputStream = queryOutputFilePath.getOutputStream();
return new QueryBEPHelperForUploadingQueryOutputUsingBEP(
env.getCommandName(),
env.getEventBus(),
queryOutputFilePath,
queryOutputStream);
} else {
return new QueryBEPHelperForStdoutOutput(
env.getEventBus(),
env.getReporter().getOutErr().getOutputStream());
}
}
static QueryBEPHelperForNonBuildingCommand createForNonBuildingCommand(
CommandEnvironment env, CommonQueryOptions commonQueryOptions) throws IOException {
QueryBEPHelper delegate = create(env, commonQueryOptions);
return new QueryBEPHelperForNonBuildingCommand(env, delegate);
}
@VisibleForTesting
static QueryBEPHelper createForUnitTests(
String commandName,
EventBus eventBus,
CommonQueryOptions commonQueryOptions,
Path queryOutputFilePath,
OutputStream stdoutOutputStream) throws IOException {
if (commonQueryOptions.uploadQueryOutputUsingBEP) {
OutputStream queryOutputStream = queryOutputFilePath.getOutputStream();
return new QueryBEPHelperForUploadingQueryOutputUsingBEP(
commandName,
eventBus,
queryOutputFilePath,
queryOutputStream);
} else {
return new QueryBEPHelperForStdoutOutput(eventBus, stdoutOutputStream);
}
}
/**
* Implementation of {@link QueryBEPHelper} for the situation where we want to write query output
* to stdout on the console.
*/
class QueryBEPHelperForStdoutOutput implements QueryBEPHelper {
private final EventBus eventBus;
private final OutputStream stdoutOutputStream;
private QueryBEPHelperForStdoutOutput(EventBus eventBus, OutputStream stdoutOutputStream) {
this.eventBus = eventBus;
this.stdoutOutputStream = stdoutOutputStream;
}
@Override
public OutputStream getOutputStreamForQueryOutput() {
return stdoutOutputStream;
}
@Override
public void afterQueryOutputIsWritten() {
eventBus.post(QueryOutputEvent.forOutputWrittenToStdout());
}
@Override
public void close() {
// Nothing to do here. The CommandEnvironment owns the stdout OutputStream.
}
}
/**
* Implementation of {@link QueryBEPHelper} for the situation where we want to write query output
* to a temporary file and then upload that temporary file via BEP.
*/
class QueryBEPHelperForUploadingQueryOutputUsingBEP implements QueryBEPHelper {
private final String commandName;
private final EventBus eventBus;
private final Path queryOutputFilePath;
private final OutputStream queryOutputStream;
private QueryBEPHelperForUploadingQueryOutputUsingBEP(
String commandName,
EventBus eventBus,
Path queryOutputFilePath,
OutputStream queryOutputStream) {
this.commandName = commandName;
this.eventBus = eventBus;
this.queryOutputFilePath = queryOutputFilePath;
this.queryOutputStream = queryOutputStream;
}
@Override
public OutputStream getOutputStreamForQueryOutput() {
return queryOutputStream;
}
@Override
public void afterQueryOutputIsWritten() {
eventBus.post(QueryOutputEvent.forOutputWrittenToFile(commandName, queryOutputFilePath));
}
@Override
public void close() throws IOException {
queryOutputStream.close();
}
}
/** Implementation of {@link QueryBEPHelper} for commands that don't "build". */
class QueryBEPHelperForNonBuildingCommand implements QueryBEPHelper {
private final CommandEnvironment env;
private final QueryBEPHelper delegate;
private QueryBEPHelperForNonBuildingCommand(CommandEnvironment env, QueryBEPHelper delegate) {
this.env = env;
this.delegate = delegate;
}
public void beforeQueryOutputIsWritten() {
env.getEventBus()
.post(
NoBuildEvent.newBuilder()
.setCommand(env.getCommandName())
.setStartTimeMillis(env.getCommandStartTime())
.addAdditionalChildrenEvents(
ImmutableList.of(getBuildEventIdOfQueryOutputEvent()))
.setSeparateFinishedEvent(true)
.build());
}
@Override
public OutputStream getOutputStreamForQueryOutput() {
return delegate.getOutputStreamForQueryOutput();
}
@Override
public void afterQueryOutputIsWritten() {
delegate.afterQueryOutputIsWritten();
}
public void afterExitCodeIsDetermined(ExitCode exitCode) {
env.getEventBus().post(
new NoBuildRequestFinishedEvent(
exitCode, env.getRuntime().getClock().currentTimeMillis()));
}
@Override
public void close() throws IOException {
delegate.close();
}
}
}