use of com.google.devtools.build.lib.util.ExitCode in project bazel by bazelbuild.
the class BlazeCommandDispatcher method execExclusively.
private int execExclusively(List<String> args, OutErr outErr, long firstContactTime, String commandName, BlazeCommand command, long waitTimeInMs) throws ShutdownBlazeServerException {
Command commandAnnotation = command.getClass().getAnnotation(Command.class);
// Record the start time for the profiler. Do not put anything before this!
long execStartTimeNanos = runtime.getClock().nanoTime();
// The initCommand call also records the start time for the timestamp granularity monitor.
CommandEnvironment env = runtime.getWorkspace().initCommand();
// Record the command's starting time for use by the commands themselves.
env.recordCommandStartTime(firstContactTime);
AbruptExitException exitCausingException = null;
for (BlazeModule module : runtime.getBlazeModules()) {
try {
module.beforeCommand(commandAnnotation, env);
} catch (AbruptExitException e) {
// Don't let one module's complaints prevent the other modules from doing necessary
// setup. We promised to call beforeCommand exactly once per-module before each command
// and will be calling afterCommand soon in the future - a module's afterCommand might
// rightfully assume its beforeCommand has already been called.
outErr.printErrLn(e.getMessage());
// It's not ideal but we can only return one exit code, so we just pick the code of the
// last exception.
exitCausingException = e;
}
}
if (exitCausingException != null) {
return exitCausingException.getExitCode().getNumericExitCode();
}
try {
Path commandLog = getCommandLogPath(env.getOutputBase());
// Unlink old command log from previous build, if present, so scripts
// reading it don't conflate it with the command log we're about to write.
closeSilently(logOutputStream);
logOutputStream = null;
commandLog.delete();
if (env.getRuntime().writeCommandLog() && commandAnnotation.writeCommandLog()) {
logOutputStream = commandLog.getOutputStream();
outErr = tee(outErr, OutErr.create(logOutputStream, logOutputStream));
}
} catch (IOException ioException) {
LoggingUtil.logToRemote(Level.WARNING, "Unable to delete or open command.log", ioException);
}
ExitCode result = checkCwdInWorkspace(env, commandAnnotation, commandName, outErr);
if (!result.equals(ExitCode.SUCCESS)) {
return result.getNumericExitCode();
}
OptionsParser optionsParser;
// Delay output of notes regarding the parsed rc file, so it's possible to disable this in the
// rc file.
List<String> rcfileNotes = new ArrayList<>();
try {
optionsParser = createOptionsParser(command);
parseArgsAndConfigs(env, optionsParser, commandAnnotation, args, rcfileNotes, outErr);
InvocationPolicyEnforcer optionsPolicyEnforcer = new InvocationPolicyEnforcer(runtime.getInvocationPolicy());
optionsPolicyEnforcer.enforce(optionsParser, commandName);
optionsPolicyEnforcer = InvocationPolicyEnforcer.create(getRuntime().getStartupOptionsProvider().getOptions(BlazeServerStartupOptions.class).invocationPolicy);
optionsPolicyEnforcer.enforce(optionsParser, commandName);
} catch (OptionsParsingException e) {
for (String note : rcfileNotes) {
outErr.printErrLn("INFO: " + note);
}
outErr.printErrLn(e.getMessage());
return ExitCode.COMMAND_LINE_ERROR.getNumericExitCode();
}
// Setup log filtering
BlazeCommandEventHandler.Options eventHandlerOptions = optionsParser.getOptions(BlazeCommandEventHandler.Options.class);
OutErr colorfulOutErr = outErr;
if (!eventHandlerOptions.useColor()) {
outErr = ansiStripOut(ansiStripErr(outErr));
if (!commandAnnotation.binaryStdOut()) {
colorfulOutErr = ansiStripOut(colorfulOutErr);
}
if (!commandAnnotation.binaryStdErr()) {
colorfulOutErr = ansiStripErr(colorfulOutErr);
}
}
if (!commandAnnotation.binaryStdOut()) {
outErr = lineBufferOut(outErr);
}
if (!commandAnnotation.binaryStdErr()) {
outErr = lineBufferErr(outErr);
}
CommonCommandOptions commonOptions = optionsParser.getOptions(CommonCommandOptions.class);
if (!commonOptions.verbosity.equals(lastLogVerbosityLevel)) {
BlazeRuntime.setupLogging(commonOptions.verbosity);
lastLogVerbosityLevel = commonOptions.verbosity;
}
// 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();
PrintStream savedOut = System.out;
PrintStream savedErr = System.err;
EventHandler handler = createEventHandler(outErr, eventHandlerOptions);
Reporter reporter = env.getReporter();
reporter.addHandler(handler);
env.getEventBus().register(handler);
// We register an ANSI-allowing handler associated with {@code handler} so that ANSI control
// codes can be re-introduced later even if blaze is invoked with --color=no. This is useful
// for commands such as 'blaze run' where the output of the final executable shouldn't be
// modified.
EventHandler ansiAllowingHandler = null;
if (!eventHandlerOptions.useColor()) {
ansiAllowingHandler = createEventHandler(colorfulOutErr, eventHandlerOptions);
reporter.registerAnsiAllowingHandler(handler, ansiAllowingHandler);
if (ansiAllowingHandler instanceof ExperimentalEventHandler) {
env.getEventBus().register(new PassiveExperimentalEventHandler((ExperimentalEventHandler) ansiAllowingHandler));
}
}
try {
// While a Blaze command is active, direct all errors to the client's
// event handler (and out/err streams).
OutErr reporterOutErr = reporter.getOutErr();
System.setOut(new PrintStream(reporterOutErr.getOutputStream(), /*autoflush=*/
true));
System.setErr(new PrintStream(reporterOutErr.getErrorStream(), /*autoflush=*/
true));
for (BlazeModule module : runtime.getBlazeModules()) {
module.checkEnvironment(env);
}
if (commonOptions.announceRcOptions) {
for (String note : rcfileNotes) {
reporter.handle(Event.info(note));
}
}
try {
// Notify the BlazeRuntime, so it can do some initial setup.
env.beforeCommand(commandAnnotation, optionsParser, commonOptions, execStartTimeNanos, waitTimeInMs);
// Allow the command to edit options after parsing:
command.editOptions(env, optionsParser);
} catch (AbruptExitException e) {
reporter.handle(Event.error(e.getMessage()));
return e.getExitCode().getNumericExitCode();
}
for (BlazeModule module : runtime.getBlazeModules()) {
module.handleOptions(optionsParser);
}
// Print warnings for odd options usage
for (String warning : optionsParser.getWarnings()) {
reporter.handle(Event.warn(warning));
}
ExitCode outcome = command.exec(env, optionsParser);
outcome = env.precompleteCommand(outcome);
numericExitCode = outcome.getNumericExitCode();
return numericExitCode;
} catch (ShutdownBlazeServerException e) {
numericExitCode = e.getExitStatus();
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);
} finally {
env.getEventBus().post(new AfterCommandEvent());
runtime.afterCommand(env, numericExitCode);
// Swallow IOException, as we are already in a finally clause
Flushables.flushQuietly(outErr.getOutputStream());
Flushables.flushQuietly(outErr.getErrorStream());
System.setOut(savedOut);
System.setErr(savedErr);
reporter.removeHandler(handler);
releaseHandler(handler);
if (!eventHandlerOptions.useColor()) {
reporter.removeHandler(ansiAllowingHandler);
releaseHandler(ansiAllowingHandler);
}
env.getTimestampGranularityMonitor().waitForTimestampGranularity(outErr);
}
}
Aggregations