Cleanup SbtHandler

This commit is contained in:
Dale Wijnand 2018-01-25 12:09:21 +00:00
parent 4debec0053
commit 89e501443c
No known key found for this signature in database
GPG Key ID: 4F256E3D151DF5EF
1 changed files with 23 additions and 20 deletions

View File

@ -22,41 +22,40 @@ final case class SbtInstance(process: Process, server: IPC.Server)
final class SbtHandler(remoteSbtCreator: RemoteSbtCreator) extends StatementHandler {
type State = Option[SbtInstance]
def initialState = None
def apply(command: String, arguments: List[String], i: Option[SbtInstance]): Option[SbtInstance] =
onSbtInstance(i) { (process, server) =>
onSbtInstance(i) { (_, server) =>
send((command :: arguments.map(escape)).mkString(" "), server)
receive(command + " failed", server)
receive(s"$command failed", server)
}
def onSbtInstance(i: Option[SbtInstance])(f: (Process, IPC.Server) => Unit): Option[SbtInstance] =
i match {
case Some(SbtInstance(_, server)) if server.isClosed =>
finish(i)
onNewSbtInstance(f)
case Some(SbtInstance(process, server)) =>
f(process, server)
i
case None =>
onNewSbtInstance(f)
case Some(SbtInstance(_, server)) if server.isClosed => finish(i); onNewSbtInstance(f)
case Some(SbtInstance(process, server)) => f(process, server); i
case None => onNewSbtInstance(f)
}
private[this] def onNewSbtInstance(f: (Process, IPC.Server) => Unit): Option[SbtInstance] = {
val server = IPC.unmanagedServer
val p = try newRemote(server)
catch { case e: Throwable => server.close(); throw e }
val ai = Some(SbtInstance(p, server))
val p =
try newRemote(server)
catch { case e: Throwable => server.close(); throw e }
val i = Some(SbtInstance(p, server))
try f(p, server)
catch {
case e: Throwable =>
// TODO: closing is necessary only because StatementHandler uses exceptions for signaling errors
finish(ai); throw e
finish(i)
throw e
}
ai
i
}
def finish(state: Option[SbtInstance]) = state match {
def finish(state: State) = state match {
case None =>
case Some(SbtInstance(process, server)) =>
try {
send("exit", server)
@ -65,24 +64,28 @@ final class SbtHandler(remoteSbtCreator: RemoteSbtCreator) extends StatementHand
} catch {
case _: IOException => process.destroy()
}
case None =>
}
def send(message: String, server: IPC.Server) = server.connection { _.send(message) }
def send(message: String, server: IPC.Server) = server.connection(_.send(message))
def receive(errorMessage: String, server: IPC.Server) =
server.connection { ipc =>
val resultMessage = ipc.receive
if (!resultMessage.toBoolean) throw new TestFailed(errorMessage)
}
def newRemote(server: IPC.Server): Process = {
val p = remoteSbtCreator.newRemote(server)
try receive("Remote sbt initialization failed", server)
catch { case _: SocketException => throw new TestFailed("Remote sbt initialization failed") }
p
}
import java.util.regex.Pattern.{ quote => q }
// if the argument contains spaces, enclose it in quotes, quoting backslashes and quotes
def escape(argument: String) =
def escape(argument: String) = {
import java.util.regex.Pattern.{ quote => q }
if (argument.contains(" "))
"\"" + argument.replaceAll(q("""\"""), """\\""").replaceAll(q("\""), "\\\"") + "\""
else argument
}
}