diff --git a/main-command/src/main/contraband-scala/sbt/CommandSource.scala b/main-command/src/main/contraband-scala/sbt/CommandSource.scala new file mode 100644 index 000000000..08b399ea1 --- /dev/null +++ b/main-command/src/main/contraband-scala/sbt/CommandSource.scala @@ -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) +} diff --git a/main-command/src/main/contraband-scala/sbt/Exec.scala b/main-command/src/main/contraband-scala/sbt/Exec.scala new file mode 100644 index 000000000..e618f49a7 --- /dev/null +++ b/main-command/src/main/contraband-scala/sbt/Exec.scala @@ -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)) +} diff --git a/main-command/src/main/contraband/state.contra b/main-command/src/main/contraband/state.contra new file mode 100644 index 000000000..b319ecb56 --- /dev/null +++ b/main-command/src/main/contraband/state.contra @@ -0,0 +1,11 @@ +package sbt +@target(Scala) + +type Exec { + commandLine: String! + source: sbt.CommandSource +} + +type CommandSource { + channelName: String! +} diff --git a/main-command/src/main/scala/sbt/BasicCommands.scala b/main-command/src/main/scala/sbt/BasicCommands.scala index 51e8ba9d8..caa1e0906 100644 --- a/main-command/src/main/scala/sbt/BasicCommands.scala +++ b/main-command/src/main/scala/sbt/BasicCommands.scala @@ -6,7 +6,7 @@ import sbt.internal.util.complete.{ Completion, Completions, DefaultParsers, His import sbt.internal.util.Types.{ const, idFun } import sbt.internal.inc.classpath.ClasspathUtilities.toLoader import sbt.internal.inc.ModuleUtilities -import sbt.internal.{ Exec, ConsolePromptEvent, ConsoleUnpromptEvent } +import sbt.internal.{ ConsolePromptEvent, ConsoleUnpromptEvent } import sbt.internal.client.NetworkClient import DefaultParsers._ import Function.tupled @@ -82,13 +82,13 @@ object BasicCommands { state } - def multiParser(s: State): Parser[Seq[String]] = + def multiParser(s: State): Parser[List[String]] = { 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) def multi = Command.custom(multiApplied, Help(Multi, MultiBrief, MultiDetailed)) @@ -101,11 +101,11 @@ object BasicCommands { if (s.remainingCommands.isEmpty) arg :: s else s } 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) => - s.copy(onFailure = Some(arg)) + s.copy(onFailure = Some(Exec(arg, s.source))) } private[sbt] def compatCommands = Seq( 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) => s.log.warn(Compat.OnFailureDeprecated) - s.copy(onFailure = Some(arg)) + s.copy(onFailure = Some(Exec(arg, s.source))) }, Command.command(Compat.FailureWall) { s => s.log.warn(Compat.FailureWallDeprecated) @@ -187,7 +187,7 @@ object BasicCommands { val line = reader.readLine(prompt) line match { 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 case None => s.setInteractive(false) } @@ -197,9 +197,11 @@ object BasicCommands { val exchange = State.exchange val s1 = exchange.run(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)") - 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)) if (line.trim.isEmpty) newState else newState.clearGlobalLog @@ -212,8 +214,8 @@ object BasicCommands { applyEffect(p)({ inputArg => val arguments = inputArg.toList ++ (s0.remainingCommands.toList match { - case "shell" :: Nil => Nil - case xs => xs + case e :: Nil if e.commandLine == "shell" :: Nil => Nil + case xs => xs map { _.commandLine } }) NetworkClient.run(arguments) "exit" :: s0.copy(remainingCommands = Nil) @@ -233,7 +235,7 @@ object BasicCommands { val port = math.abs(portAndSuccess) val previousSuccess = portAndSuccess >= 0 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 => System.err.println("Connection closed.") s.fail @@ -241,7 +243,7 @@ object BasicCommands { case Right(from) => val notFound = notReadable(from) 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 { s.log.error("Command file(s) not readable: \n\t" + notFound.mkString("\n\t")) s diff --git a/main-command/src/main/scala/sbt/BasicKeys.scala b/main-command/src/main/scala/sbt/BasicKeys.scala index d42a1d381..3b174083e 100644 --- a/main-command/src/main/scala/sbt/BasicKeys.scala +++ b/main-command/src/main/scala/sbt/BasicKeys.scala @@ -11,6 +11,6 @@ object BasicKeys { 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 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) } diff --git a/main-command/src/main/scala/sbt/Command.scala b/main-command/src/main/scala/sbt/Command.scala index 4b8693e97..735ccf1af 100644 --- a/main-command/src/main/scala/sbt/Command.scala +++ b/main-command/src/main/scala/sbt/Command.scala @@ -89,16 +89,16 @@ object Command { } /** 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 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 Left(errMsg) => state.log.error(errMsg) state.fail } - State.exchange.publishEvent(ExecStatusEvent("Ready", newState.remainingCommands.toVector)) + State.exchange.publishEvent(ExecStatusEvent("Ready", newState.remainingCommands.toVector map { _.commandLine })) newState } def invalidValue(label: String, allowed: Iterable[String])(value: String): String = diff --git a/main-command/src/main/scala/sbt/State.scala b/main-command/src/main/scala/sbt/State.scala index 0f217dc73..733d07a5b 100644 --- a/main-command/src/main/scala/sbt/State.scala +++ b/main-command/src/main/scala/sbt/State.scala @@ -27,11 +27,12 @@ final case class State( configuration: xsbti.AppConfiguration, definedCommands: Seq[Command], exitHooks: Set[ExitHook], - onFailure: Option[String], - remainingCommands: Seq[String], + onFailure: Option[Exec], + remainingCommands: List[Exec], history: State.History, attributes: AttributeMap, globalLogging: GlobalLogging, + source: Option[CommandSource], next: State.Next ) extends Identity { lazy val combinedParser = Command.combine(definedCommands)(this) @@ -45,14 +46,20 @@ trait Identity { /** Convenience methods for State transformations and operations. */ 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.*/ - 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.*/ 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.*/ def continue: State @@ -69,6 +76,9 @@ trait StateOps { /** Sets the next command processing action to do.*/ 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 /** @@ -158,9 +168,9 @@ object State { * @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. */ - 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.*/ - def ::(command: String): History = + def ::(command: Exec): History = { val prependTo = if (maxSize > 0 && executed.size >= maxSize) executed.take(maxSize - 1) else executed new History(command +: prependTo, maxSize) @@ -168,8 +178,8 @@ object State { /** Changes the maximum number of commands kept, adjusting the current history if necessary.*/ def setMaxSize(size: Int): History = new History(if (size <= 0) executed else executed.take(size), size) - def currentOption: Option[String] = executed.headOption - def previous: Option[String] = executed.drop(1).headOption + def currentOption: Option[Exec] = executed.headOption + def previous: Option[Exec] = executed.drop(1).headOption } /** Constructs an empty command History with a default, finite command limit.*/ def newHistory = new History(Vector.empty, HistoryCommands.MaxLines) @@ -177,29 +187,37 @@ object State { def defaultReload(state: State): Reboot = { 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() /** Provides operations and transformations on State. */ 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 { - case Seq() => exit(true) - case Seq(x, xs @ _*) => + case List() => exit(true) + case x :: xs => log.debug(s"> $x") 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 +(newCommand: Command): State = this ++ (newCommand :: Nil) def baseDir: File = s.configuration.baseDirectory 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 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 clearGlobalLog = setNext(ClearGlobalLog) def keepLastLog = setNext(KeepLastLog) @@ -220,7 +238,7 @@ object State { else 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 { case Some(c) => s.copy(remainingCommands = c +: remaining, onFailure = None) case None => noHandler diff --git a/main-command/src/main/scala/sbt/internal/CommandChannel.scala b/main-command/src/main/scala/sbt/internal/CommandChannel.scala index d280fdca9..b18965987 100644 --- a/main-command/src/main/scala/sbt/internal/CommandChannel.scala +++ b/main-command/src/main/scala/sbt/internal/CommandChannel.scala @@ -18,11 +18,12 @@ abstract class CommandChannel { def publishEvent(event: EventMessage): Unit def publishBytes(bytes: Array[Byte]): 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. diff --git a/main-command/src/main/scala/sbt/internal/CommandExchange.scala b/main-command/src/main/scala/sbt/internal/CommandExchange.scala index c1bbab9cf..f4b9b5358 100644 --- a/main-command/src/main/scala/sbt/internal/CommandExchange.scala +++ b/main-command/src/main/scala/sbt/internal/CommandExchange.scala @@ -5,7 +5,7 @@ import java.net.SocketException import java.util.concurrent.ConcurrentLinkedQueue import java.util.concurrent.atomic.AtomicInteger import sbt.internal.server._ -import sbt.protocol.{ EventMessage, Serialization } +import sbt.protocol.{ EventMessage, Serialization, ChannelAcceptedEvent } import scala.collection.mutable.ListBuffer import scala.annotation.tailrec import BasicKeys.serverPort @@ -74,6 +74,7 @@ private[sbt] final class CommandExchange { s.log.info(s"new client connected from: ${socket.getPort}") val channel = new NetworkChannel(newChannelName, socket) subscribe(channel) + channel.publishEvent(ChannelAcceptedEvent(channel.name)) } server match { case Some(x) => // do nothing diff --git a/main-command/src/main/scala/sbt/internal/ConsoleChannel.scala b/main-command/src/main/scala/sbt/internal/ConsoleChannel.scala index 5bc784653..dd032b3c8 100644 --- a/main-command/src/main/scala/sbt/internal/ConsoleChannel.scala +++ b/main-command/src/main/scala/sbt/internal/ConsoleChannel.scala @@ -6,7 +6,7 @@ import BasicKeys._ import java.io.File 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 def makeAskUserThread(s: State): Thread = new Thread("ask-user-thread") { val history = (s get historyPath) getOrElse Some(new File(s.baseDir, ".history")) diff --git a/main-command/src/main/scala/sbt/internal/client/NetworkClient.scala b/main-command/src/main/scala/sbt/internal/client/NetworkClient.scala index b46fb1e79..7a0798fdf 100644 --- a/main-command/src/main/scala/sbt/internal/client/NetworkClient.scala +++ b/main-command/src/main/scala/sbt/internal/client/NetworkClient.scala @@ -11,7 +11,8 @@ import sbt.protocol._ import sbt.internal.util.JLine 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 lock: AnyRef = new AnyRef {} private val running = new AtomicBoolean(true) @@ -38,15 +39,7 @@ class NetworkClient(arguments: List[String]) { println(s"client on port $port") val socket = new Socket(InetAddress.getByName(host), port) new ServerConnection(socket) { - override def onEvent(event: EventMessage): Unit = - event match { - case e: ExecStatusEvent => - lock.synchronized { - status.set(e.status) - } - println(event) - case e => println(e.toString) - } + override def onEvent(event: EventMessage): Unit = self.onEvent(event) override def onShutdown(): Unit = { 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 = { val reader = JLine.simple(None, JLine.HandleCONT, injectThreadSleep = true) diff --git a/main-command/src/main/scala/sbt/internal/server/NetworkChannel.scala b/main-command/src/main/scala/sbt/internal/server/NetworkChannel.scala index 83ddbe84e..c1cef4db8 100644 --- a/main-command/src/main/scala/sbt/internal/server/NetworkChannel.scala +++ b/main-command/src/main/scala/sbt/internal/server/NetworkChannel.scala @@ -9,7 +9,7 @@ import java.net.{ Socket, SocketTimeoutException } import java.util.concurrent.atomic.AtomicBoolean 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 delimiter: Byte = '\n'.toByte private val out = connection.getOutputStream @@ -50,7 +50,11 @@ final class NetworkChannel(name: String, connection: Socket) extends CommandChan } 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 = { diff --git a/main/src/main/scala/sbt/Cross.scala b/main/src/main/scala/sbt/Cross.scala index 53ac58ba4..4bd53ddab 100644 --- a/main/src/main/scala/sbt/Cross.scala +++ b/main/src/main/scala/sbt/Cross.scala @@ -137,7 +137,7 @@ object Cross { 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 = { val switchedState = switchScalaVersion(args, state) - args.command.toSeq ::: switchedState + args.command.toList ::: switchedState } private def switchScalaVersion(switch: Switch, state: State): State = { diff --git a/main/src/main/scala/sbt/Main.scala b/main/src/main/scala/sbt/Main.scala index fb3e99c9a..868811a09 100644 --- a/main/src/main/scala/sbt/Main.scala +++ b/main/src/main/scala/sbt/Main.scala @@ -94,9 +94,9 @@ object StandardMain { import BasicCommandStrings.isEarlyCommand val userCommands = configuration.arguments.map(_.trim) 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 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 } } @@ -129,7 +129,7 @@ object BuiltinCommands { // This parser schedules the default boot commands unless overridden by an alias def bootParser(s: State) = { - val orElse = () => DefaultBootCommands ::: s + val orElse = () => DefaultBootCommands.toList ::: s delegateToAlias(BootCommand, success(orElse))(s) } @@ -242,7 +242,7 @@ object BuiltinCommands { } 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) => diff --git a/main/src/main/scala/sbt/internal/IvyConsole.scala b/main/src/main/scala/sbt/internal/IvyConsole.scala index e7f300300..4ae73db61 100644 --- a/main/src/main/scala/sbt/internal/IvyConsole.scala +++ b/main/src/main/scala/sbt/internal/IvyConsole.scala @@ -20,7 +20,7 @@ object IvyConsole { final val Name = "ivy-console" lazy val command = 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) IO.createDirectory(base) @@ -39,7 +39,7 @@ object IvyConsole { val append = Load.transformSettings(Load.projectScope(currentRef), currentRef.build, rootProject, depSettings) 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) } diff --git a/main/src/main/scala/sbt/internal/Script.scala b/main/src/main/scala/sbt/internal/Script.scala index 9ead77992..0a6ec339e 100644 --- a/main/src/main/scala/sbt/internal/Script.scala +++ b/main/src/main/scala/sbt/internal/Script.scala @@ -19,7 +19,7 @@ object Script { final val Name = "script" lazy val command = 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 hash = Hash.halve(Hash.toHex(Hash(scriptFile.getAbsolutePath))) val base = new File(CommandUtil.bootDirectory(state), hash) diff --git a/protocol/src/main/contraband-scala/sbt/protocol/ChannelAcceptedEvent.scala b/protocol/src/main/contraband-scala/sbt/protocol/ChannelAcceptedEvent.scala new file mode 100644 index 000000000..f0dd2233d --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/protocol/ChannelAcceptedEvent.scala @@ -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) +} diff --git a/protocol/src/main/contraband-scala/sbt/protocol/codec/ChannelAcceptedEventFormats.scala b/protocol/src/main/contraband-scala/sbt/protocol/codec/ChannelAcceptedEventFormats.scala new file mode 100644 index 000000000..1bcb80ce7 --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/protocol/codec/ChannelAcceptedEventFormats.scala @@ -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() + } +} +} diff --git a/protocol/src/main/contraband-scala/sbt/protocol/codec/EventMessageFormats.scala b/protocol/src/main/contraband-scala/sbt/protocol/codec/EventMessageFormats.scala index 06640f15b..547cd7031 100644 --- a/protocol/src/main/contraband-scala/sbt/protocol/codec/EventMessageFormats.scala +++ b/protocol/src/main/contraband-scala/sbt/protocol/codec/EventMessageFormats.scala @@ -5,6 +5,6 @@ // DO NOT EDIT MANUALLY package sbt.protocol.codec import _root_.sjsonnew.{ deserializationError, serializationError, Builder, JsonFormat, Unbuilder } -trait EventMessageFormats { self: sjsonnew.BasicJsonProtocol 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") +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] = flatUnionFormat3[sbt.protocol.EventMessage, sbt.protocol.ChannelAcceptedEvent, sbt.protocol.LogEvent, sbt.protocol.ExecStatusEvent]("type") } diff --git a/protocol/src/main/contraband-scala/sbt/protocol/codec/JsonProtocol.scala b/protocol/src/main/contraband-scala/sbt/protocol/codec/JsonProtocol.scala index 4504ee808..5bf383215 100644 --- a/protocol/src/main/contraband-scala/sbt/protocol/codec/JsonProtocol.scala +++ b/protocol/src/main/contraband-scala/sbt/protocol/codec/JsonProtocol.scala @@ -4,5 +4,5 @@ // DO NOT EDIT MANUALLY 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 \ No newline at end of file diff --git a/protocol/src/main/contraband/server.contra b/protocol/src/main/contraband/server.contra index 05589d583..0702db439 100644 --- a/protocol/src/main/contraband/server.contra +++ b/protocol/src/main/contraband/server.contra @@ -17,6 +17,10 @@ type ExecCommand implements CommandMessage { interface EventMessage { } +type ChannelAcceptedEvent implements EventMessage { + channelName: String! +} + ## Log event. type LogEvent implements EventMessage { level: String!