Use Exec in State

This commit is contained in:
Eugene Yokota 2016-12-06 15:03:39 -05:00
parent d96ef58605
commit 1bf50e10c8
21 changed files with 238 additions and 62 deletions

View File

@ -0,0 +1,32 @@
/**
* This code is generated using sbt-datatype.
*/
// DO NOT EDIT MANUALLY
package sbt
final class CommandSource private (
val channelName: String) extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: CommandSource => (this.channelName == x.channelName)
case _ => false
}
override def hashCode: Int = {
37 * (17 + channelName.##)
}
override def toString: String = {
"CommandSource(" + channelName + ")"
}
protected[this] def copy(channelName: String = channelName): CommandSource = {
new CommandSource(channelName)
}
def withChannelName(channelName: String): CommandSource = {
copy(channelName = channelName)
}
}
object CommandSource {
def apply(channelName: String): CommandSource = new CommandSource(channelName)
}

View File

@ -0,0 +1,40 @@
/**
* This code is generated using sbt-datatype.
*/
// DO NOT EDIT MANUALLY
package sbt
final class Exec private (
val commandLine: String,
val source: Option[sbt.CommandSource]) extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: Exec => (this.commandLine == x.commandLine) && (this.source == x.source)
case _ => false
}
override def hashCode: Int = {
37 * (37 * (17 + commandLine.##) + source.##)
}
override def toString: String = {
"Exec(" + commandLine + ", " + source + ")"
}
protected[this] def copy(commandLine: String = commandLine, source: Option[sbt.CommandSource] = source): Exec = {
new Exec(commandLine, source)
}
def withCommandLine(commandLine: String): Exec = {
copy(commandLine = commandLine)
}
def withSource(source: Option[sbt.CommandSource]): Exec = {
copy(source = source)
}
def withSource(source: sbt.CommandSource): Exec = {
copy(source = Option(source))
}
}
object Exec {
def apply(commandLine: String, source: Option[sbt.CommandSource]): Exec = new Exec(commandLine, source)
def apply(commandLine: String, source: sbt.CommandSource): Exec = new Exec(commandLine, Option(source))
}

View File

@ -0,0 +1,11 @@
package sbt
@target(Scala)
type Exec {
commandLine: String!
source: sbt.CommandSource
}
type CommandSource {
channelName: String!
}

View File

@ -6,7 +6,7 @@ import sbt.internal.util.complete.{ Completion, Completions, DefaultParsers, His
import sbt.internal.util.Types.{ const, idFun } import sbt.internal.util.Types.{ const, idFun }
import sbt.internal.inc.classpath.ClasspathUtilities.toLoader import sbt.internal.inc.classpath.ClasspathUtilities.toLoader
import sbt.internal.inc.ModuleUtilities import sbt.internal.inc.ModuleUtilities
import sbt.internal.{ Exec, ConsolePromptEvent, ConsoleUnpromptEvent } import sbt.internal.{ ConsolePromptEvent, ConsoleUnpromptEvent }
import sbt.internal.client.NetworkClient import sbt.internal.client.NetworkClient
import DefaultParsers._ import DefaultParsers._
import Function.tupled import Function.tupled
@ -82,13 +82,13 @@ object BasicCommands {
state state
} }
def multiParser(s: State): Parser[Seq[String]] = def multiParser(s: State): Parser[List[String]] =
{ {
val nonSemi = token(charClass(_ != ';').+, hide = const(true)) val nonSemi = token(charClass(_ != ';').+, hide = const(true))
(token(';' ~> OptSpace) flatMap { _ => matched((s.combinedParser & nonSemi) | nonSemi) <~ token(OptSpace) } map (_.trim)).+ (token(';' ~> OptSpace) flatMap { _ => matched((s.combinedParser & nonSemi) | nonSemi) <~ token(OptSpace) } map (_.trim)).+ map { _.toList }
} }
def multiApplied(s: State) = def multiApplied(s: State): Parser[() => State] =
Command.applyEffect(multiParser(s))(_ ::: s) Command.applyEffect(multiParser(s))(_ ::: s)
def multi = Command.custom(multiApplied, Help(Multi, MultiBrief, MultiDetailed)) def multi = Command.custom(multiApplied, Help(Multi, MultiBrief, MultiDetailed))
@ -101,11 +101,11 @@ object BasicCommands {
if (s.remainingCommands.isEmpty) arg :: s else s if (s.remainingCommands.isEmpty) arg :: s else s
} }
def append = Command(AppendCommand, Help.more(AppendCommand, AppendLastDetailed))(otherCommandParser) { (s, arg) => def append = Command(AppendCommand, Help.more(AppendCommand, AppendLastDetailed))(otherCommandParser) { (s, arg) =>
s.copy(remainingCommands = s.remainingCommands :+ arg) s.copy(remainingCommands = s.remainingCommands :+ Exec(arg, s.source))
} }
def setOnFailure = Command(OnFailure, Help.more(OnFailure, OnFailureDetailed))(otherCommandParser) { (s, arg) => def setOnFailure = Command(OnFailure, Help.more(OnFailure, OnFailureDetailed))(otherCommandParser) { (s, arg) =>
s.copy(onFailure = Some(arg)) s.copy(onFailure = Some(Exec(arg, s.source)))
} }
private[sbt] def compatCommands = Seq( private[sbt] def compatCommands = Seq(
Command.command(Compat.ClearOnFailure) { s => Command.command(Compat.ClearOnFailure) { s =>
@ -114,7 +114,7 @@ object BasicCommands {
}, },
Command.arb(s => token(Compat.OnFailure, hide = const(true)).flatMap(x => otherCommandParser(s))) { (s, arg) => Command.arb(s => token(Compat.OnFailure, hide = const(true)).flatMap(x => otherCommandParser(s))) { (s, arg) =>
s.log.warn(Compat.OnFailureDeprecated) s.log.warn(Compat.OnFailureDeprecated)
s.copy(onFailure = Some(arg)) s.copy(onFailure = Some(Exec(arg, s.source)))
}, },
Command.command(Compat.FailureWall) { s => Command.command(Compat.FailureWall) { s =>
s.log.warn(Compat.FailureWallDeprecated) s.log.warn(Compat.FailureWallDeprecated)
@ -187,7 +187,7 @@ object BasicCommands {
val line = reader.readLine(prompt) val line = reader.readLine(prompt)
line match { line match {
case Some(line) => case Some(line) =>
val newState = s.copy(onFailure = Some(Shell), remainingCommands = line +: Shell +: s.remainingCommands).setInteractive(true) val newState = s.copy(onFailure = Some(Exec(Shell, None)), remainingCommands = Exec(line, s.source) +: Exec(Shell, None) +: s.remainingCommands).setInteractive(true)
if (line.trim.isEmpty) newState else newState.clearGlobalLog if (line.trim.isEmpty) newState else newState.clearGlobalLog
case None => s.setInteractive(false) case None => s.setInteractive(false)
} }
@ -197,9 +197,11 @@ object BasicCommands {
val exchange = State.exchange val exchange = State.exchange
val s1 = exchange.run(s0) val s1 = exchange.run(s0)
exchange.publishEvent(ConsolePromptEvent(s0)) exchange.publishEvent(ConsolePromptEvent(s0))
val Exec(line, source) = exchange.blockUntilNextExec val exec: Exec = exchange.blockUntilNextExec
val line = exec.commandLine
val source = exec.source
println(s"server (line, source): ($line, $source)") println(s"server (line, source): ($line, $source)")
val newState = s1.copy(onFailure = Some(Server), remainingCommands = line +: Server +: s1.remainingCommands).setInteractive(true) val newState = s1.copy(onFailure = Some(Exec(Server, None)), remainingCommands = Exec(line, source) +: Exec(Server, None) +: s1.remainingCommands).setInteractive(true)
exchange.publishEvent(ConsoleUnpromptEvent(source)) exchange.publishEvent(ConsoleUnpromptEvent(source))
if (line.trim.isEmpty) newState if (line.trim.isEmpty) newState
else newState.clearGlobalLog else newState.clearGlobalLog
@ -212,8 +214,8 @@ object BasicCommands {
applyEffect(p)({ inputArg => applyEffect(p)({ inputArg =>
val arguments = inputArg.toList ++ val arguments = inputArg.toList ++
(s0.remainingCommands.toList match { (s0.remainingCommands.toList match {
case "shell" :: Nil => Nil case e :: Nil if e.commandLine == "shell" :: Nil => Nil
case xs => xs case xs => xs map { _.commandLine }
}) })
NetworkClient.run(arguments) NetworkClient.run(arguments)
"exit" :: s0.copy(remainingCommands = Nil) "exit" :: s0.copy(remainingCommands = Nil)
@ -233,7 +235,7 @@ object BasicCommands {
val port = math.abs(portAndSuccess) val port = math.abs(portAndSuccess)
val previousSuccess = portAndSuccess >= 0 val previousSuccess = portAndSuccess >= 0
readMessage(port, previousSuccess) match { readMessage(port, previousSuccess) match {
case Some(message) => (message :: (ReadCommand + " " + port) :: s).copy(onFailure = Some(ReadCommand + " " + (-port))) case Some(message) => (message :: (ReadCommand + " " + port) :: s).copy(onFailure = Some(Exec(ReadCommand + " " + (-port), s.source)))
case None => case None =>
System.err.println("Connection closed.") System.err.println("Connection closed.")
s.fail s.fail
@ -241,7 +243,7 @@ object BasicCommands {
case Right(from) => case Right(from) =>
val notFound = notReadable(from) val notFound = notReadable(from)
if (notFound.isEmpty) if (notFound.isEmpty)
readLines(from) ::: s // this means that all commands from all files are loaded, parsed, and inserted before any are executed readLines(from).toList ::: s // this means that all commands from all files are loaded, parsed, and inserted before any are executed
else { else {
s.log.error("Command file(s) not readable: \n\t" + notFound.mkString("\n\t")) s.log.error("Command file(s) not readable: \n\t" + notFound.mkString("\n\t"))
s s

View File

@ -11,6 +11,6 @@ object BasicKeys {
val serverPort = AttributeKey[Int]("server-port", "The port number used by server command.", 10000) val serverPort = AttributeKey[Int]("server-port", "The port number used by server command.", 10000)
private[sbt] val interactive = AttributeKey[Boolean]("interactive", "True if commands are currently being entered from an interactive environment.", 10) private[sbt] val interactive = AttributeKey[Boolean]("interactive", "True if commands are currently being entered from an interactive environment.", 10)
private[sbt] val classLoaderCache = AttributeKey[ClassLoaderCache]("class-loader-cache", "Caches class loaders based on the classpath entries and last modified times.", 10) private[sbt] val classLoaderCache = AttributeKey[ClassLoaderCache]("class-loader-cache", "Caches class loaders based on the classpath entries and last modified times.", 10)
private[sbt] val OnFailureStack = AttributeKey[List[Option[String]]]("on-failure-stack", "Stack that remembers on-failure handlers.", 10) private[sbt] val OnFailureStack = AttributeKey[List[Option[Exec]]]("on-failure-stack", "Stack that remembers on-failure handlers.", 10)
private[sbt] val explicitGlobalLogLevels = AttributeKey[Boolean]("explicit-global-log-levels", "True if the global logging levels were explicitly set by the user.", 10) private[sbt] val explicitGlobalLogLevels = AttributeKey[Boolean]("explicit-global-log-levels", "True if the global logging levels were explicitly set by the user.", 10)
} }

View File

@ -89,16 +89,16 @@ object Command {
} }
/** This is the main function State transfer function of the sbt command processing, called by MainLoop.next, */ /** This is the main function State transfer function of the sbt command processing, called by MainLoop.next, */
def process(command: String, state: State): State = def process(command: Exec, state: State): State =
{ {
val parser = combine(state.definedCommands) val parser = combine(state.definedCommands)
val newState = parse(command, parser(state)) match { val newState = parse(command.commandLine, parser(state)) match {
case Right(s) => s() // apply command. command side effects happen here case Right(s) => s() // apply command. command side effects happen here
case Left(errMsg) => case Left(errMsg) =>
state.log.error(errMsg) state.log.error(errMsg)
state.fail state.fail
} }
State.exchange.publishEvent(ExecStatusEvent("Ready", newState.remainingCommands.toVector)) State.exchange.publishEvent(ExecStatusEvent("Ready", newState.remainingCommands.toVector map { _.commandLine }))
newState newState
} }
def invalidValue(label: String, allowed: Iterable[String])(value: String): String = def invalidValue(label: String, allowed: Iterable[String])(value: String): String =

View File

@ -27,11 +27,12 @@ final case class State(
configuration: xsbti.AppConfiguration, configuration: xsbti.AppConfiguration,
definedCommands: Seq[Command], definedCommands: Seq[Command],
exitHooks: Set[ExitHook], exitHooks: Set[ExitHook],
onFailure: Option[String], onFailure: Option[Exec],
remainingCommands: Seq[String], remainingCommands: List[Exec],
history: State.History, history: State.History,
attributes: AttributeMap, attributes: AttributeMap,
globalLogging: GlobalLogging, globalLogging: GlobalLogging,
source: Option[CommandSource],
next: State.Next next: State.Next
) extends Identity { ) extends Identity {
lazy val combinedParser = Command.combine(definedCommands)(this) lazy val combinedParser = Command.combine(definedCommands)(this)
@ -45,14 +46,20 @@ trait Identity {
/** Convenience methods for State transformations and operations. */ /** Convenience methods for State transformations and operations. */
trait StateOps { trait StateOps {
def process(f: (String, State) => State): State def process(f: (Exec, State) => State): State
/** Schedules `commands` to be run before any remaining commands.*/ /** Schedules `commands` to be run before any remaining commands.*/
def :::(commands: Seq[String]): State def :::(newCommands: List[String]): State
/** Schedules `commands` to be run before any remaining commands.*/
def ++:(newCommands: List[Exec]): State
/** Schedules `command` to be run before any remaining commands.*/ /** Schedules `command` to be run before any remaining commands.*/
def ::(command: String): State def ::(command: String): State
/** Schedules `command` to be run before any remaining commands.*/
def +:(command: Exec): State
/** Sets the next command processing action to be to continue processing the next command.*/ /** Sets the next command processing action to be to continue processing the next command.*/
def continue: State def continue: State
@ -69,6 +76,9 @@ trait StateOps {
/** Sets the next command processing action to do.*/ /** Sets the next command processing action to do.*/
def setNext(n: State.Next): State def setNext(n: State.Next): State
/** Sets the current command source channel.*/
def setSource(source: CommandSource): State
@deprecated("Use setNext", "0.11.0") def setResult(ro: Option[xsbti.MainResult]): State @deprecated("Use setNext", "0.11.0") def setResult(ro: Option[xsbti.MainResult]): State
/** /**
@ -158,9 +168,9 @@ object State {
* @param executed the list of the most recently executed commands, with the most recent command first. * @param executed the list of the most recently executed commands, with the most recent command first.
* @param maxSize the maximum number of commands to keep, or 0 to keep an unlimited number. * @param maxSize the maximum number of commands to keep, or 0 to keep an unlimited number.
*/ */
final class History private[State] (val executed: Seq[String], val maxSize: Int) { final class History private[State] (val executed: Seq[Exec], val maxSize: Int) {
/** Adds `command` as the most recently executed command.*/ /** Adds `command` as the most recently executed command.*/
def ::(command: String): History = def ::(command: Exec): History =
{ {
val prependTo = if (maxSize > 0 && executed.size >= maxSize) executed.take(maxSize - 1) else executed val prependTo = if (maxSize > 0 && executed.size >= maxSize) executed.take(maxSize - 1) else executed
new History(command +: prependTo, maxSize) new History(command +: prependTo, maxSize)
@ -168,8 +178,8 @@ object State {
/** Changes the maximum number of commands kept, adjusting the current history if necessary.*/ /** Changes the maximum number of commands kept, adjusting the current history if necessary.*/
def setMaxSize(size: Int): History = def setMaxSize(size: Int): History =
new History(if (size <= 0) executed else executed.take(size), size) new History(if (size <= 0) executed else executed.take(size), size)
def currentOption: Option[String] = executed.headOption def currentOption: Option[Exec] = executed.headOption
def previous: Option[String] = executed.drop(1).headOption def previous: Option[Exec] = executed.drop(1).headOption
} }
/** Constructs an empty command History with a default, finite command limit.*/ /** Constructs an empty command History with a default, finite command limit.*/
def newHistory = new History(Vector.empty, HistoryCommands.MaxLines) def newHistory = new History(Vector.empty, HistoryCommands.MaxLines)
@ -177,29 +187,37 @@ object State {
def defaultReload(state: State): Reboot = def defaultReload(state: State): Reboot =
{ {
val app = state.configuration.provider val app = state.configuration.provider
new Reboot(app.scalaProvider.version, state.remainingCommands, app.id, state.configuration.baseDirectory) new Reboot(
app.scalaProvider.version,
state.remainingCommands map { case e: Exec => e.commandLine },
app.id, state.configuration.baseDirectory
)
} }
private[sbt] lazy val exchange = new CommandExchange() private[sbt] lazy val exchange = new CommandExchange()
/** Provides operations and transformations on State. */ /** Provides operations and transformations on State. */
implicit def stateOps(s: State): StateOps = new StateOps { implicit def stateOps(s: State): StateOps = new StateOps {
def process(f: (String, State) => State): State = def process(f: (Exec, State) => State): State =
s.remainingCommands match { s.remainingCommands match {
case Seq() => exit(true) case List() => exit(true)
case Seq(x, xs @ _*) => case x :: xs =>
log.debug(s"> $x") log.debug(s"> $x")
f(x, s.copy(remainingCommands = xs, history = x :: s.history)) f(x, s.copy(remainingCommands = xs, history = x :: s.history))
} }
def :::(newCommands: Seq[String]): State = s.copy(remainingCommands = newCommands ++ s.remainingCommands)
def ::(command: String): State = (command :: Nil) ::: this def :::(newCommands: List[String]): State = ++:(newCommands map { Exec(_, s.source) })
def ++:(newCommands: List[Exec]): State = s.copy(remainingCommands = newCommands ::: s.remainingCommands)
def ::(command: String): State = +:(Exec(command, s.source))
def +:(command: Exec): State = (command :: Nil) ++: this
def ++(newCommands: Seq[Command]): State = s.copy(definedCommands = (s.definedCommands ++ newCommands).distinct) def ++(newCommands: Seq[Command]): State = s.copy(definedCommands = (s.definedCommands ++ newCommands).distinct)
def +(newCommand: Command): State = this ++ (newCommand :: Nil) def +(newCommand: Command): State = this ++ (newCommand :: Nil)
def baseDir: File = s.configuration.baseDirectory def baseDir: File = s.configuration.baseDirectory
def setNext(n: Next) = s.copy(next = n) def setNext(n: Next) = s.copy(next = n)
def setSource(x: CommandSource): State = s.copy(source = Some(x))
def setResult(ro: Option[xsbti.MainResult]) = ro match { case None => continue; case Some(r) => setNext(new Return(r)) } def setResult(ro: Option[xsbti.MainResult]) = ro match { case None => continue; case Some(r) => setNext(new Return(r)) }
def continue = setNext(Continue) def continue = setNext(Continue)
def reboot(full: Boolean) = { runExitHooks(); throw new xsbti.FullReload(s.remainingCommands.toArray, full) } def reboot(full: Boolean) = { runExitHooks(); throw new xsbti.FullReload((s.remainingCommands map { case e: Exec => e.commandLine }).toArray, full) }
def reload = runExitHooks().setNext(new Return(defaultReload(s))) def reload = runExitHooks().setNext(new Return(defaultReload(s)))
def clearGlobalLog = setNext(ClearGlobalLog) def clearGlobalLog = setNext(ClearGlobalLog)
def keepLastLog = setNext(KeepLastLog) def keepLastLog = setNext(KeepLastLog)
@ -220,7 +238,7 @@ object State {
else else
applyOnFailure(s, remaining, s.copy(remainingCommands = remaining)) applyOnFailure(s, remaining, s.copy(remainingCommands = remaining))
} }
private[this] def applyOnFailure(s: State, remaining: Seq[String], noHandler: => State): State = private[this] def applyOnFailure(s: State, remaining: List[Exec], noHandler: => State): State =
s.onFailure match { s.onFailure match {
case Some(c) => s.copy(remainingCommands = c +: remaining, onFailure = None) case Some(c) => s.copy(remainingCommands = c +: remaining, onFailure = None)
case None => noHandler case None => noHandler

View File

@ -18,11 +18,12 @@ abstract class CommandChannel {
def publishEvent(event: EventMessage): Unit def publishEvent(event: EventMessage): Unit
def publishBytes(bytes: Array[Byte]): Unit def publishBytes(bytes: Array[Byte]): Unit
def shutdown(): Unit def shutdown(): Unit
def name: String
} }
case class Exec(commandLine: String, source: Option[CommandSource]) // case class Exec(commandLine: String, source: Option[CommandSource])
case class CommandSource(channelName: String) // case class CommandSource(channelName: String)
/* /*
* This is a data passed specifically for local prompting console. * This is a data passed specifically for local prompting console.

View File

@ -5,7 +5,7 @@ import java.net.SocketException
import java.util.concurrent.ConcurrentLinkedQueue import java.util.concurrent.ConcurrentLinkedQueue
import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger
import sbt.internal.server._ import sbt.internal.server._
import sbt.protocol.{ EventMessage, Serialization } import sbt.protocol.{ EventMessage, Serialization, ChannelAcceptedEvent }
import scala.collection.mutable.ListBuffer import scala.collection.mutable.ListBuffer
import scala.annotation.tailrec import scala.annotation.tailrec
import BasicKeys.serverPort import BasicKeys.serverPort
@ -74,6 +74,7 @@ private[sbt] final class CommandExchange {
s.log.info(s"new client connected from: ${socket.getPort}") s.log.info(s"new client connected from: ${socket.getPort}")
val channel = new NetworkChannel(newChannelName, socket) val channel = new NetworkChannel(newChannelName, socket)
subscribe(channel) subscribe(channel)
channel.publishEvent(ChannelAcceptedEvent(channel.name))
} }
server match { server match {
case Some(x) => // do nothing case Some(x) => // do nothing

View File

@ -6,7 +6,7 @@ import BasicKeys._
import java.io.File import java.io.File
import sbt.protocol.EventMessage import sbt.protocol.EventMessage
private[sbt] final class ConsoleChannel(name: String) extends CommandChannel { private[sbt] final class ConsoleChannel(val name: String) extends CommandChannel {
private var askUserThread: Option[Thread] = None private var askUserThread: Option[Thread] = None
def makeAskUserThread(s: State): Thread = new Thread("ask-user-thread") { def makeAskUserThread(s: State): Thread = new Thread("ask-user-thread") {
val history = (s get historyPath) getOrElse Some(new File(s.baseDir, ".history")) val history = (s get historyPath) getOrElse Some(new File(s.baseDir, ".history"))

View File

@ -11,7 +11,8 @@ import sbt.protocol._
import sbt.internal.util.JLine import sbt.internal.util.JLine
import java.util.concurrent.atomic.{ AtomicBoolean, AtomicReference } import java.util.concurrent.atomic.{ AtomicBoolean, AtomicReference }
class NetworkClient(arguments: List[String]) { class NetworkClient(arguments: List[String]) { self =>
private val channelName = new AtomicReference("_")
private val status = new AtomicReference("Ready") private val status = new AtomicReference("Ready")
private val lock: AnyRef = new AnyRef {} private val lock: AnyRef = new AnyRef {}
private val running = new AtomicBoolean(true) private val running = new AtomicBoolean(true)
@ -38,15 +39,7 @@ class NetworkClient(arguments: List[String]) {
println(s"client on port $port") println(s"client on port $port")
val socket = new Socket(InetAddress.getByName(host), port) val socket = new Socket(InetAddress.getByName(host), port)
new ServerConnection(socket) { new ServerConnection(socket) {
override def onEvent(event: EventMessage): Unit = override def onEvent(event: EventMessage): Unit = self.onEvent(event)
event match {
case e: ExecStatusEvent =>
lock.synchronized {
status.set(e.status)
}
println(event)
case e => println(e.toString)
}
override def onShutdown(): Unit = override def onShutdown(): Unit =
{ {
running.set(false) running.set(false)
@ -54,6 +47,17 @@ class NetworkClient(arguments: List[String]) {
} }
} }
def onEvent(event: EventMessage): Unit =
event match {
case e: ChannelAcceptedEvent =>
channelName.set(e.channelName)
println(event)
case e: ExecStatusEvent =>
status.set(e.status)
println(event)
case e => println(e.toString)
}
def start(): Unit = def start(): Unit =
{ {
val reader = JLine.simple(None, JLine.HandleCONT, injectThreadSleep = true) val reader = JLine.simple(None, JLine.HandleCONT, injectThreadSleep = true)

View File

@ -9,7 +9,7 @@ import java.net.{ Socket, SocketTimeoutException }
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
import sbt.protocol.{ Serialization, CommandMessage, ExecCommand, EventMessage } import sbt.protocol.{ Serialization, CommandMessage, ExecCommand, EventMessage }
final class NetworkChannel(name: String, connection: Socket) extends CommandChannel { final class NetworkChannel(val name: String, connection: Socket) extends CommandChannel {
private val running = new AtomicBoolean(true) private val running = new AtomicBoolean(true)
private val delimiter: Byte = '\n'.toByte private val delimiter: Byte = '\n'.toByte
private val out = connection.getOutputStream private val out = connection.getOutputStream
@ -50,7 +50,11 @@ final class NetworkChannel(name: String, connection: Socket) extends CommandChan
} }
thread.start() thread.start()
def publishEvent(event: EventMessage): Unit = () def publishEvent(event: EventMessage): Unit =
{
val bytes = Serialization.serializeEvent(event)
publishBytes(bytes)
}
def publishBytes(event: Array[Byte]): Unit = def publishBytes(event: Array[Byte]): Unit =
{ {

View File

@ -137,7 +137,7 @@ object Cross {
Seq(s"$SwitchCommand $verbose $version", projects.map(_ + "/" + aggCommand).mkString("all ", " ", "")) Seq(s"$SwitchCommand $verbose $version", projects.map(_ + "/" + aggCommand).mkString("all ", " ", ""))
} }
allCommands ::: CrossRestoreSessionCommand :: captureCurrentSession(state, x) allCommands.toList ::: CrossRestoreSessionCommand :: captureCurrentSession(state, x)
} }
} }
@ -169,7 +169,7 @@ object Cross {
private def switchCommandImpl(state: State, args: Switch): State = { private def switchCommandImpl(state: State, args: Switch): State = {
val switchedState = switchScalaVersion(args, state) val switchedState = switchScalaVersion(args, state)
args.command.toSeq ::: switchedState args.command.toList ::: switchedState
} }
private def switchScalaVersion(switch: Switch, state: State): State = { private def switchScalaVersion(switch: Switch, state: State): State = {

View File

@ -94,9 +94,9 @@ object StandardMain {
import BasicCommandStrings.isEarlyCommand import BasicCommandStrings.isEarlyCommand
val userCommands = configuration.arguments.map(_.trim) val userCommands = configuration.arguments.map(_.trim)
val (earlyCommands, normalCommands) = (preCommands ++ userCommands).partition(isEarlyCommand) val (earlyCommands, normalCommands) = (preCommands ++ userCommands).partition(isEarlyCommand)
val commands = earlyCommands ++ normalCommands val commands = (earlyCommands ++ normalCommands).toList map { x => Exec(x, None) }
val initAttrs = BuiltinCommands.initialAttributes val initAttrs = BuiltinCommands.initialAttributes
val s = State(configuration, initialDefinitions, Set.empty, None, commands, State.newHistory, initAttrs, initialGlobalLogging, State.Continue) val s = State(configuration, initialDefinitions, Set.empty, None, commands, State.newHistory, initAttrs, initialGlobalLogging, None, State.Continue)
s.initializeClassLoaderCache s.initializeClassLoaderCache
} }
} }
@ -129,7 +129,7 @@ object BuiltinCommands {
// This parser schedules the default boot commands unless overridden by an alias // This parser schedules the default boot commands unless overridden by an alias
def bootParser(s: State) = def bootParser(s: State) =
{ {
val orElse = () => DefaultBootCommands ::: s val orElse = () => DefaultBootCommands.toList ::: s
delegateToAlias(BootCommand, success(orElse))(s) delegateToAlias(BootCommand, success(orElse))(s)
} }
@ -242,7 +242,7 @@ object BuiltinCommands {
} }
def initialize = Command.command(InitCommand) { s => def initialize = Command.command(InitCommand) { s =>
/*"load-commands -base ~/.sbt/commands" :: */ readLines(readable(sbtRCs(s))) ::: s /*"load-commands -base ~/.sbt/commands" :: */ readLines(readable(sbtRCs(s))).toList ::: s
} }
def eval = Command.single(EvalCommand, Help.more(EvalCommand, evalDetailed)) { (s, arg) => def eval = Command.single(EvalCommand, Help.more(EvalCommand, evalDetailed)) { (s, arg) =>

View File

@ -20,7 +20,7 @@ object IvyConsole {
final val Name = "ivy-console" final val Name = "ivy-console"
lazy val command = lazy val command =
Command.command(Name) { state => Command.command(Name) { state =>
val Dependencies(managed, repos, unmanaged) = parseDependencies(state.remainingCommands, state.log) val Dependencies(managed, repos, unmanaged) = parseDependencies(state.remainingCommands map { _.commandLine }, state.log)
val base = new File(CommandUtil.bootDirectory(state), Name) val base = new File(CommandUtil.bootDirectory(state), Name)
IO.createDirectory(base) IO.createDirectory(base)
@ -39,7 +39,7 @@ object IvyConsole {
val append = Load.transformSettings(Load.projectScope(currentRef), currentRef.build, rootProject, depSettings) val append = Load.transformSettings(Load.projectScope(currentRef), currentRef.build, rootProject, depSettings)
val newStructure = Load.reapply(session.original ++ append, structure) val newStructure = Load.reapply(session.original ++ append, structure)
val newState = state.copy(remainingCommands = "console-quick" :: Nil) val newState = state.copy(remainingCommands = Exec("console-quick", None) :: Nil)
Project.setProject(session, newStructure, newState) Project.setProject(session, newStructure, newState)
} }

View File

@ -19,7 +19,7 @@ object Script {
final val Name = "script" final val Name = "script"
lazy val command = lazy val command =
Command.command(Name) { state => Command.command(Name) { state =>
val scriptArg = state.remainingCommands.headOption getOrElse sys.error("No script file specified") val scriptArg = state.remainingCommands.headOption map { _.commandLine } getOrElse sys.error("No script file specified")
val scriptFile = new File(scriptArg).getAbsoluteFile val scriptFile = new File(scriptArg).getAbsoluteFile
val hash = Hash.halve(Hash.toHex(Hash(scriptFile.getAbsolutePath))) val hash = Hash.halve(Hash.toHex(Hash(scriptFile.getAbsolutePath)))
val base = new File(CommandUtil.bootDirectory(state), hash) val base = new File(CommandUtil.bootDirectory(state), hash)

View File

@ -0,0 +1,32 @@
/**
* This code is generated using sbt-datatype.
*/
// DO NOT EDIT MANUALLY
package sbt.protocol
final class ChannelAcceptedEvent private (
val channelName: String) extends sbt.protocol.EventMessage() with Serializable {
override def equals(o: Any): Boolean = o match {
case x: ChannelAcceptedEvent => (this.channelName == x.channelName)
case _ => false
}
override def hashCode: Int = {
37 * (17 + channelName.##)
}
override def toString: String = {
"ChannelAcceptedEvent(" + channelName + ")"
}
protected[this] def copy(channelName: String = channelName): ChannelAcceptedEvent = {
new ChannelAcceptedEvent(channelName)
}
def withChannelName(channelName: String): ChannelAcceptedEvent = {
copy(channelName = channelName)
}
}
object ChannelAcceptedEvent {
def apply(channelName: String): ChannelAcceptedEvent = new ChannelAcceptedEvent(channelName)
}

View File

@ -0,0 +1,27 @@
/**
* This code is generated using sbt-datatype.
*/
// DO NOT EDIT MANUALLY
package sbt.protocol.codec
import _root_.sjsonnew.{ deserializationError, serializationError, Builder, JsonFormat, Unbuilder }
trait ChannelAcceptedEventFormats { self: sjsonnew.BasicJsonProtocol =>
implicit lazy val ChannelAcceptedEventFormat: JsonFormat[sbt.protocol.ChannelAcceptedEvent] = new JsonFormat[sbt.protocol.ChannelAcceptedEvent] {
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.protocol.ChannelAcceptedEvent = {
jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val channelName = unbuilder.readField[String]("channelName")
unbuilder.endObject()
sbt.protocol.ChannelAcceptedEvent(channelName)
case None =>
deserializationError("Expected JsObject but found None")
}
}
override def write[J](obj: sbt.protocol.ChannelAcceptedEvent, builder: Builder[J]): Unit = {
builder.beginObject()
builder.addField("channelName", obj.channelName)
builder.endObject()
}
}
}

View File

@ -5,6 +5,6 @@
// DO NOT EDIT MANUALLY // DO NOT EDIT MANUALLY
package sbt.protocol.codec package sbt.protocol.codec
import _root_.sjsonnew.{ deserializationError, serializationError, Builder, JsonFormat, Unbuilder } import _root_.sjsonnew.{ deserializationError, serializationError, Builder, JsonFormat, Unbuilder }
trait EventMessageFormats { self: sjsonnew.BasicJsonProtocol with sbt.protocol.codec.LogEventFormats with sbt.protocol.codec.ExecStatusEventFormats => trait EventMessageFormats { self: sjsonnew.BasicJsonProtocol with sbt.protocol.codec.ChannelAcceptedEventFormats with sbt.protocol.codec.LogEventFormats with sbt.protocol.codec.ExecStatusEventFormats =>
implicit lazy val EventMessageFormat: JsonFormat[sbt.protocol.EventMessage] = flatUnionFormat2[sbt.protocol.EventMessage, sbt.protocol.LogEvent, sbt.protocol.ExecStatusEvent]("type") implicit lazy val EventMessageFormat: JsonFormat[sbt.protocol.EventMessage] = flatUnionFormat3[sbt.protocol.EventMessage, sbt.protocol.ChannelAcceptedEvent, sbt.protocol.LogEvent, sbt.protocol.ExecStatusEvent]("type")
} }

View File

@ -4,5 +4,5 @@
// DO NOT EDIT MANUALLY // DO NOT EDIT MANUALLY
package sbt.protocol.codec package sbt.protocol.codec
trait JsonProtocol extends sjsonnew.BasicJsonProtocol with sbt.protocol.codec.ExecCommandFormats with sbt.protocol.codec.CommandMessageFormats with sbt.protocol.codec.LogEventFormats with sbt.protocol.codec.ExecStatusEventFormats with sbt.protocol.codec.EventMessageFormats trait JsonProtocol extends sjsonnew.BasicJsonProtocol with sbt.protocol.codec.ExecCommandFormats with sbt.protocol.codec.CommandMessageFormats with sbt.protocol.codec.ChannelAcceptedEventFormats with sbt.protocol.codec.LogEventFormats with sbt.protocol.codec.ExecStatusEventFormats with sbt.protocol.codec.EventMessageFormats
object JsonProtocol extends JsonProtocol object JsonProtocol extends JsonProtocol

View File

@ -17,6 +17,10 @@ type ExecCommand implements CommandMessage {
interface EventMessage { interface EventMessage {
} }
type ChannelAcceptedEvent implements EventMessage {
channelName: String!
}
## Log event. ## Log event.
type LogEvent implements EventMessage { type LogEvent implements EventMessage {
level: String! level: String!