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

View File

@ -5,23 +5,23 @@ package sbt
import java.io.File 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) 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 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 mainComponents = components.toArray
def name = delegate.name def classpathExtra = extra.toArray
def version = newVersion }
object ApplicationID
def mainClass = delegate.mainClass {
def mainComponents = delegate.mainComponents def apply(delegate: xsbti.ApplicationID, newVersion: String): ApplicationID =
def crossVersioned = delegate.crossVersioned apply(delegate).copy(version = newVersion)
def apply(delegate: xsbti.ApplicationID): ApplicationID =
def classpathExtra = delegate.classpathExtra 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], onFailure: Option[String],
remainingCommands: Seq[String], remainingCommands: Seq[String],
attributes: AttributeMap, attributes: AttributeMap,
next: Next.Value result: Option[xsbti.MainResult]
) extends Identity { ) extends Identity {
lazy val combinedParser = Command.combine(definedCommands)(this) lazy val combinedParser = Command.combine(definedCommands)(this)
} }
@ -24,16 +24,13 @@ trait Identity {
override final def toString = super.toString override final def toString = super.toString
} }
object Next extends Enumeration {
val Reload, Fail, Done, Continue = Value
}
trait StateOps { trait StateOps {
def process(f: (String, State) => State): State def process(f: (String, State) => State): State
def ::: (commands: Seq[String]): State def ::: (commands: Seq[String]): State
def :: (command: String): State def :: (command: String): State
def continue: State def continue: State
def reboot(full: Boolean): State def reboot(full: Boolean): State
def setResult(n: Option[xsbti.MainResult]): State
def reload: State def reload: State
def exit(ok: Boolean): State def exit(ok: Boolean): State
def fail: State def fail: State
@ -48,6 +45,12 @@ trait StateOps {
} }
object State 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 { implicit def stateOps(s: State): StateOps = new StateOps {
def process(f: (String, State) => State): State = def process(f: (String, State) => State): State =
s.remainingCommands match { s.remainingCommands match {
@ -60,11 +63,11 @@ object State
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.Value) = s.copy(next = n) def setResult(n: Option[xsbti.MainResult]) = s.copy(result = n)
def continue = setNext(Next.Continue) def continue = setResult(None)
def reboot(full: Boolean) = throw new xsbti.FullReload(s.remainingCommands.toArray, full) def reboot(full: Boolean) = throw new xsbti.FullReload(s.remainingCommands.toArray, full)
def reload = setNext(Next.Reload) def reload = setResult(Some(defaultReload(s)))
def exit(ok: Boolean) = setNext(if(ok) Next.Done else Next.Fail) def exit(ok: Boolean) = setResult(Some(Exit(if(ok) 0 else 1)))
def get[T](key: AttributeKey[T]) = s.attributes get key 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 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) def remove(key: AttributeKey[_]) = s.copy(attributes = s.attributes remove key)