cleanup MainResult handling to enable finer control over reloading

This commit is contained in:
Mark Harrah 2011-07-01 23:38:03 -04:00
parent cf17a578a1
commit 8d922b61ab
3 changed files with 31 additions and 34 deletions

View File

@ -29,7 +29,7 @@ final class xMain extends xsbti.AppMain
import CommandSupport.{DefaultsCommand, InitCommand}
val initialCommandDefs = Seq(initialize, defaults)
val commands = DefaultsCommand +: InitCommand +: (DefaultBootCommands ++ configuration.arguments.map(_.trim))
val state = State( configuration, initialCommandDefs, Set.empty, None, commands, initialAttributes, Next.Continue )
val state = State( configuration, initialCommandDefs, Set.empty, None, commands, initialAttributes, None )
MainLoop.run(state)
}
}
@ -39,7 +39,7 @@ final class ScriptMain extends xsbti.AppMain
{
import BuiltinCommands.{initialAttributes, ScriptCommands}
val commands = Script.Name +: configuration.arguments.map(_.trim)
val state = State( configuration, ScriptCommands, Set.empty, None, commands, initialAttributes, Next.Continue )
val state = State( configuration, ScriptCommands, Set.empty, None, commands, initialAttributes, None )
MainLoop.run(state)
}
}
@ -49,25 +49,19 @@ final class ConsoleMain extends xsbti.AppMain
{
import BuiltinCommands.{initialAttributes, ConsoleCommands}
val commands = IvyConsole.Name +: configuration.arguments.map(_.trim)
val state = State( configuration, ConsoleCommands, Set.empty, None, commands, initialAttributes, Next.Continue )
val state = State( configuration, ConsoleCommands, Set.empty, None, commands, initialAttributes, None )
MainLoop.run(state)
}
}
object MainLoop
{
@tailrec final def run(state: State): xsbti.MainResult =
{
import Next._
state.next match
state.result match
{
case Continue => run(next(state))
case Fail => Exit(1)
case Done => Exit(0)
case Reload =>
val app = state.configuration.provider
new Reboot(app.scalaProvider.version, state.remainingCommands, app.id, state.configuration.baseDirectory)
case None => run(next(state))
case Some(result) => result
}
}
def next(state: State): State =
ErrorHandling.wideConvert { state.process(Command.process) } match
{

View File

@ -5,23 +5,23 @@ package sbt
import java.io.File
private case class Exit(code: Int) extends xsbti.Exit
final case class Exit(code: Int) extends xsbti.Exit
{
require(code >= 0)
}
private class Reboot(val scalaVersion: String, argsList: Seq[String], val app: xsbti.ApplicationID, val baseDirectory: File) extends xsbti.Reboot
final case class Reboot(scalaVersion: String, argsList: Seq[String], app: xsbti.ApplicationID, baseDirectory: File) extends xsbti.Reboot
{
def arguments = argsList.toArray
}
private class ApplicationID(delegate: xsbti.ApplicationID, newVersion: String) extends xsbti.ApplicationID
final case class ApplicationID(groupID: String, name: String, version: String, mainClass: String, components: Seq[String], crossVersioned: Boolean, extra: Seq[File]) extends xsbti.ApplicationID
{
def groupID = delegate.groupID
def name = delegate.name
def version = newVersion
def mainClass = delegate.mainClass
def mainComponents = delegate.mainComponents
def crossVersioned = delegate.crossVersioned
def classpathExtra = delegate.classpathExtra
def mainComponents = components.toArray
def classpathExtra = extra.toArray
}
object ApplicationID
{
def apply(delegate: xsbti.ApplicationID, newVersion: String): ApplicationID =
apply(delegate).copy(version = newVersion)
def apply(delegate: xsbti.ApplicationID): ApplicationID =
ApplicationID(delegate.groupID, delegate.name, delegate.version, delegate.mainClass, delegate.mainComponents, delegate.crossVersioned, delegate.classpathExtra)
}

View File

@ -13,7 +13,7 @@ final case class State(
onFailure: Option[String],
remainingCommands: Seq[String],
attributes: AttributeMap,
next: Next.Value
result: Option[xsbti.MainResult]
) extends Identity {
lazy val combinedParser = Command.combine(definedCommands)(this)
}
@ -24,16 +24,13 @@ trait Identity {
override final def toString = super.toString
}
object Next extends Enumeration {
val Reload, Fail, Done, Continue = Value
}
trait StateOps {
def process(f: (String, State) => State): State
def ::: (commands: Seq[String]): State
def :: (command: String): State
def continue: State
def reboot(full: Boolean): State
def setResult(n: Option[xsbti.MainResult]): State
def reload: State
def exit(ok: Boolean): State
def fail: State
@ -48,6 +45,12 @@ trait StateOps {
}
object State
{
def defaultReload(state: State): Reboot =
{
val app = state.configuration.provider
new Reboot(app.scalaProvider.version, state.remainingCommands, app.id, state.configuration.baseDirectory)
}
implicit def stateOps(s: State): StateOps = new StateOps {
def process(f: (String, State) => State): State =
s.remainingCommands match {
@ -60,11 +63,11 @@ object State
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.Value) = s.copy(next = n)
def continue = setNext(Next.Continue)
def setResult(n: Option[xsbti.MainResult]) = s.copy(result = n)
def continue = setResult(None)
def reboot(full: Boolean) = throw new xsbti.FullReload(s.remainingCommands.toArray, full)
def reload = setNext(Next.Reload)
def exit(ok: Boolean) = setNext(if(ok) Next.Done else Next.Fail)
def reload = setResult(Some(defaultReload(s)))
def exit(ok: Boolean) = setResult(Some(Exit(if(ok) 0 else 1)))
def get[T](key: AttributeKey[T]) = s.attributes get key
def put[T](key: AttributeKey[T], value: T) = s.copy(attributes = s.attributes.put(key, value))
def remove(key: AttributeKey[_]) = s.copy(attributes = s.attributes remove key)