mirror of https://github.com/sbt/sbt.git
Reply to sbt/exec w/ a Response/Error w/ error code
This commit is contained in:
parent
bde6365013
commit
98332c0891
|
|
@ -15,6 +15,7 @@ import jline.TerminalFactory
|
||||||
import sbt.io.{ IO, Using }
|
import sbt.io.{ IO, Using }
|
||||||
import sbt.internal.util.{ ErrorHandling, GlobalLogBacking }
|
import sbt.internal.util.{ ErrorHandling, GlobalLogBacking }
|
||||||
import sbt.internal.util.complete.DefaultParsers
|
import sbt.internal.util.complete.DefaultParsers
|
||||||
|
import sbt.internal.langserver.ErrorCodes
|
||||||
import sbt.util.Logger
|
import sbt.util.Logger
|
||||||
import sbt.protocol._
|
import sbt.protocol._
|
||||||
|
|
||||||
|
|
@ -155,13 +156,63 @@ object MainLoop {
|
||||||
state.log error errMsg
|
state.log error errMsg
|
||||||
state.fail
|
state.fail
|
||||||
}
|
}
|
||||||
StandardMain.exchange publishEventMessage ExecStatusEvent(
|
val doneEvent = ExecStatusEvent(
|
||||||
"Done",
|
"Done",
|
||||||
channelName,
|
channelName,
|
||||||
exec.execId,
|
exec.execId,
|
||||||
newState.remainingCommands.toVector map (_.commandLine))
|
newState.remainingCommands.toVector map (_.commandLine),
|
||||||
|
exitCode(newState, state),
|
||||||
|
)
|
||||||
|
if (doneEvent.execId.isDefined) { // send back a response or error
|
||||||
|
import sbt.protocol.codec.JsonProtocol._
|
||||||
|
StandardMain.exchange publishEvent doneEvent
|
||||||
|
} else { // send back a notification
|
||||||
|
StandardMain.exchange publishEventMessage doneEvent
|
||||||
|
}
|
||||||
newState
|
newState
|
||||||
}
|
}
|
||||||
|
|
||||||
def logFullException(e: Throwable, log: Logger): Unit = State.logFullException(e, log)
|
def logFullException(e: Throwable, log: Logger): Unit = State.logFullException(e, log)
|
||||||
|
|
||||||
|
private[this] type ExitCode = Option[Long]
|
||||||
|
private[this] object ExitCode {
|
||||||
|
def apply(n: Long): ExitCode = Option(n)
|
||||||
|
val Success: ExitCode = ExitCode(0)
|
||||||
|
val Unknown: ExitCode = None
|
||||||
|
}
|
||||||
|
|
||||||
|
private[this] def exitCode(state: State, prevState: State): ExitCode = {
|
||||||
|
exitCodeFromStateNext(state) match {
|
||||||
|
case ExitCode.Success => exitCodeFromStateOnFailure(state, prevState)
|
||||||
|
case x => x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// State's "next" field indicates the next action for the command processor to take
|
||||||
|
// we'll use that to determine if the command failed
|
||||||
|
private[this] def exitCodeFromStateNext(state: State): ExitCode = {
|
||||||
|
state.next match {
|
||||||
|
case State.Continue => ExitCode.Success
|
||||||
|
case State.ClearGlobalLog => ExitCode.Success
|
||||||
|
case State.KeepLastLog => ExitCode.Success
|
||||||
|
case ret: State.Return =>
|
||||||
|
ret.result match {
|
||||||
|
case exit: xsbti.Exit => ExitCode(exit.code().toLong)
|
||||||
|
case _: xsbti.Continue => ExitCode.Success
|
||||||
|
case _: xsbti.Reboot => ExitCode.Success
|
||||||
|
case x =>
|
||||||
|
val clazz = if (x eq null) "" else " (class: " + x.getClass + ")"
|
||||||
|
state.log debug s"Unknown main result: $x$clazz"
|
||||||
|
ExitCode.Unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the shell command specifies an onFailure so that if an exception is thrown
|
||||||
|
// it's handled by executing the shell again, instead of the state failing
|
||||||
|
// so we also use that to indicate that the execution failed
|
||||||
|
private[this] def exitCodeFromStateOnFailure(state: State, prevState: State): ExitCode =
|
||||||
|
if (prevState.onFailure.isDefined && state.onFailure.isEmpty) ExitCode(ErrorCodes.UnknownError)
|
||||||
|
else ExitCode.Success
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -240,7 +240,13 @@ final class NetworkChannel(val name: String,
|
||||||
if (isLanguageServerProtocol) {
|
if (isLanguageServerProtocol) {
|
||||||
event match {
|
event match {
|
||||||
case entry: StringEvent => logMessage(entry.level, entry.message)
|
case entry: StringEvent => logMessage(entry.level, entry.message)
|
||||||
case _ => langRespond(event, execId)
|
case entry: ExecStatusEvent =>
|
||||||
|
entry.exitCode match {
|
||||||
|
case None => langRespond(event, entry.execId)
|
||||||
|
case Some(0) => langRespond(event, entry.execId)
|
||||||
|
case Some(exitCode) => langError(entry.execId, exitCode, "")
|
||||||
|
}
|
||||||
|
case _ => langRespond(event, execId)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
contentType match {
|
contentType match {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue