aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib
diff options
context:
space:
mode:
authorGravatar lberki <lberki@google.com>2018-02-05 07:59:13 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2018-02-05 08:01:17 -0800
commit4741aa83145fd2d3ab0599314f7732c5b80977bd (patch)
treeb33310e226d9733ae0e538e433a54e337d6a67ed /src/main/java/com/google/devtools/build/lib
parent03ad9155f765fcdc0ccf4aae30a4def9914ea0b4 (diff)
Add a "direct" mode to "blaze run" that makes the process being run a direct
child of the process where the Blaze client itself was run. Limitations: - Untested on Windows; it should work because ExecuteProgram() is implemented there, too, but since Windows doesn't support exec(), there is at least one process in between Progress towards #2815. RELNOTES[NEW]: The new "--direct_run" flag on "blaze run" lets one run interactive binaries. PiperOrigin-RevId: 184528845
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib')
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/commands/FetchCommand.java19
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/BlazeCommand.java3
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/BlazeCommandDispatcher.java58
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/BlazeCommandResult.java53
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java62
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/BugReport.java8
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/CommandEnvironment.java8
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/CommandExecutor.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/BuildCommand.java6
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/CanonicalizeCommand.java9
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java13
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/CqueryCommand.java10
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/DumpCommand.java7
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/HelpCommand.java25
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java20
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/LicenseCommand.java5
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/PrintActionCommand.java5
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/ProfileCommand.java5
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/QueryCommand.java37
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/RunCommand.java82
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/ShutdownCommand.java7
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/TestCommand.java11
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/VersionCommand.java7
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/mobileinstall/MobileInstallCommand.java22
-rw-r--r--src/main/java/com/google/devtools/build/lib/server/GrpcServerImpl.java32
-rw-r--r--src/main/java/com/google/devtools/build/lib/server/ServerCommand.java3
-rw-r--r--src/main/java/com/google/devtools/build/lib/shell/Command.java4
27 files changed, 346 insertions, 179 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/commands/FetchCommand.java b/src/main/java/com/google/devtools/build/lib/bazel/commands/FetchCommand.java
index 7581de0eb0..202a29b45c 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/commands/FetchCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/commands/FetchCommand.java
@@ -28,6 +28,7 @@ import com.google.devtools.build.lib.query2.engine.QueryException;
import com.google.devtools.build.lib.query2.engine.QueryExpression;
import com.google.devtools.build.lib.query2.engine.ThreadSafeOutputFormatterCallback;
import com.google.devtools.build.lib.runtime.BlazeCommand;
+import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
@@ -60,29 +61,29 @@ public final class FetchCommand implements BlazeCommand {
public void editOptions(OptionsParser optionsParser) { }
@Override
- public ExitCode exec(CommandEnvironment env, OptionsProvider options) {
+ public BlazeCommandResult exec(CommandEnvironment env, OptionsProvider options) {
BlazeRuntime runtime = env.getRuntime();
if (options.getResidue().isEmpty()) {
env.getReporter().handle(Event.error(String.format(
"missing fetch expression. Type '%s help fetch' for syntax and help",
env.getRuntime().getProductName())));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
try {
env.setupPackageCache(options, runtime.getDefaultsPackageContent());
} catch (InterruptedException e) {
env.getReporter().handle(Event.error("fetch interrupted"));
- return ExitCode.INTERRUPTED;
+ return BlazeCommandResult.exitCode(ExitCode.INTERRUPTED);
} catch (AbruptExitException e) {
env.getReporter().handle(Event.error(null, "Unknown error: " + e.getMessage()));
- return e.getExitCode();
+ return BlazeCommandResult.exitCode(e.getExitCode());
}
PackageCacheOptions pkgOptions = options.getOptions(PackageCacheOptions.class);
if (!pkgOptions.fetch) {
env.getReporter().handle(Event.error(null, "You cannot run fetch with --fetch=false"));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
// Querying for all of the dependencies of the targets has the side-effect of populating the
@@ -110,7 +111,7 @@ public final class FetchCommand implements BlazeCommand {
} catch (QueryException e) {
env.getReporter().handle(Event.error(
null, "Error while parsing '" + query + "': " + e.getMessage()));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
env.getReporter()
@@ -139,7 +140,7 @@ public final class FetchCommand implements BlazeCommand {
.post(
new NoBuildRequestFinishedEvent(
ExitCode.COMMAND_LINE_ERROR, env.getRuntime().getClock().currentTimeMillis()));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
} catch (QueryException e) {
// Keep consistent with reportBuildFileError()
env.getReporter().handle(Event.error(e.getMessage()));
@@ -147,7 +148,7 @@ public final class FetchCommand implements BlazeCommand {
.post(
new NoBuildRequestFinishedEvent(
ExitCode.COMMAND_LINE_ERROR, env.getRuntime().getClock().currentTimeMillis()));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
} catch (IOException e) {
// Should be impossible since our OutputFormatterCallback doesn't throw IOException.
throw new IllegalStateException(e);
@@ -162,6 +163,6 @@ public final class FetchCommand implements BlazeCommand {
.post(
new NoBuildRequestFinishedEvent(
exitCode, env.getRuntime().getClock().currentTimeMillis()));
- return exitCode;
+ return BlazeCommandResult.exitCode(exitCode);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BlazeCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/BlazeCommand.java
index b5759edf77..22c1e636f5 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/BlazeCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/BlazeCommand.java
@@ -13,7 +13,6 @@
// limitations under the License.
package com.google.devtools.build.lib.runtime;
-import com.google.devtools.build.lib.util.ExitCode;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.OptionsProvider;
@@ -41,7 +40,7 @@ public interface BlazeCommand {
* @throws BlazeCommandDispatcher.ShutdownBlazeServerException Indicates that the command wants to
* shutdown the Blaze server.
*/
- ExitCode exec(CommandEnvironment env, OptionsProvider options)
+ BlazeCommandResult exec(CommandEnvironment env, OptionsProvider options)
throws BlazeCommandDispatcher.ShutdownBlazeServerException;
/**
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BlazeCommandDispatcher.java b/src/main/java/com/google/devtools/build/lib/runtime/BlazeCommandDispatcher.java
index b664561d0d..e58d670e1b 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/BlazeCommandDispatcher.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/BlazeCommandDispatcher.java
@@ -80,19 +80,19 @@ public class BlazeCommandDispatcher {
* the Blaze server process.
*/
public static class ShutdownBlazeServerException extends Exception {
- private final int exitStatus;
+ private final ExitCode exitCode;
- public ShutdownBlazeServerException(int exitStatus, Throwable cause) {
+ public ShutdownBlazeServerException(ExitCode exitCode, Throwable cause) {
super(cause);
- this.exitStatus = exitStatus;
+ this.exitCode = exitCode;
}
- public ShutdownBlazeServerException(int exitStatus) {
- this.exitStatus = exitStatus;
+ public ShutdownBlazeServerException(ExitCode exitCode) {
+ this.exitCode = exitCode;
}
- public int getExitStatus() {
- return exitStatus;
+ public ExitCode getExitCode() {
+ return exitCode;
}
}
@@ -138,7 +138,7 @@ public class BlazeCommandDispatcher {
* {@link ShutdownBlazeServerException} to indicate that a command wants to shutdown the Blaze
* server.
*/
- int exec(
+ BlazeCommandResult exec(
InvocationPolicy invocationPolicy,
List<String> args,
OutErr outErr,
@@ -165,7 +165,7 @@ public class BlazeCommandDispatcher {
if (command == null) {
outErr.printErrLn(String.format(
"Command '%s' not found. Try '%s help'.", commandName, runtime.getProductName()));
- return ExitCode.COMMAND_LINE_ERROR.getNumericExitCode();
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
// Take the exclusive server lock. If we fail, we busy-wait until the lock becomes available.
@@ -193,7 +193,7 @@ public class BlazeCommandDispatcher {
case ERROR_OUT:
outErr.printErrLn(String.format("Another command (" + currentClientDescription + ") is "
+ "running. Exiting immediately."));
- return ExitCode.COMMAND_LINE_ERROR.getNumericExitCode();
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
default:
throw new IllegalStateException();
@@ -213,7 +213,7 @@ public class BlazeCommandDispatcher {
try {
if (shutdownReason != null) {
outErr.printErrLn("Server shut down " + shutdownReason);
- return ExitCode.LOCAL_ENVIRONMENTAL_ERROR.getNumericExitCode();
+ return BlazeCommandResult.exitCode(ExitCode.LOCAL_ENVIRONMENTAL_ERROR);
}
return execExclusively(
originalCommandLine,
@@ -236,7 +236,7 @@ public class BlazeCommandDispatcher {
}
}
- private int execExclusively(
+ private BlazeCommandResult execExclusively(
OriginalUnstructuredCommandLineEvent unstructuredServerCommandLineEvent,
InvocationPolicy invocationPolicy,
List<String> args,
@@ -325,7 +325,7 @@ public class BlazeCommandDispatcher {
env.getEventBus().post(post);
}
// TODO(ulfjack): We're not calling BlazeModule.afterCommand here, even though we should.
- return earlyExitCode.getNumericExitCode();
+ return BlazeCommandResult.exitCode(earlyExitCode);
}
// Setup log filtering
@@ -360,7 +360,7 @@ public class BlazeCommandDispatcher {
// Do this before an actual crash so we don't have to worry about
// allocating memory post-crash.
String[] crashData = env.getCrashData();
- int numericExitCode = ExitCode.BLAZE_INTERNAL_ERROR.getNumericExitCode();
+ BlazeCommandResult result = BlazeCommandResult.exitCode(ExitCode.BLAZE_INTERNAL_ERROR);
PrintStream savedOut = System.out;
PrintStream savedErr = System.err;
@@ -379,14 +379,14 @@ public class BlazeCommandDispatcher {
}
if (oomMoreEagerlyThreshold < 0 || oomMoreEagerlyThreshold > 100) {
reporter.handle(Event.error("--oom_more_eagerly_threshold must be non-negative percent"));
- return ExitCode.COMMAND_LINE_ERROR.getNumericExitCode();
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
if (oomMoreEagerlyThreshold != 100) {
try {
RetainedHeapLimiter.maybeInstallRetainedHeapLimiter(oomMoreEagerlyThreshold);
} catch (OptionsParsingException e) {
reporter.handle(Event.error(e.getMessage()));
- return ExitCode.COMMAND_LINE_ERROR.getNumericExitCode();
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
}
@@ -472,7 +472,7 @@ public class BlazeCommandDispatcher {
invocationPolicy);
} catch (AbruptExitException e) {
reporter.handle(Event.error(e.getMessage()));
- return e.getExitCode().getNumericExitCode();
+ return BlazeCommandResult.exitCode(e.getExitCode());
}
// Log the command line now that the modules have all had a change to register their listeners
@@ -486,21 +486,29 @@ public class BlazeCommandDispatcher {
env.getSkyframeExecutor().injectExtraPrecomputedValues(module.getPrecomputedValues());
}
- ExitCode outcome = command.exec(env, options);
- outcome = env.precompleteCommand(outcome);
- numericExitCode = outcome.getNumericExitCode();
- return numericExitCode;
+ result = command.exec(env, options);
+ ExitCode moduleExitCode = env.precompleteCommand(result.getExitCode());
+ // If Blaze did not suffer an infrastructure failure, check for errors in modules.
+ if (result.getExitCode() != null
+ && !result.getExitCode().isInfrastructureFailure()
+ && moduleExitCode != null) {
+ result = BlazeCommandResult.exitCode(moduleExitCode);
+ }
+ return result;
} catch (ShutdownBlazeServerException e) {
- numericExitCode = e.getExitStatus();
+ // result is read in the finally block
+ result = BlazeCommandResult.exitCode(e.getExitCode());
throw e;
} catch (Throwable e) {
e.printStackTrace();
BugReport.printBug(outErr, e);
BugReport.sendBugReport(e, args, crashData);
- numericExitCode = BugReport.getExitCodeForThrowable(e);
- throw new ShutdownBlazeServerException(numericExitCode, e);
+ throw new ShutdownBlazeServerException(BugReport.getExitCodeForThrowable(e), e);
} finally {
env.getEventBus().post(new AfterCommandEvent());
+ int numericExitCode = result.getExitCode() == null
+ ? 0
+ : result.getExitCode().getNumericExitCode();
runtime.afterCommand(env, numericExitCode);
// Swallow IOException, as we are already in a finally clause
Flushables.flushQuietly(outErr.getOutputStream());
@@ -533,7 +541,7 @@ public class BlazeCommandDispatcher {
LockingMode.ERROR_OUT,
clientDescription,
runtime.getClock().currentTimeMillis(),
- Optional.empty() /* startupOptionBundles */);
+ Optional.empty() /* startupOptionBundles */).getExitCode().getNumericExitCode();
}
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BlazeCommandResult.java b/src/main/java/com/google/devtools/build/lib/runtime/BlazeCommandResult.java
new file mode 100644
index 0000000000..c1701c6ece
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/runtime/BlazeCommandResult.java
@@ -0,0 +1,53 @@
+// 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.base.Preconditions;
+import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
+import com.google.devtools.build.lib.server.CommandProtos.ExecRequest;
+import com.google.devtools.build.lib.util.ExitCode;
+import javax.annotation.Nullable;
+
+/**
+ * The result of a Blaze command. It is usually an exit code, but can be an instruction to the
+ * client to execute a particular binary for "blaze run".
+ */
+@Immutable
+public final class BlazeCommandResult {
+ private final ExitCode exitCode;
+ @Nullable
+ private final ExecRequest execDescription;
+
+ private BlazeCommandResult(ExitCode exitCode, ExecRequest execDescription) {
+ this.exitCode = Preconditions.checkNotNull(exitCode);
+ this.execDescription = execDescription;
+ }
+
+ public ExitCode getExitCode() {
+ return exitCode;
+ }
+
+ @Nullable public ExecRequest getExecRequest() {
+ return execDescription;
+ }
+
+ public static BlazeCommandResult exitCode(ExitCode exitCode) {
+ return new BlazeCommandResult(exitCode, null);
+ }
+
+ public static BlazeCommandResult execute(ExecRequest execDescription) {
+ return new BlazeCommandResult(ExitCode.SUCCESS, Preconditions.checkNotNull(execDescription));
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java b/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java
index 7789605f1d..7319206e80 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java
@@ -54,6 +54,8 @@ import com.google.devtools.build.lib.query2.output.OutputFormatter;
import com.google.devtools.build.lib.runtime.BlazeCommandDispatcher.LockingMode;
import com.google.devtools.build.lib.runtime.commands.InfoItem;
import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.InvocationPolicy;
+import com.google.devtools.build.lib.server.CommandProtos.EnvironmentVariable;
+import com.google.devtools.build.lib.server.CommandProtos.ExecRequest;
import com.google.devtools.build.lib.server.RPCServer;
import com.google.devtools.build.lib.server.signal.InterruptSignalHandler;
import com.google.devtools.build.lib.shell.JavaSubprocessFactory;
@@ -86,9 +88,11 @@ import com.google.devtools.common.options.OptionsParsingException;
import com.google.devtools.common.options.OptionsProvider;
import com.google.devtools.common.options.TriState;
import java.io.BufferedOutputStream;
+import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Type;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
@@ -702,7 +706,7 @@ public final class BlazeRuntime {
return new CommandLineOptions(startupArgs, otherArgs);
}
- private static void captureSigint() {
+ private static InterruptSignalHandler captureSigint() {
final Thread mainThread = Thread.currentThread();
final AtomicInteger numInterrupts = new AtomicInteger();
@@ -718,7 +722,7 @@ public final class BlazeRuntime {
}
};
- new InterruptSignalHandler() {
+ return new InterruptSignalHandler() {
@Override
public void run() {
logger.info("User interrupt");
@@ -743,7 +747,7 @@ public final class BlazeRuntime {
* exit status of the program.
*/
private static int batchMain(Iterable<BlazeModule> modules, String[] args) {
- captureSigint();
+ InterruptSignalHandler signalHandler = captureSigint();
CommandLineOptions commandLineOptions = splitStartupOptions(modules, args);
logger.info(
"Running Blaze in batch mode with "
@@ -773,10 +777,11 @@ public final class BlazeRuntime {
}
BlazeCommandDispatcher dispatcher = new BlazeCommandDispatcher(runtime);
+ boolean shutdownDone = false;
try {
logger.info(getRequestLogString(commandLineOptions.getOtherArgs()));
- return dispatcher.exec(
+ BlazeCommandResult result = dispatcher.exec(
policy,
commandLineOptions.getOtherArgs(),
OutErr.SYSTEM_OUT_ERR,
@@ -784,14 +789,57 @@ public final class BlazeRuntime {
"batch client",
runtime.getClock().currentTimeMillis(),
Optional.of(startupOptionsFromCommandLine.build()));
+ if (result.getExecRequest() == null) {
+ // Simple case: we are given an exit code
+ return result.getExitCode().getNumericExitCode();
+ }
+
+ // Not so simple case: we need to execute a binary on shutdown. exec() is not accessible from
+ // Java and is impossible on Windows in any case, so we just execute the binary after getting
+ // out of the way as completely as possible and forward its exit code.
+ // When this code is executed, no locks are held: the client lock is released by the client
+ // before it executes any command and the server lock is handled by BlazeCommandDispatcher,
+ // whose job is done by the time we get here.
+ runtime.shutdown();
+ dispatcher.shutdown();
+ shutdownDone = true;
+ signalHandler.uninstall();
+ ExecRequest request = result.getExecRequest();
+ String[] argv = new String[request.getArgvCount()];
+ for (int i = 0; i < argv.length; i++) {
+ argv[i] = request.getArgv(i).toString(StandardCharsets.ISO_8859_1);
+ }
+
+ String workingDirectory = request.getWorkingDirectory().toString(StandardCharsets.ISO_8859_1);
+ try {
+ ProcessBuilder process = new ProcessBuilder()
+ .command(argv)
+ .directory(new File(workingDirectory))
+ .inheritIO();
+
+ for (int i = 0; i < request.getEnvironmentVariableCount(); i++) {
+ EnvironmentVariable variable = request.getEnvironmentVariable(i);
+ process.environment().put(variable.getName().toString(StandardCharsets.ISO_8859_1),
+ variable.getValue().toString(StandardCharsets.ISO_8859_1));
+ }
+
+ return process.start().waitFor();
+ } catch (IOException e) {
+ // We are in batch mode, thus, stdout/stderr are the same as that of the client.
+ System.err.println("Cannot execute process for 'run' command: " + e.getMessage());
+ logger.log(Level.SEVERE, "Exception while executing binary from 'run' command", e);
+ return ExitCode.LOCAL_ENVIRONMENTAL_ERROR.getNumericExitCode();
+ }
} catch (BlazeCommandDispatcher.ShutdownBlazeServerException e) {
- return e.getExitStatus();
+ return e.getExitCode().getNumericExitCode();
} catch (InterruptedException e) {
// This is almost main(), so it's okay to just swallow it. We are exiting soon.
return ExitCode.INTERRUPTED.getNumericExitCode();
} finally {
- runtime.shutdown();
- dispatcher.shutdown();
+ if (!shutdownDone) {
+ runtime.shutdown();
+ dispatcher.shutdown();
+ }
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BugReport.java b/src/main/java/com/google/devtools/build/lib/runtime/BugReport.java
index 1d8c0d874a..af1d263e08 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/BugReport.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/BugReport.java
@@ -87,7 +87,7 @@ public abstract class BugReport {
* halts the runtime in that case.
*/
public static void handleCrash(Throwable throwable, String... args) {
- int exitCode = getExitCodeForThrowable(throwable);
+ int exitCode = getExitCodeForThrowable(throwable).getNumericExitCode();
try {
if (alreadyHandlingCrash.compareAndSet(false, true)) {
try {
@@ -131,10 +131,10 @@ public abstract class BugReport {
}
/** Get exit code corresponding to throwable. */
- public static int getExitCodeForThrowable(Throwable throwable) {
+ public static ExitCode getExitCodeForThrowable(Throwable throwable) {
return (Throwables.getRootCause(throwable) instanceof OutOfMemoryError)
- ? ExitCode.OOM_ERROR.getNumericExitCode()
- : ExitCode.BLAZE_INTERNAL_ERROR.getNumericExitCode();
+ ? ExitCode.OOM_ERROR
+ : ExitCode.BLAZE_INTERNAL_ERROR;
}
private static void printThrowableTo(OutErr outErr, Throwable e) {
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/CommandEnvironment.java b/src/main/java/com/google/devtools/build/lib/runtime/CommandEnvironment.java
index 34a2ebfcdd..f75f06a0b4 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/CommandEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/CommandEnvironment.java
@@ -481,13 +481,7 @@ public final class CommandEnvironment {
*/
ExitCode precompleteCommand(ExitCode originalExit) {
eventBus.post(new CommandPrecompleteEvent(originalExit));
- // If Blaze did not suffer an infrastructure failure, check for errors in modules.
- ExitCode exitCode = originalExit;
- ExitCode newExitCode = finalizeExitCode();
- if (!originalExit.isInfrastructureFailure() && newExitCode != null) {
- exitCode = newExitCode;
- }
- return exitCode;
+ return finalizeExitCode();
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/CommandExecutor.java b/src/main/java/com/google/devtools/build/lib/runtime/CommandExecutor.java
index f57c8ca04a..89c3a57911 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/CommandExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/CommandExecutor.java
@@ -43,7 +43,7 @@ public class CommandExecutor implements ServerCommand {
}
@Override
- public int exec(
+ public BlazeCommandResult exec(
InvocationPolicy invocationPolicy,
List<String> args,
OutErr outErr,
@@ -75,7 +75,7 @@ public class CommandExecutor implements ServerCommand {
shutdown = true;
runtime.shutdown();
dispatcher.shutdown();
- return e.getExitStatus();
+ return BlazeCommandResult.exitCode(e.getExitCode());
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/BuildCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/BuildCommand.java
index a02c991839..4803aaf115 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/BuildCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/BuildCommand.java
@@ -22,6 +22,7 @@ import com.google.devtools.build.lib.exec.local.LocalExecutionOptions;
import com.google.devtools.build.lib.pkgcache.LoadingOptions;
import com.google.devtools.build.lib.pkgcache.PackageCacheOptions;
import com.google.devtools.build.lib.runtime.BlazeCommand;
+import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
@@ -62,7 +63,7 @@ public final class BuildCommand implements BlazeCommand {
}
@Override
- public ExitCode exec(CommandEnvironment env, OptionsProvider options) {
+ public BlazeCommandResult exec(CommandEnvironment env, OptionsProvider options) {
BlazeRuntime runtime = env.getRuntime();
List<String> targets = ProjectFileSupport.getTargets(runtime.getProjectFileProvider(), options);
@@ -71,6 +72,7 @@ public final class BuildCommand implements BlazeCommand {
runtime.getStartupOptionsProvider(),
targets,
env.getReporter().getOutErr(), env.getCommandId(), env.getCommandStartTime());
- return new BuildTool(env).processRequest(request, null).getExitCondition();
+ ExitCode exitCode = new BuildTool(env).processRequest(request, null).getExitCondition();
+ return BlazeCommandResult.exitCode(exitCode);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/CanonicalizeCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/CanonicalizeCommand.java
index c2951f1d28..d17b281fbb 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/CanonicalizeCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/CanonicalizeCommand.java
@@ -17,6 +17,7 @@ import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.runtime.BlazeCommand;
+import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.BlazeCommandUtils;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.runtime.Command;
@@ -127,7 +128,7 @@ public final class CanonicalizeCommand implements BlazeCommand {
}
@Override
- public ExitCode exec(CommandEnvironment env, OptionsProvider options) {
+ public BlazeCommandResult exec(CommandEnvironment env, OptionsProvider options) {
BlazeRuntime runtime = env.getRuntime();
Options canonicalizeOptions = options.getOptions(Options.class);
String commandName = canonicalizeOptions.forCommand;
@@ -135,7 +136,7 @@ public final class CanonicalizeCommand implements BlazeCommand {
if (command == null) {
env.getReporter().handle(Event.error("Not a valid command: '" + commandName
+ "' (should be one of " + Joiner.on(", ").join(runtime.getCommandMap().keySet()) + ")"));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
Collection<Class<? extends OptionsBase>> optionsClasses =
ImmutableList.<Class<? extends OptionsBase>>builder()
@@ -175,9 +176,9 @@ public final class CanonicalizeCommand implements BlazeCommand {
}
} catch (OptionsParsingException e) {
env.getReporter().handle(Event.error(e.getMessage()));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
- return ExitCode.SUCCESS;
+ return BlazeCommandResult.exitCode(ExitCode.SUCCESS);
}
@Override
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java
index 721a0644fc..bf88f451a0 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java
@@ -21,6 +21,7 @@ import com.google.devtools.build.lib.buildtool.OutputDirectoryLinksUtils;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.runtime.BlazeCommand;
import com.google.devtools.build.lib.runtime.BlazeCommandDispatcher.ShutdownBlazeServerException;
+import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.shell.CommandException;
@@ -127,7 +128,7 @@ public final class CleanCommand implements BlazeCommand {
private static final Logger logger = Logger.getLogger(CleanCommand.class.getName());
@Override
- public ExitCode exec(CommandEnvironment env, OptionsProvider options)
+ public BlazeCommandResult exec(CommandEnvironment env, OptionsProvider options)
throws ShutdownBlazeServerException {
Options cleanOptions = options.getOptions(Options.class);
boolean async = cleanOptions.async;
@@ -165,16 +166,16 @@ public final class CleanCommand implements BlazeCommand {
.getOptions(BuildRequestOptions.class)
.getSymlinkPrefix(env.getRuntime().getProductName());
actuallyClean(env, env.getOutputBase(), cleanOptions.expunge, async, symlinkPrefix);
- return ExitCode.SUCCESS;
+ return BlazeCommandResult.exitCode(ExitCode.SUCCESS);
} catch (IOException e) {
env.getReporter().handle(Event.error(e.getMessage()));
- return ExitCode.LOCAL_ENVIRONMENTAL_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.LOCAL_ENVIRONMENTAL_ERROR);
} catch (CommandException | ExecException e) {
env.getReporter().handle(Event.error(e.getMessage()));
- return ExitCode.RUN_FAILURE;
+ return BlazeCommandResult.exitCode(ExitCode.RUN_FAILURE);
} catch (InterruptedException e) {
env.getReporter().handle(Event.error("clean interrupted"));
- return ExitCode.INTERRUPTED;
+ return BlazeCommandResult.exitCode(ExitCode.INTERRUPTED);
}
}
@@ -265,7 +266,7 @@ public final class CleanCommand implements BlazeCommand {
// shutdown on expunge cleans
if (expunge) {
- throw new ShutdownBlazeServerException(0);
+ throw new ShutdownBlazeServerException(ExitCode.SUCCESS);
}
System.gc();
}
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/CqueryCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/CqueryCommand.java
index b99002ad9c..1aa6c8dc4e 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/CqueryCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/CqueryCommand.java
@@ -25,6 +25,7 @@ import com.google.devtools.build.lib.query2.engine.QueryException;
import com.google.devtools.build.lib.query2.engine.QueryExpression;
import com.google.devtools.build.lib.query2.engine.QueryParser;
import com.google.devtools.build.lib.runtime.BlazeCommand;
+import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
@@ -66,13 +67,13 @@ public final class CqueryCommand implements BlazeCommand {
}
@Override
- public ExitCode exec(CommandEnvironment env, OptionsProvider options) {
+ public BlazeCommandResult exec(CommandEnvironment env, OptionsProvider options) {
if (options.getResidue().isEmpty()) {
env.getReporter()
.handle(
Event.error(
"Missing query expression. Use the 'help cquery' command for syntax and help."));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
String query = Joiner.on(' ').join(options.getResidue());
HashMap<String, QueryFunction> functions = new HashMap<>();
@@ -85,7 +86,7 @@ public final class CqueryCommand implements BlazeCommand {
} catch (QueryException e) {
env.getReporter()
.handle(Event.error("Error while parsing '" + query + "': " + e.getMessage()));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
List<String> topLevelTargets = options.getOptions(CommonQueryOptions.class).universeScope;
@@ -104,6 +105,7 @@ public final class CqueryCommand implements BlazeCommand {
env.getReporter().getOutErr(),
env.getCommandId(),
env.getCommandStartTime());
- return new BuildTool(env).processRequest(request, null, expr).getExitCondition();
+ ExitCode exitCode = new BuildTool(env).processRequest(request, null, expr).getExitCondition();
+ return BlazeCommandResult.exitCode(exitCode);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/DumpCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/DumpCommand.java
index 96b3149463..6f92ae0a06 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/DumpCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/DumpCommand.java
@@ -23,6 +23,7 @@ import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.profiler.memory.AllocationTracker;
import com.google.devtools.build.lib.profiler.memory.AllocationTracker.RuleBytes;
import com.google.devtools.build.lib.runtime.BlazeCommand;
+import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.BlazeCommandUtils;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.runtime.BlazeWorkspace;
@@ -166,7 +167,7 @@ public class DumpCommand implements BlazeCommand {
public void editOptions(OptionsParser optionsParser) {}
@Override
- public ExitCode exec(CommandEnvironment env, OptionsProvider options) {
+ public BlazeCommandResult exec(CommandEnvironment env, OptionsProvider options) {
BlazeRuntime runtime = env.getRuntime();
DumpOptions dumpOptions = options.getOptions(DumpOptions.class);
@@ -190,7 +191,7 @@ public class DumpCommand implements BlazeCommand {
getClass(),
optionList, categories, OptionsParser.HelpVerbosity.LONG,
runtime.getProductName()));
- return ExitCode.ANALYSIS_FAILURE;
+ return BlazeCommandResult.exitCode(ExitCode.ANALYSIS_FAILURE);
}
PrintStream out = new PrintStream(env.getReporter().getOutErr().getOutputStream());
try {
@@ -241,7 +242,7 @@ public class DumpCommand implements BlazeCommand {
out.println();
}
- return success ? ExitCode.SUCCESS : ExitCode.ANALYSIS_FAILURE;
+ return BlazeCommandResult.exitCode(success ? ExitCode.SUCCESS : ExitCode.ANALYSIS_FAILURE);
} finally {
out.flush();
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/HelpCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/HelpCommand.java
index 1e163e295e..6f47e3d1fb 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/HelpCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/HelpCommand.java
@@ -29,6 +29,7 @@ import com.google.devtools.build.lib.analysis.NoBuildEvent;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.runtime.BlazeCommand;
+import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.BlazeCommandUtils;
import com.google.devtools.build.lib.runtime.BlazeModule;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
@@ -176,7 +177,7 @@ public final class HelpCommand implements BlazeCommand {
public void editOptions(OptionsParser optionsParser) {}
@Override
- public ExitCode exec(CommandEnvironment env, OptionsProvider options) {
+ public BlazeCommandResult exec(CommandEnvironment env, OptionsProvider options) {
env.getEventBus().post(new NoBuildEvent());
BlazeRuntime runtime = env.getRuntime();
@@ -185,11 +186,11 @@ public final class HelpCommand implements BlazeCommand {
if (options.getResidue().isEmpty()) {
emitBlazeVersionInfo(outErr, runtime.getProductName());
emitGenericHelp(outErr, runtime);
- return ExitCode.SUCCESS;
+ return BlazeCommandResult.exitCode(ExitCode.SUCCESS);
}
if (options.getResidue().size() != 1) {
env.getReporter().handle(Event.error("You must specify exactly one command"));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
String helpSubject = options.getResidue().get(0);
String productName = runtime.getProductName();
@@ -203,7 +204,7 @@ public final class HelpCommand implements BlazeCommand {
runtime,
getDeprecatedOptionCategoriesDescriptions(productName),
helpOptions.useNewCategoryEnum);
- return ExitCode.SUCCESS;
+ return BlazeCommandResult.exitCode(ExitCode.SUCCESS);
case "target-syntax":
emitBlazeVersionInfo(outErr, runtime.getProductName());
emitTargetSyntaxHelp(
@@ -212,19 +213,19 @@ public final class HelpCommand implements BlazeCommand {
productName,
helpOptions.useNewCategoryEnum);
- return ExitCode.SUCCESS;
+ return BlazeCommandResult.exitCode(ExitCode.SUCCESS);
case "info-keys":
emitInfoKeysHelp(env, outErr);
- return ExitCode.SUCCESS;
+ return BlazeCommandResult.exitCode(ExitCode.SUCCESS);
case "completion":
emitCompletionHelp(runtime, outErr);
- return ExitCode.SUCCESS;
+ return BlazeCommandResult.exitCode(ExitCode.SUCCESS);
case "flags-as-proto":
emitFlagsAsProtoHelp(runtime, outErr);
- return ExitCode.SUCCESS;
+ return BlazeCommandResult.exitCode(ExitCode.SUCCESS);
case "everything-as-html":
new HtmlEmitter(runtime, helpOptions.useNewCategoryEnum).emit(outErr);
- return ExitCode.SUCCESS;
+ return BlazeCommandResult.exitCode(ExitCode.SUCCESS);
default: // fall out
}
@@ -236,11 +237,11 @@ public final class HelpCommand implements BlazeCommand {
// There is a rule with a corresponding name
outErr.printOut(
BlazeRuleHelpPrinter.getRuleDoc(helpSubject, runtime.getProductName(), provider));
- return ExitCode.SUCCESS;
+ return BlazeCommandResult.exitCode(ExitCode.SUCCESS);
} else {
env.getReporter().handle(Event.error(
null, "'" + helpSubject + "' is neither a command nor a build rule"));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
}
emitBlazeVersionInfo(outErr, productName);
@@ -254,7 +255,7 @@ public final class HelpCommand implements BlazeCommand {
productName,
helpOptions.useNewCategoryEnum));
- return ExitCode.SUCCESS;
+ return BlazeCommandResult.exitCode(ExitCode.SUCCESS);
}
private void emitBlazeVersionInfo(OutErr outErr, String productName) {
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java
index ca32232cc0..e10e5735e1 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java
@@ -22,6 +22,7 @@ import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.runtime.BlazeCommand;
+import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
@@ -101,7 +102,8 @@ public class InfoCommand implements BlazeCommand {
public void editOptions(OptionsParser optionsParser) { }
@Override
- public ExitCode exec(final CommandEnvironment env, final OptionsProvider optionsProvider) {
+ public BlazeCommandResult exec(
+ final CommandEnvironment env, final OptionsProvider optionsProvider) {
final BlazeRuntime runtime = env.getRuntime();
env.getReporter().switchToAnsiAllowingHandler();
Options infoOptions = optionsProvider.getOptions(Options.class);
@@ -152,7 +154,7 @@ public class InfoCommand implements BlazeCommand {
List<String> residue = optionsProvider.getResidue();
if (residue.size() > 1) {
env.getReporter().handle(Event.error("at most one key may be specified"));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
String key = residue.size() == 1 ? residue.get(0) : null;
@@ -163,14 +165,14 @@ public class InfoCommand implements BlazeCommand {
value = items.get(key).get(configurationSupplier, env);
} else {
env.getReporter().handle(Event.error("unknown key: '" + key + "'"));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
try {
outErr.getOutputStream().write(value);
outErr.getOutputStream().flush();
} catch (IOException e) {
env.getReporter().handle(Event.error("Cannot write info block: " + e.getMessage()));
- return ExitCode.ANALYSIS_FAILURE;
+ return BlazeCommandResult.exitCode(ExitCode.ANALYSIS_FAILURE);
}
} else { // print them all
configurationSupplier.get(); // We'll need this later anyway
@@ -184,15 +186,15 @@ public class InfoCommand implements BlazeCommand {
}
}
} catch (AbruptExitException e) {
- return e.getExitCode();
+ return BlazeCommandResult.exitCode(e.getExitCode());
} catch (ExitCausingRuntimeException e) {
- return e.getExitCode();
+ return BlazeCommandResult.exitCode(e.getExitCode());
} catch (IOException e) {
- return ExitCode.LOCAL_ENVIRONMENTAL_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.LOCAL_ENVIRONMENTAL_ERROR);
} catch (InterruptedException e) {
- return ExitCode.INTERRUPTED;
+ return BlazeCommandResult.exitCode(ExitCode.INTERRUPTED);
}
- return ExitCode.SUCCESS;
+ return BlazeCommandResult.exitCode(ExitCode.SUCCESS);
}
static Map<String, InfoItem> getHardwiredInfoItemMap(OptionsProvider commandOptions,
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/LicenseCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/LicenseCommand.java
index b735107e79..7ad512acb6 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/LicenseCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/LicenseCommand.java
@@ -16,6 +16,7 @@ package com.google.devtools.build.lib.runtime.commands;
import com.google.common.io.Files;
import com.google.devtools.build.lib.analysis.NoBuildEvent;
import com.google.devtools.build.lib.runtime.BlazeCommand;
+import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.util.ExitCode;
@@ -52,7 +53,7 @@ public class LicenseCommand implements BlazeCommand {
}
@Override
- public ExitCode exec(CommandEnvironment env, OptionsProvider options) {
+ public BlazeCommandResult exec(CommandEnvironment env, OptionsProvider options) {
env.getEventBus().post(new NoBuildEvent());
OutErr outErr = env.getReporter().getOutErr();
@@ -81,7 +82,7 @@ public class LicenseCommand implements BlazeCommand {
printJavaLicenseFiles(outErr, bundledJre);
}
- return ExitCode.SUCCESS;
+ return BlazeCommandResult.exitCode(ExitCode.SUCCESS);
}
private static void printJavaLicenseFiles(OutErr outErr, Path bundledJdkOrJre) {
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/PrintActionCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/PrintActionCommand.java
index 930575f674..6b4b266076 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/PrintActionCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/PrintActionCommand.java
@@ -44,6 +44,7 @@ import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.pkgcache.LoadingOptions;
import com.google.devtools.build.lib.runtime.BlazeCommand;
+import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
@@ -99,7 +100,7 @@ public final class PrintActionCommand implements BlazeCommand {
}
@Override
- public ExitCode exec(CommandEnvironment env, OptionsProvider options) {
+ public BlazeCommandResult exec(CommandEnvironment env, OptionsProvider options) {
LoadingOptions loadingOptions =
options.getOptions(LoadingOptions.class);
@@ -107,7 +108,7 @@ public final class PrintActionCommand implements BlazeCommand {
PrintActionRunner runner = new PrintActionRunner(loadingOptions.compileOneDependency, options,
env.getReporter().getOutErr(),
options.getResidue(), Sets.newHashSet(printActionOptions.printActionMnemonics));
- return runner.printActionsForTargets(env);
+ return BlazeCommandResult.exitCode(runner.printActionsForTargets(env));
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/ProfileCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/ProfileCommand.java
index 951e5c490b..f39f0054b3 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/ProfileCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/ProfileCommand.java
@@ -30,6 +30,7 @@ import com.google.devtools.build.lib.profiler.statistics.MultiProfileStatistics;
import com.google.devtools.build.lib.profiler.statistics.PhaseStatistics;
import com.google.devtools.build.lib.profiler.statistics.PhaseSummaryStatistics;
import com.google.devtools.build.lib.runtime.BlazeCommand;
+import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.util.ExitCode;
@@ -212,7 +213,7 @@ public final class ProfileCommand implements BlazeCommand {
public void editOptions(OptionsParser optionsParser) {}
@Override
- public ExitCode exec(final CommandEnvironment env, OptionsProvider options) {
+ public BlazeCommandResult exec(final CommandEnvironment env, OptionsProvider options) {
ProfileOptions opts =
options.getOptions(ProfileOptions.class);
@@ -325,7 +326,7 @@ public final class ProfileCommand implements BlazeCommand {
}
}
}
- return ExitCode.SUCCESS;
+ return BlazeCommandResult.exitCode(ExitCode.SUCCESS);
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/QueryCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/QueryCommand.java
index d34ae7b4a5..75b20fea68 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/QueryCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/QueryCommand.java
@@ -36,6 +36,7 @@ import com.google.devtools.build.lib.query2.output.OutputFormatter.StreamedForma
import com.google.devtools.build.lib.query2.output.QueryOptions;
import com.google.devtools.build.lib.query2.output.QueryOutputUtils;
import com.google.devtools.build.lib.runtime.BlazeCommand;
+import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
@@ -85,7 +86,7 @@ public final class QueryCommand implements BlazeCommand {
* (only when --keep_going is in effect.)
*/
@Override
- public ExitCode exec(CommandEnvironment env, OptionsProvider options) {
+ public BlazeCommandResult exec(CommandEnvironment env, OptionsProvider options) {
BlazeRuntime runtime = env.getRuntime();
QueryOptions queryOptions = options.getOptions(QueryOptions.class);
@@ -93,10 +94,10 @@ public final class QueryCommand implements BlazeCommand {
env.setupPackageCache(options, runtime.getDefaultsPackageContent());
} catch (InterruptedException e) {
env.getReporter().handle(Event.error("query interrupted"));
- return ExitCode.INTERRUPTED;
+ return BlazeCommandResult.exitCode(ExitCode.INTERRUPTED);
} catch (AbruptExitException e) {
env.getReporter().handle(Event.error(null, "Unknown error: " + e.getMessage()));
- return e.getExitCode();
+ return BlazeCommandResult.exitCode(e.getExitCode());
}
String query;
@@ -104,7 +105,7 @@ public final class QueryCommand implements BlazeCommand {
if (!queryOptions.queryFile.isEmpty()) {
env.getReporter()
.handle(Event.error("Command-line query and --query_file cannot both be specified"));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
query = Joiner.on(' ').join(options.getResidue());
} else if (!queryOptions.queryFile.isEmpty()) {
@@ -115,13 +116,13 @@ public final class QueryCommand implements BlazeCommand {
} catch (IOException e) {
env.getReporter()
.handle(Event.error("I/O error reading from " + residuePath.getPathString()));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
} else {
env.getReporter().handle(Event.error(String.format(
"missing query expression. Type '%s help query' for syntax and help",
runtime.getProductName())));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
Iterable<OutputFormatter> formatters = runtime.getQueryOutputFormatters();
@@ -131,7 +132,7 @@ public final class QueryCommand implements BlazeCommand {
env.getReporter().handle(Event.error(
String.format("Invalid output format '%s'. Valid values are: %s",
queryOptions.outputFormat, OutputFormatter.formatterNames(formatters))));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
Set<Setting> settings = queryOptions.toSettings();
@@ -151,14 +152,14 @@ public final class QueryCommand implements BlazeCommand {
} catch (QueryException e) {
env.getReporter()
.handle(Event.error(null, "Error while parsing '" + query + "': " + e.getMessage()));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
try {
formatter.verifyCompatible(queryEnv, expr);
} catch (QueryException e) {
env.getReporter().handle(Event.error(e.getMessage()));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
expr = queryEnv.transformParsedQuery(expr);
@@ -194,21 +195,21 @@ public final class QueryCommand implements BlazeCommand {
// TODO(bazel-team): this is a kludge to fix a bug observed in the wild. We should make
// sure no null error messages ever get in.
.handle(Event.error(e.getMessage() == null ? e.toString() : e.getMessage()));
- return ExitCode.ANALYSIS_FAILURE;
+ return BlazeCommandResult.exitCode(ExitCode.ANALYSIS_FAILURE);
} catch (InterruptedException e) {
catastrophe = false;
IOException ioException = callback.getIoException();
if (ioException == null || ioException instanceof ClosedByInterruptException) {
env.getReporter().handle(Event.error("query interrupted"));
- return ExitCode.INTERRUPTED;
+ return BlazeCommandResult.exitCode(ExitCode.INTERRUPTED);
} else {
env.getReporter().handle(Event.error("I/O error: " + e.getMessage()));
- return ExitCode.LOCAL_ENVIRONMENTAL_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.LOCAL_ENVIRONMENTAL_ERROR);
}
} catch (IOException e) {
catastrophe = false;
env.getReporter().handle(Event.error("I/O error: " + e.getMessage()));
- return ExitCode.LOCAL_ENVIRONMENTAL_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.LOCAL_ENVIRONMENTAL_ERROR);
} finally {
if (!catastrophe) {
try {
@@ -216,7 +217,7 @@ public final class QueryCommand implements BlazeCommand {
} catch (IOException e) {
env.getReporter().handle(
Event.error("Failed to flush query results: " + e.getMessage()));
- return ExitCode.LOCAL_ENVIRONMENTAL_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.LOCAL_ENVIRONMENTAL_ERROR);
}
}
}
@@ -236,17 +237,17 @@ public final class QueryCommand implements BlazeCommand {
queryOptions.aspectDeps.createResolver(env.getPackageManager(), env.getReporter()));
} catch (ClosedByInterruptException | InterruptedException e) {
env.getReporter().handle(Event.error("query interrupted"));
- return ExitCode.INTERRUPTED;
+ return BlazeCommandResult.exitCode(ExitCode.INTERRUPTED);
} catch (IOException e) {
env.getReporter().handle(Event.error("I/O error: " + e.getMessage()));
- return ExitCode.LOCAL_ENVIRONMENTAL_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.LOCAL_ENVIRONMENTAL_ERROR);
} finally {
try {
out.flush();
} catch (IOException e) {
env.getReporter().handle(
Event.error("Failed to flush query results: " + e.getMessage()));
- return ExitCode.LOCAL_ENVIRONMENTAL_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.LOCAL_ENVIRONMENTAL_ERROR);
}
}
}
@@ -258,7 +259,7 @@ public final class QueryCommand implements BlazeCommand {
ExitCode exitCode = result.getSuccess() ? ExitCode.SUCCESS : ExitCode.PARTIAL_ANALYSIS_FAILURE;
env.getEventBus()
.post(new NoBuildRequestFinishedEvent(exitCode, runtime.getClock().currentTimeMillis()));
- return exitCode;
+ return BlazeCommandResult.exitCode(exitCode);
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/RunCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/RunCommand.java
index 921fd7dda0..8535616a4b 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/RunCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/RunCommand.java
@@ -46,9 +46,12 @@ import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.pkgcache.LoadingFailedException;
import com.google.devtools.build.lib.runtime.BlazeCommand;
+import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.runtime.ProcessWrapperUtil;
+import com.google.devtools.build.lib.server.CommandProtos.EnvironmentVariable;
+import com.google.devtools.build.lib.server.CommandProtos.ExecRequest;
import com.google.devtools.build.lib.shell.AbnormalTerminationException;
import com.google.devtools.build.lib.shell.BadExitStatusException;
import com.google.devtools.build.lib.shell.CommandException;
@@ -71,11 +74,13 @@ import com.google.devtools.common.options.OptionEffectTag;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.OptionsProvider;
+import com.google.protobuf.ByteString;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.Map;
/**
* Builds and run a target with the given command line arguments.
@@ -92,9 +97,21 @@ import java.util.List;
completion = "label-bin",
binaryStdErr = true)
public class RunCommand implements BlazeCommand {
-
public static class RunOptions extends OptionsBase {
@Option(
+ name = "direct_run",
+ category = "run",
+ defaultValue = "false",
+ documentationCategory = OptionDocumentationCategory.OUTPUT_PARAMETERS,
+ effectTags = {OptionEffectTag.EXECUTION},
+ help = "If set, the 'run' command will execute the binary to be executed in the terminal "
+ + "where the command was called. Otherwise, it'll be executed as a child of the server "
+ + "process. If set, the binary will have access to direct terminal I/O and the command "
+ + "lock will not be held during its execution. This makes it possible to run other "
+ + "commands in parallel.")
+ public boolean direct;
+
+ @Option(
name = "script_path",
category = "run",
defaultValue = "null",
@@ -139,7 +156,7 @@ public class RunCommand implements BlazeCommand {
public void editOptions(OptionsParser optionsParser) { }
@Override
- public ExitCode exec(CommandEnvironment env, OptionsProvider options) {
+ public BlazeCommandResult exec(CommandEnvironment env, OptionsProvider options) {
RunOptions runOptions = options.getOptions(RunOptions.class);
// This list should look like: ["//executable:target", "arg1", "arg2"]
List<String> targetAndArgs = options.getResidue();
@@ -147,7 +164,7 @@ public class RunCommand implements BlazeCommand {
// The user must at the least specify an executable target.
if (targetAndArgs.isEmpty()) {
env.getReporter().handle(Event.error("Must specify a target to run"));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
String targetString = targetAndArgs.get(0);
List<String> runTargetArgs = targetAndArgs.subList(1, targetAndArgs.size());
@@ -172,7 +189,7 @@ public class RunCommand implements BlazeCommand {
if (!result.getSuccess()) {
env.getReporter().handle(Event.error("Build failed. Not running target"));
- return result.getExitCondition();
+ return BlazeCommandResult.exitCode(result.getExitCondition());
}
// Make sure that we have exactly 1 built target (excluding --run_under),
@@ -187,25 +204,25 @@ public class RunCommand implements BlazeCommand {
int maxTargets = runUnder != null && runUnder.getLabel() != null ? 2 : 1;
if (targetsBuilt.size() > maxTargets) {
env.getReporter().handle(Event.error(SINGLE_TARGET_MESSAGE));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
for (ConfiguredTarget target : targetsBuilt) {
ExitCode targetValidation = fullyValidateTarget(env, target);
if (!targetValidation.equals(ExitCode.SUCCESS)) {
- return targetValidation;
+ return BlazeCommandResult.exitCode(targetValidation);
}
if (runUnder != null && target.getLabel().equals(runUnder.getLabel())) {
if (runUnderTarget != null) {
env.getReporter().handle(Event.error(
null, "Can't identify the run_under target from multiple options?"));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
runUnderTarget = target;
} else if (targetToRun == null) {
targetToRun = target;
} else {
env.getReporter().handle(Event.error(SINGLE_TARGET_MESSAGE));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
}
}
@@ -215,7 +232,7 @@ public class RunCommand implements BlazeCommand {
}
if (targetToRun == null) {
env.getReporter().handle(Event.error(NO_TARGET_MESSAGE));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
Path executablePath = Preconditions.checkNotNull(
@@ -231,13 +248,13 @@ public class RunCommand implements BlazeCommand {
env.getReporter()
.handle(
Event.error("--nobuild_runfile_manifests is incompatible with the \"run\" command"));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
try {
workingDir = ensureRunfilesBuilt(env, targetToRun);
} catch (CommandException e) {
env.getReporter().handle(Event.error("Error creating runfiles: " + e.getMessage()));
- return ExitCode.LOCAL_ENVIRONMENTAL_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.LOCAL_ENVIRONMENTAL_ERROR);
}
List<String> args = Lists.newArrayList();
@@ -250,7 +267,7 @@ public class RunCommand implements BlazeCommand {
Iterables.addAll(args, targetArgs.arguments());
} catch (CommandLineExpansionException e) {
env.getReporter().handle(Event.error("Could not expand target command line: " + e));
- return ExitCode.ANALYSIS_FAILURE;
+ return BlazeCommandResult.exitCode(ExitCode.ANALYSIS_FAILURE);
}
}
args.addAll(runTargetArgs);
@@ -271,7 +288,8 @@ public class RunCommand implements BlazeCommand {
// process-wrapper does not work on Windows (nor is it necessary), so don't use it
// on that platform. Also we skip it when writing the command-line to a file instead
// of executing it directly.
- if (OS.getCurrent() != OS.WINDOWS && runOptions.scriptPath == null) {
+ if (OS.getCurrent() != OS.WINDOWS && runOptions.scriptPath == null
+ && !runOptions.direct) {
Preconditions.checkState(ProcessWrapperUtil.isSupported(env),
"process-wraper not found in embedded tools");
cmdLine.add(ProcessWrapperUtil.getProcessWrapper(env).getPathString());
@@ -317,19 +335,38 @@ public class RunCommand implements BlazeCommand {
CommandDescriptionForm.COMPLETE_UNISOLATED,
cmdLine, null, workingDir.getPathString());
if (writeScript(env, runOptions.scriptPath, unisolatedCommand)) {
- return ExitCode.SUCCESS;
+ return BlazeCommandResult.exitCode(ExitCode.SUCCESS);
} else {
- return ExitCode.RUN_FAILURE;
+ return BlazeCommandResult.exitCode(ExitCode.RUN_FAILURE);
}
}
env.getReporter().handle(Event.info(
null, "Running command line: " + ShellEscaper.escapeJoinAll(prettyCmdLine)));
- com.google.devtools.build.lib.shell.Command command = new CommandBuilder()
- .addArgs(cmdLine).setEnv(env.getClientEnv()).setWorkingDir(workingDir).build();
+ if (runOptions.direct) {
+ ExecRequest.Builder execDescription = ExecRequest.newBuilder()
+ .setWorkingDirectory(
+ ByteString.copyFrom(workingDir.getPathString(), StandardCharsets.ISO_8859_1));
+
+ for (String arg : cmdLine) {
+ execDescription.addArgv(ByteString.copyFrom(arg, StandardCharsets.ISO_8859_1));
+ }
+
+ for (Map.Entry<String, String> variable : env.getClientEnv().entrySet()) {
+ execDescription.addEnvironmentVariable(EnvironmentVariable.newBuilder()
+ .setName(ByteString.copyFrom(variable.getKey(), StandardCharsets.ISO_8859_1))
+ .setValue(ByteString.copyFrom(variable.getValue(), StandardCharsets.ISO_8859_1))
+ .build());
+ }
+
+ return BlazeCommandResult.execute(execDescription.build());
+ }
try {
+ com.google.devtools.build.lib.shell.Command command = new CommandBuilder()
+ .addArgs(cmdLine).setEnv(env.getClientEnv()).setWorkingDir(workingDir).build();
+
// Restore a raw EventHandler if it is registered. This allows for blaze run to produce the
// actual output of the command being run even if --color=no is specified.
env.getReporter().switchToAnsiAllowingHandler();
@@ -341,19 +378,19 @@ public class RunCommand implements BlazeCommand {
.execute(outErr.getOutputStream(), outErr.getErrorStream())
.getTerminationStatus()
.getExitCode();
- return ExitCode.SUCCESS;
+ return BlazeCommandResult.exitCode(ExitCode.SUCCESS);
} catch (BadExitStatusException e) {
String message = "Non-zero return code '"
+ e.getResult().getTerminationStatus().getExitCode()
+ "' from command: " + e.getMessage();
env.getReporter().handle(Event.error(message));
- return ExitCode.RUN_FAILURE;
+ return BlazeCommandResult.exitCode(ExitCode.RUN_FAILURE);
} catch (AbnormalTerminationException e) {
// The process was likely terminated by a signal in this case.
- return ExitCode.INTERRUPTED;
+ return BlazeCommandResult.exitCode(ExitCode.INTERRUPTED);
} catch (CommandException e) {
env.getReporter().handle(Event.error("Error running program: " + e.getMessage()));
- return ExitCode.RUN_FAILURE;
+ return BlazeCommandResult.exitCode(ExitCode.RUN_FAILURE);
}
}
@@ -480,7 +517,8 @@ public class RunCommand implements BlazeCommand {
* Performs all available validation checks on an individual target.
*
* @param configuredTarget ConfiguredTarget to validate
- * @return ExitCode.SUCCESS if all checks succeeded, otherwise a different error code.
+ * @return BlazeCommandResult.exitCode(ExitCode.SUCCESS) if all checks succeeded, otherwise a
+ * different error code.
* @throws IllegalStateException if unable to find a target from the package manager.
*/
private ExitCode fullyValidateTarget(CommandEnvironment env, ConfiguredTarget configuredTarget) {
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/ShutdownCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/ShutdownCommand.java
index 09423c0b56..f242c9d7ce 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/ShutdownCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/ShutdownCommand.java
@@ -15,6 +15,7 @@ package com.google.devtools.build.lib.runtime.commands;
import com.google.devtools.build.lib.runtime.BlazeCommand;
import com.google.devtools.build.lib.runtime.BlazeCommandDispatcher.ShutdownBlazeServerException;
+import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.util.ExitCode;
@@ -56,7 +57,7 @@ public final class ShutdownCommand implements BlazeCommand {
public void editOptions(OptionsParser optionsParser) {}
@Override
- public ExitCode exec(CommandEnvironment env, OptionsProvider options)
+ public BlazeCommandResult exec(CommandEnvironment env, OptionsProvider options)
throws ShutdownBlazeServerException {
int limit = options.getOptions(Options.class).heapSizeLimit;
@@ -69,9 +70,9 @@ public final class ShutdownCommand implements BlazeCommand {
if (limit == 0 ||
Runtime.getRuntime().totalMemory() > limit * 1000L * 1000) {
- throw new ShutdownBlazeServerException(0);
+ throw new ShutdownBlazeServerException(ExitCode.SUCCESS);
}
- return ExitCode.SUCCESS;
+ return BlazeCommandResult.exitCode(ExitCode.SUCCESS);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/TestCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/TestCommand.java
index 1e3f61a97a..5887aa59da 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/TestCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/TestCommand.java
@@ -29,6 +29,7 @@ import com.google.devtools.build.lib.exec.TestStrategy.TestOutputFormat;
import com.google.devtools.build.lib.runtime.AggregatingTestListener;
import com.google.devtools.build.lib.runtime.BlazeCommand;
import com.google.devtools.build.lib.runtime.BlazeCommandEventHandler;
+import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
@@ -81,7 +82,7 @@ public class TestCommand implements BlazeCommand {
}
@Override
- public ExitCode exec(CommandEnvironment env, OptionsProvider options) {
+ public BlazeCommandResult exec(CommandEnvironment env, OptionsProvider options) {
TestOutputFormat testOutput = options.getOptions(ExecutionOptions.class).testOutput;
if (testOutput == TestStrategy.TestOutputFormat.STREAMED) {
env.getReporter().handle(Event.warn(
@@ -105,7 +106,7 @@ public class TestCommand implements BlazeCommand {
return doTest(env, options, testListener);
}
- private ExitCode doTest(CommandEnvironment env,
+ private BlazeCommandResult doTest(CommandEnvironment env,
OptionsProvider options,
AggregatingTestListener testListener) {
BlazeRuntime runtime = env.getRuntime();
@@ -134,7 +135,7 @@ public class TestCommand implements BlazeCommand {
ExitCode exitCode =
buildResult.getSuccess() ? ExitCode.PARSING_FAILURE : buildResult.getExitCondition();
env.getEventBus().post(new TestingCompleteEvent(exitCode, buildResult.getStopTime()));
- return exitCode;
+ return BlazeCommandResult.exitCode(exitCode);
}
// TODO(bazel-team): the check above shadows NO_TESTS_FOUND, but switching the conditions breaks
// more tests
@@ -146,7 +147,7 @@ public class TestCommand implements BlazeCommand {
buildResult.getSuccess() ? ExitCode.NO_TESTS_FOUND : buildResult.getExitCondition();
env.getEventBus()
.post(new NoTestsFound(exitCode, env.getRuntime().getClock().currentTimeMillis()));
- return exitCode;
+ return BlazeCommandResult.exitCode(exitCode);
}
boolean buildSuccess = buildResult.getSuccess();
@@ -165,7 +166,7 @@ public class TestCommand implements BlazeCommand {
? (testSuccess ? ExitCode.SUCCESS : ExitCode.TESTS_FAILED)
: buildResult.getExitCondition();
env.getEventBus().post(new TestingCompleteEvent(exitCode, buildResult.getStopTime()));
- return exitCode;
+ return BlazeCommandResult.exitCode(exitCode);
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/VersionCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/VersionCommand.java
index eff8700248..729c3b7c25 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/VersionCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/VersionCommand.java
@@ -17,6 +17,7 @@ import com.google.devtools.build.lib.analysis.BlazeVersionInfo;
import com.google.devtools.build.lib.analysis.NoBuildEvent;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.runtime.BlazeCommand;
+import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.util.ExitCode;
@@ -38,14 +39,14 @@ public final class VersionCommand implements BlazeCommand {
public void editOptions(OptionsParser optionsParser) {}
@Override
- public ExitCode exec(CommandEnvironment env, OptionsProvider options) {
+ public BlazeCommandResult exec(CommandEnvironment env, OptionsProvider options) {
BlazeVersionInfo info = BlazeVersionInfo.instance();
if (info.getSummary() == null) {
env.getReporter().handle(Event.error("Version information not available"));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
env.getEventBus().post(new NoBuildEvent());
env.getReporter().getOutErr().printOutLn(info.getSummary());
- return ExitCode.SUCCESS;
+ return BlazeCommandResult.exitCode(ExitCode.SUCCESS);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/mobileinstall/MobileInstallCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/mobileinstall/MobileInstallCommand.java
index acdd49784d..d382daf5c4 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/mobileinstall/MobileInstallCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/mobileinstall/MobileInstallCommand.java
@@ -28,6 +28,7 @@ import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.rules.android.WriteAdbArgsAction;
import com.google.devtools.build.lib.rules.android.WriteAdbArgsAction.StartType;
import com.google.devtools.build.lib.runtime.BlazeCommand;
+import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.runtime.CommonCommandOptions;
@@ -167,7 +168,7 @@ public class MobileInstallCommand implements BlazeCommand {
private static final String NO_TARGET_MESSAGE = "No targets found to run";
@Override
- public ExitCode exec(CommandEnvironment env, OptionsProvider options) {
+ public BlazeCommandResult exec(CommandEnvironment env, OptionsProvider options) {
Options mobileInstallOptions = options.getOptions(Options.class);
WriteAdbArgsAction.Options adbOptions = options.getOptions(WriteAdbArgsAction.Options.class);
@@ -193,7 +194,8 @@ public class MobileInstallCommand implements BlazeCommand {
env.getReporter().getOutErr(),
env.getCommandId(),
env.getCommandStartTime());
- return new BuildTool(env).processRequest(request, null).getExitCondition();
+ ExitCode exitCode = new BuildTool(env).processRequest(request, null).getExitCondition();
+ return BlazeCommandResult.exitCode(exitCode);
}
// This list should look like: ["//executable:target", "arg1", "arg2"]
@@ -202,7 +204,7 @@ public class MobileInstallCommand implements BlazeCommand {
// The user must at least specify an executable target.
if (targetAndArgs.isEmpty()) {
env.getReporter().handle(Event.error("Must specify a target to run"));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
List<String> targets = ImmutableList.of(targetAndArgs.get(0));
@@ -222,17 +224,17 @@ public class MobileInstallCommand implements BlazeCommand {
if (!result.getSuccess()) {
env.getReporter().handle(Event.error("Build failed. Not running target"));
- return result.getExitCondition();
+ return BlazeCommandResult.exitCode(result.getExitCondition());
}
Collection<ConfiguredTarget> targetsBuilt = result.getSuccessfulTargets();
if (targetsBuilt == null) {
env.getReporter().handle(Event.error(NO_TARGET_MESSAGE));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
if (targetsBuilt.size() != 1) {
env.getReporter().handle(Event.error(SINGLE_TARGET_MESSAGE));
- return ExitCode.COMMAND_LINE_ERROR;
+ return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
ConfiguredTarget targetToRun = Iterables.getOnlyElement(targetsBuilt);
@@ -299,7 +301,7 @@ public class MobileInstallCommand implements BlazeCommand {
.execute(outErr.getOutputStream(), outErr.getErrorStream())
.getTerminationStatus()
.getExitCode();
- return ExitCode.SUCCESS;
+ return BlazeCommandResult.exitCode(ExitCode.SUCCESS);
} catch (BadExitStatusException e) {
String message =
"Non-zero return code '"
@@ -307,13 +309,13 @@ public class MobileInstallCommand implements BlazeCommand {
+ "' from command: "
+ e.getMessage();
env.getReporter().handle(Event.error(message));
- return ExitCode.RUN_FAILURE;
+ return BlazeCommandResult.exitCode(ExitCode.RUN_FAILURE);
} catch (AbnormalTerminationException e) {
// The process was likely terminated by a signal in this case.
- return ExitCode.INTERRUPTED;
+ return BlazeCommandResult.exitCode(ExitCode.INTERRUPTED);
} catch (CommandException e) {
env.getReporter().handle(Event.error("Error running program: " + e.getMessage()));
- return ExitCode.RUN_FAILURE;
+ return BlazeCommandResult.exitCode(ExitCode.RUN_FAILURE);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/server/GrpcServerImpl.java b/src/main/java/com/google/devtools/build/lib/server/GrpcServerImpl.java
index c412131ead..aa575da2b5 100644
--- a/src/main/java/com/google/devtools/build/lib/server/GrpcServerImpl.java
+++ b/src/main/java/com/google/devtools/build/lib/server/GrpcServerImpl.java
@@ -26,6 +26,7 @@ import com.google.devtools.build.lib.clock.BlazeClock;
import com.google.devtools.build.lib.clock.Clock;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.runtime.BlazeCommandDispatcher.LockingMode;
+import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.CommandExecutor;
import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.InvocationPolicy;
import com.google.devtools.build.lib.server.CommandProtos.CancelRequest;
@@ -814,7 +815,7 @@ public class GrpcServerImpl implements RPCServer {
}
String commandId;
- int exitCode;
+ BlazeCommandResult result;
// TODO(b/63925394): This information needs to be passed to the GotOptionsEvent, which does not
// currently have the explicit startup options. See Improved Command Line Reporting design doc
@@ -847,7 +848,7 @@ public class GrpcServerImpl implements RPCServer {
try {
InvocationPolicy policy = InvocationPolicyParser.parsePolicy(request.getInvocationPolicy());
- exitCode =
+ result =
commandExecutor.exec(
policy,
args.build(),
@@ -858,10 +859,10 @@ public class GrpcServerImpl implements RPCServer {
Optional.of(startupOptions.build()));
} catch (OptionsParsingException e) {
rpcOutErr.printErrLn(e.getMessage());
- exitCode = ExitCode.COMMAND_LINE_ERROR.getNumericExitCode();
+ result = BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
}
} catch (InterruptedException e) {
- exitCode = ExitCode.INTERRUPTED.getNumericExitCode();
+ result = BlazeCommandResult.exitCode(ExitCode.INTERRUPTED);
commandId = ""; // The default value, the client will ignore it
}
@@ -883,17 +884,22 @@ public class GrpcServerImpl implements RPCServer {
if (shutdown) {
server.shutdown();
}
- RunResponse response =
- RunResponse.newBuilder()
- .setCookie(responseCookie)
- .setCommandId(commandId)
- .setFinished(true)
- .setExitCode(exitCode)
- .setTerminationExpected(shutdown)
- .build();
+
+ RunResponse.Builder response = RunResponse.newBuilder()
+ .setCookie(responseCookie)
+ .setCommandId(commandId)
+ .setFinished(true)
+ .setTerminationExpected(shutdown);
+
+ if (result.getExecRequest() != null) {
+ response.setExitCode(0);
+ response.setExecRequest(result.getExecRequest());
+ } else {
+ response.setExitCode(result.getExitCode().getNumericExitCode());
+ }
try {
- observer.onNext(response);
+ observer.onNext(response.build());
observer.onCompleted();
} catch (StatusRuntimeException e) {
// The client cancelled the call. Log an error and go on.
diff --git a/src/main/java/com/google/devtools/build/lib/server/ServerCommand.java b/src/main/java/com/google/devtools/build/lib/server/ServerCommand.java
index f0574cdbaa..aed9d73b98 100644
--- a/src/main/java/com/google/devtools/build/lib/server/ServerCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/server/ServerCommand.java
@@ -14,6 +14,7 @@
package com.google.devtools.build.lib.server;
import com.google.devtools.build.lib.runtime.BlazeCommandDispatcher;
+import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.InvocationPolicy;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.util.io.OutErr;
@@ -35,7 +36,7 @@ public interface ServerCommand {
* --[no]flag or --flag=value form. If we don't have access to this information (--batch),
* leave this parameter as Optional.empty().
*/
- int exec(
+ BlazeCommandResult exec(
InvocationPolicy policy,
List<String> args,
OutErr outErr,
diff --git a/src/main/java/com/google/devtools/build/lib/shell/Command.java b/src/main/java/com/google/devtools/build/lib/shell/Command.java
index 0e8c5a0247..1584275184 100644
--- a/src/main/java/com/google/devtools/build/lib/shell/Command.java
+++ b/src/main/java/com/google/devtools/build/lib/shell/Command.java
@@ -46,7 +46,7 @@ import javax.annotation.Nullable;
* <p>The most basic use-case for this class is as follows:
* <pre>
* String[] args = { "/bin/du", "-s", directory };
- * CommandResult result = new Command(args).execute();
+ * BlazeCommandResult result = new Command(args).execute();
* String output = new String(result.getStdout());
* </pre>
* which writes the output of the {@code du(1)} command into {@code output}. More complex cases
@@ -78,7 +78,7 @@ import javax.annotation.Nullable;
* <p>To execute a shell command directly, use the following pattern:
* <pre>
* String[] args = { "/bin/sh", "-c", shellCommand };
- * CommandResult result = new Command(args).execute();
+ * BlazeCommandResult result = new Command(args).execute();
* </pre>
* {@code shellCommand} is a complete Bourne shell program, possibly containing all kinds of
* unescaped metacharacters. For example, here's a shell command that enumerates the working