Skip to content
Browse files

clean up last/global logging

add history of actually executed commands
  • Loading branch information...
1 parent 2cbc755 commit fa8fb49cc3a6ce71b9b57d8b622ad0ac6248c550 @harrah committed Oct 30, 2011
View
2 main/Aggregation.scala
@@ -82,7 +82,7 @@ final object Aggregation
val config = extractedConfig(extracted, structure)
val start = System.currentTimeMillis
- val (newS, result) = withStreams(structure){ str =>
+ val (newS, result) = withStreams(structure, s){ str =>
val transform = nodeView(s, str, extra.tasks, extra.values)
runTask(toRun, s,str, structure.index.triggers, config)(transform)
}
View
4 main/Build.scala
@@ -209,8 +209,8 @@ object BuildStreams
final val BuildUnitPath = "$build"
final val StreamsDirectory = "streams"
- def mkStreams(units: Map[URI, LoadedBuildUnit], root: URI, data: Settings[Scope]): Streams =
- std.Streams( path(units, root, data), displayFull, LogManager.construct(data) )
+ def mkStreams(units: Map[URI, LoadedBuildUnit], root: URI, data: Settings[Scope]): State => Streams = s =>
+ std.Streams( path(units, root, data), displayFull, LogManager.construct(data, s) )
def path(units: Map[URI, LoadedBuildUnit], root: URI, data: Settings[Scope])(scoped: ScopedKey[_]): File =
resolvePath( projectPath(units, root, scoped, data), nonProjectPath(scoped) )
View
2 main/CommandSupport.scala
@@ -12,7 +12,7 @@ import Path._
object CommandSupport
{
def logger(s: State) = globalLogging(s).full
- def globalLogging(s: State) = s get Keys.globalLogging.key getOrElse error("Global logging misconfigured")
+ def globalLogging(s: State) = s get Keys.globalLogging getOrElse error("Global logging misconfigured")
// slightly better fallback in case of older launcher
def bootDirectory(state: State): File =
View
6 main/EvaluateTask.scala
@@ -58,7 +58,7 @@ object EvaluateTask
def evaluateTask[T](structure: BuildStructure, taskKey: ScopedKey[Task[T]], state: State, ref: ProjectRef, checkCycles: Boolean = false, maxWorkers: Int = SystemProcessors): Option[Result[T]] =
apply(structure, taskKey, state, ref, EvaluateConfig(false, checkCycles, maxWorkers)).map(_._2)
def apply[T](structure: BuildStructure, taskKey: ScopedKey[Task[T]], state: State, ref: ProjectRef, config: EvaluateConfig = defaultConfig): Option[(State, Result[T])] =
- withStreams(structure) { str =>
+ withStreams(structure, state) { str =>
for( (task, toNode) <- getTask(structure, taskKey, state, str, ref) ) yield
runTask(task, state, str, structure.index.triggers, config)(toNode)
}
@@ -81,9 +81,9 @@ object EvaluateTask
}
def getStreams(key: ScopedKey[_], streams: Streams): TaskStreams =
streams(ScopedKey(Project.fillTaskAxis(key).scope, Keys.streams.key))
- def withStreams[T](structure: BuildStructure)(f: Streams => T): T =
+ def withStreams[T](structure: BuildStructure, state: State)(f: Streams => T): T =
{
- val str = std.Streams.closeable(structure.streams)
+ val str = std.Streams.closeable(structure.streams(state))
try { f(str) } finally { str.close() }
}
View
2 main/GlobalPlugin.scala
@@ -51,7 +51,7 @@ object GlobalPlugin
def evaluate[T](state: State, structure: BuildStructure, t: Task[T]): (State, T) =
{
import EvaluateTask._
- withStreams(structure) { str =>
+ withStreams(structure, state) { str =>
val nv = nodeView(state, str)
val config = EvaluateTask.defaultConfig
val (newS, result) = runTask(t, state, str, structure.index.triggers, config)(nv)
View
2 main/Keys.scala
@@ -56,7 +56,7 @@ object Keys
// val onComplete = SettingKey[RMap[Task,Result] => RMap[Task,Result]]("on-complete", "Transformation to apply to the final task result map. This may also be used to register hooks to run when task evaluation completes.")
// Command keys
- val globalLogging = SettingKey[GlobalLogging]("global-logging", "Provides a global Logger, including command logging.")
+ val globalLogging = AttributeKey[GlobalLogging]("global-logging", "Provides a global Logger, including command logging.")
val historyPath = SettingKey[Option[File]]("history", "The location where command line history is persisted.")
val shellPrompt = SettingKey[State => String]("shell-prompt", "The function that constructs the command prompt from the current build state.")
val analysis = AttributeKey[inc.Analysis]("analysis", "Analysis of compilation, including dependencies and generated outputs.")
View
3 main/Load.scala
@@ -53,7 +53,6 @@ object Load
}
def injectGlobal(state: State): Seq[Project.Setting[_]] =
(appConfiguration in GlobalScope :== state.configuration) +:
- (globalLogging in GlobalScope := CommandSupport.globalLogging(state)) +:
EvaluateTask.injectSettings
def defaultWithGlobal(state: State, base: File, rawConfig: LoadBuildConfiguration, globalBase: File, log: Logger): LoadBuildConfiguration =
{
@@ -576,7 +575,7 @@ object Load
def referenced[PR <: ProjectReference](definitions: Seq[ProjectDefinition[PR]]): Seq[PR] = definitions flatMap { _.referenced }
- final class BuildStructure(val units: Map[URI, LoadedBuildUnit], val root: URI, val settings: Seq[Setting[_]], val data: Settings[Scope], val index: StructureIndex, val streams: Streams, val delegates: Scope => Seq[Scope], val scopeLocal: ScopeLocal)
+ final class BuildStructure(val units: Map[URI, LoadedBuildUnit], val root: URI, val settings: Seq[Setting[_]], val data: Settings[Scope], val index: StructureIndex, val streams: State => Streams, val delegates: Scope => Seq[Scope], val scopeLocal: ScopeLocal)
{
val rootProject: URI => String = Load getRootProject units
def allProjects: Seq[ResolvedProject] = units.values.flatMap(_.defined.values).toSeq
View
25 main/LogManager.scala
@@ -13,10 +13,10 @@ package sbt
object LogManager
{
- def construct(data: Settings[Scope]) = (task: ScopedKey[_], to: PrintWriter) =>
+ def construct(data: Settings[Scope], state: State) = (task: ScopedKey[_], to: PrintWriter) =>
{
val manager = logManager in task.scope get data getOrElse default
- manager(data, task, to)
+ manager(data, state, task, to)
}
lazy val default: LogManager = withLoggers()
def defaults(extra: ScopedKey[_] => Seq[AbstractLogger]): LogManager = withLoggers(extra = extra)
@@ -30,19 +30,19 @@ object LogManager
def withLoggers(screen: => AbstractLogger = defaultScreen, backed: PrintWriter => AbstractLogger = defaultBacked(), extra: ScopedKey[_] => Seq[AbstractLogger] = _ => Nil): LogManager =
new LogManager {
- def apply(data: Settings[Scope], task: ScopedKey[_], to: PrintWriter): Logger =
- defaultLogger(data, task, screen, backed(to), extra(task).toList)
+ def apply(data: Settings[Scope], state: State, task: ScopedKey[_], to: PrintWriter): Logger =
+ defaultLogger(data, state, task, screen, backed(to), extra(task).toList)
}
- def defaultLogger(data: Settings[Scope], task: ScopedKey[_], console: AbstractLogger, backed: AbstractLogger, extra: List[AbstractLogger]): Logger =
+ def defaultLogger(data: Settings[Scope], state: State, task: ScopedKey[_], console: AbstractLogger, backed: AbstractLogger, extra: List[AbstractLogger]): Logger =
{
val scope = task.scope
def getOr[T](key: AttributeKey[T], default: T): T = data.get(scope, key) getOrElse default
val screenLevel = getOr(logLevel.key, Level.Info)
val backingLevel = getOr(persistLogLevel.key, Level.Debug)
val screenTrace = getOr(traceLevel.key, -1)
val backingTrace = getOr(persistTraceLevel.key, Int.MaxValue)
- val extraBacked = data.get(Scope.GlobalScope, Keys.globalLogging.key).map(_.backed).toList
+ val extraBacked = (state get Keys.globalLogging).map(_.backed).toList
multiLogger( new MultiLoggerConfig(console, backed, extraBacked ::: extra, screenLevel, backingLevel, screenTrace, backingTrace) )
}
def multiLogger(config: MultiLoggerConfig): Logger =
@@ -58,11 +58,11 @@ object LogManager
backed setTrace backingTrace
multi: Logger
}
- def globalDefault(writer: PrintWriter, file: File): GlobalLogging =
+ def globalDefault(writer: PrintWriter, backing: GlobalLogBacking): GlobalLogging =
{
val backed = defaultBacked()(writer)
val full = multiLogger(defaultMultiConfig( backed ) )
- GlobalLogging(full, backed, file)
+ GlobalLogging(full, backed, backing)
}
def defaultMultiConfig(backing: AbstractLogger): MultiLoggerConfig =
@@ -71,6 +71,11 @@ object LogManager
final case class MultiLoggerConfig(console: AbstractLogger, backed: AbstractLogger, extra: List[AbstractLogger], screenLevel: Level.Value, backingLevel: Level.Value, screenTrace: Int, backingTrace: Int)
trait LogManager
{
- def apply(data: Settings[Scope], task: ScopedKey[_], writer: PrintWriter): Logger
+ def apply(data: Settings[Scope], state: State, task: ScopedKey[_], writer: PrintWriter): Logger
}
-final case class GlobalLogging(full: Logger, backed: ConsoleLogger, backing: File)
+final case class GlobalLogBacking(file: File, last: Option[File])
+{
+ def shift(newFile: File) = GlobalLogBacking(newFile, Some(file))
+ def unshift = GlobalLogBacking(last getOrElse file, None)
+}
+final case class GlobalLogging(full: Logger, backed: ConsoleLogger, backing: GlobalLogBacking)
View
123 main/Main.scala
@@ -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, None )
+ val state = State( configuration, initialCommandDefs, Set.empty, None, commands, State.newHistory, initialAttributes, State.Continue )
MainLoop.runLogged(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, None )
+ val state = State( configuration, ScriptCommands, Set.empty, None, commands, State.newHistory, initialAttributes, State.Continue )
MainLoop.runLogged(state)
}
}
@@ -49,37 +49,72 @@ 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, None )
+ val state = State( configuration, ConsoleCommands, Set.empty, None, commands, State.newHistory, initialAttributes, State.Continue )
MainLoop.runLogged(state)
}
}
object MainLoop
{
+ /** Entry point to run the remaining commands in State with managed global logging.*/
def runLogged(state: State): xsbti.MainResult =
- {
- val logFile = File.createTempFile("sbt", ".log")
- try {
- val result = runLogged(state, logFile)
- logFile.delete() // only delete when exiting normally
- result
+ runLoggedLoop(state, GlobalLogBacking(newBackingFile(), None))
+
+ /** Constructs a new, (weakly) unique, temporary file to use as the backing for global logging. */
+ def newBackingFile(): File = File.createTempFile("sbt",".log")
+
+ /** Run loop that evaluates remaining commands and manages changes to global logging configuration.*/
+ @tailrec def runLoggedLoop(state: State, logBacking: GlobalLogBacking): xsbti.MainResult =
+ runAndClearLast(state, logBacking) match {
+ case ret: Return => // delete current and last log files when exiting normally
+ logBacking.file.delete()
+ deleteLastLog(logBacking)
+ ret.result
+ case clear: ClearGlobalLog => // delete previous log file, move current to previous, and start writing to a new file
+ deleteLastLog(logBacking)
+ runLoggedLoop(clear.state, logBacking shift newBackingFile())
+ case keep: KeepGlobalLog => // make previous log file the current log file
+ logBacking.file.delete
+ runLoggedLoop(keep.state, logBacking.unshift)
}
+
+ /** Runs the next sequence of commands, cleaning up global logging after any exceptions. */
+ def runAndClearLast(state: State, logBacking: GlobalLogBacking): RunNext =
+ try
+ runWithNewLog(state, logBacking)
catch {
- case e: xsbti.FullReload => throw e
- case e => System.err.println("sbt appears to be exiting abnormally.\n The log file for this session is at " + logFile); throw e
+ case e: xsbti.FullReload =>
+ deleteLastLog(logBacking)
+ throw e // pass along a reboot request
+ case e =>
+ System.err.println("sbt appears to be exiting abnormally.\n The log file for this session is at " + logBacking.file)
+ deleteLastLog(logBacking)
+ throw e
}
- }
- def runLogged(state: State, backing: File): xsbti.MainResult =
- Using.fileWriter()(backing) { writer =>
+
+ /** Deletes the previous global log file. */
+ def deleteLastLog(logBacking: GlobalLogBacking): Unit =
+ logBacking.last.foreach(_.delete())
+
+ /** Runs the next sequence of commands with global logging in place. */
+ def runWithNewLog(state: State, logBacking: GlobalLogBacking): RunNext =
+ Using.fileWriter(append = true)(logBacking.file) { writer =>
val out = new java.io.PrintWriter(writer)
- val loggedState = state.put(globalLogging.key, LogManager.globalDefault(out, backing))
- try { run(loggedState) } finally { out.close() }
+ val loggedState = state.put(globalLogging, LogManager.globalDefault(out, logBacking))
+ try run(loggedState) finally out.close()
}
-
- @tailrec def run(state: State): xsbti.MainResult =
- state.result match
+ sealed trait RunNext
+ final class ClearGlobalLog(val state: State) extends RunNext
+ final class KeepGlobalLog(val state: State) extends RunNext
+ final class Return(val result: xsbti.MainResult) extends RunNext
+
+ /** Runs the next sequence of commands that doesn't require global logging changes.*/
+ @tailrec def run(state: State): RunNext =
+ state.next match
{
- case None => run(next(state))
- case Some(result) => result
+ case State.Continue => run(next(state))
+ case State.ClearGlobalLog => new ClearGlobalLog(state.continue)
+ case State.KeepLastLog => new KeepGlobalLog(state.continue)
+ case ret: State.Return => new Return(ret.result)
}
def next(state: State): State =
@@ -220,12 +255,12 @@ object BuiltinCommands
val line = reader.readLine(prompt)
line match {
case Some(line) =>
- if(!line.trim.isEmpty) CommandSupport.globalLogging(s).backed.out.println(Output.DefaultTail + line)
- s.copy(onFailure = Some(Shell), remainingCommands = line +: Shell +: s.remainingCommands)
+ val newState = s.copy(onFailure = Some(Shell), remainingCommands = line +: Shell +: s.remainingCommands)
+ if(line.trim.isEmpty) newState else newState.clearGlobalLog
case None => s
}
}
-
+
def multiParser(s: State): Parser[Seq[String]] =
( token(';' ~> OptSpace) flatMap { _ => matched(s.combinedParser | token(charClass(_ != ';').+, hide= const(true))) <~ token(OptSpace) } ).+
def multiApplied(s: State) =
@@ -356,11 +391,12 @@ object BuiltinCommands
def lastGrep = Command(LastGrepCommand, lastGrepBrief, lastGrepDetailed)(lastGrepParser) {
case (s, (pattern,Some(sk))) =>
val (str, ref, display) = extractLast(s)
- Output.lastGrep(sk, str, pattern)(display)
- s
+ Output.lastGrep(sk, str, str.streams(s), pattern, printLast(s))(display)
+ keepLastLog(s)
case (s, (pattern, None)) =>
- Output.lastGrep(CommandSupport.globalLogging(s).backing, pattern)
- s
+ for(logFile <- lastLogFile(s)) yield
+ Output.lastGrep(logFile, pattern, printLast(s))
+ keepLastLog(s)
}
def extractLast(s: State) = {
val ext = Project.extract(s)
@@ -373,13 +409,34 @@ object BuiltinCommands
def last = Command(LastCommand, lastBrief, lastDetailed)(optSpacedKeyParser) {
case (s,Some(sk)) =>
val (str, ref, display) = extractLast(s)
- Output.last(sk, str)(display)
- s
+ Output.last(sk, str, str.streams(s), printLast(s))(display)
+ keepLastLog(s)
case (s, None) =>
- Output.last( CommandSupport.globalLogging(s).backing )
- s
+ for(logFile <- lastLogFile(s)) yield
+ Output.last( logFile, printLast(s) )
+ keepLastLog(s)
}
+ /** Determines the log file that last* commands should operate on. See also isLastOnly. */
+ def lastLogFile(s: State) =
+ {
+ val backing = CommandSupport.globalLogging(s).backing
+ if(isLastOnly(s)) backing.last else Some(backing.file)
+ }
+
+ /** If false, shift the current log file to be the log file that 'last' will operate on.
+ * If true, keep the previous log file as the one 'last' operates on because there is nothing useful in the current one.*/
+ def keepLastLog(s: State): State = if(isLastOnly(s)) s.keepLastLog else s
+
+ /** The last* commands need to determine whether to read from the current log file or the previous log file
+ * and whether to keep the previous log file or not. This is selected based on whether the previous command
+ * was 'shell', which meant that the user directly entered the 'last' command. If it wasn't directly entered,
+ * the last* commands operate on any output since the last 'shell' command and do shift the log file.
+ * Otherwise, the output since the previous 'shell' command is used and the log file is not shifted.*/
+ def isLastOnly(s: State): Boolean = s.history.previous.forall(_ == Shell)
+
+ def printLast(s: State): Seq[String] => Unit = _ foreach println
+
def autoImports(extracted: Extracted): EvalImports = new EvalImports(imports(extracted), "<auto-imports>")
def imports(extracted: Extracted): Seq[(String,Int)] =
{
@@ -430,7 +487,7 @@ object BuiltinCommands
def matches(s: String) = !result.isEmpty && (s startsWith result)
if(result.isEmpty || matches("retry"))
- LoadProject :: s
+ LoadProject :: s.clearGlobalLog
else if(matches(Quit))
s.exit(ok = false)
else if(matches("ignore"))
View
18 main/Output.scala
@@ -30,16 +30,19 @@ object Output
}
final val DefaultTail = "> "
- def last(key: ScopedKey[_], structure: BuildStructure)(implicit display: Show[ScopedKey[_]]): Unit = printLines( flatLines(lastLines(key, structure))(idFun) )
- def last(file: File, tailDelim: String = DefaultTail): Unit = printLines(tailLines(file, tailDelim))
+ def last(key: ScopedKey[_], structure: BuildStructure, streams: Streams, printLines: Seq[String] => Unit)(implicit display: Show[ScopedKey[_]]): Unit =
+ printLines( flatLines(lastLines(key, structure, streams))(idFun) )
- def lastGrep(key: ScopedKey[_], structure: BuildStructure, patternString: String)(implicit display: Show[ScopedKey[_]]): Unit =
+ def last(file: File, printLines: Seq[String] => Unit, tailDelim: String = DefaultTail): Unit =
+ printLines(tailLines(file, tailDelim))
+
+ def lastGrep(key: ScopedKey[_], structure: BuildStructure, streams: Streams, patternString: String, printLines: Seq[String] => Unit)(implicit display: Show[ScopedKey[_]]): Unit =
{
val pattern = Pattern compile patternString
- val lines = flatLines( lastLines(key, structure) )(_ flatMap showMatches(pattern))
+ val lines = flatLines( lastLines(key, structure, streams) )(_ flatMap showMatches(pattern))
printLines( lines )
}
- def lastGrep(file: File, patternString: String, tailDelim: String = DefaultTail): Unit =
+ def lastGrep(file: File, patternString: String, printLines: Seq[String] => Unit, tailDelim: String = DefaultTail): Unit =
printLines(grep( tailLines(file, tailDelim), patternString) )
def grep(lines: Seq[String], patternString: String): Seq[String] =
lines flatMap showMatches(Pattern compile patternString)
@@ -52,13 +55,12 @@ object Output
if(!single) bold(display(key)) +: flines else flines
}
}
- def printLines(lines: Seq[String]) = lines foreach println
def bold(s: String) = if(ConsoleLogger.formatEnabled) BOLD + s + RESET else s
- def lastLines(key: ScopedKey[_], structure: BuildStructure): Seq[KeyValue[Seq[String]]] =
+ def lastLines(key: ScopedKey[_], structure: BuildStructure, streams: Streams): Seq[KeyValue[Seq[String]]] =
{
val aggregated = Aggregation.getTasks(key, structure, true)
- val outputs = aggregated map { case KeyValue(key, value) => KeyValue(key, lastLines(key, structure.streams)) }
+ val outputs = aggregated map { case KeyValue(key, value) => KeyValue(key, lastLines(key, streams)) }
outputs.filterNot(_.value.isEmpty)
}
def lastLines(key: ScopedKey[_], mgr: Streams): Seq[String] = mgr.use(key) { s => IO.readLines(s.readText( Project.fillTaskAxis(key) )) }
View
4 main/Project.scala
@@ -384,7 +384,7 @@ object SessionVar
}
def persist[T](key: ScopedKey[Task[T]], state: State, value: T)(implicit f: sbinary.Format[T]): Unit =
- Project.structure(state).streams.use(key)( s =>
+ Project.structure(state).streams(state).use(key)( s =>
Operations.write(s.binary(DefaultDataID), value)(f)
)
@@ -410,7 +410,7 @@ object SessionVar
}
def read[T](key: ScopedKey[Task[T]], state: State)(implicit f: Format[T]): Option[T] =
- Project.structure(state).streams.use(key) { s =>
+ Project.structure(state).streams(state).use(key) { s =>
try { Some(Operations.read(s.readBinary(key, DefaultDataID))) }
catch { case e: Exception => None }
}
View
42 main/State.scala
@@ -13,8 +13,9 @@ final case class State(
exitHooks: Set[ExitHook],
onFailure: Option[String],
remainingCommands: Seq[String],
+ history: State.History,
attributes: AttributeMap,
- result: Option[xsbti.MainResult]
+ next: State.Next
) extends Identity {
lazy val combinedParser = Command.combine(definedCommands)(this)
}
@@ -31,8 +32,11 @@ trait StateOps {
def :: (command: String): State
def continue: State
def reboot(full: Boolean): State
- def setResult(n: Option[xsbti.MainResult]): State
+ def setNext(n: State.Next): State
+ @deprecated("Use setNext", "0.11.0") def setResult(ro: Option[xsbti.MainResult])
def reload: State
+ def clearGlobalLog: State
+ def keepLastLog: State
def exit(ok: Boolean): State
def fail: State
def ++ (newCommands: Seq[Command]): State
@@ -50,6 +54,27 @@ trait StateOps {
}
object State
{
+ sealed trait Next
+ object Continue extends Next
+ final class Return(val result: xsbti.MainResult) extends Next
+ final object ClearGlobalLog extends Next
+ final object KeepLastLog extends Next
+
+ /** Provides a list of recently executed commands. The commands are stored as processed instead of as entered by the user.*/
+ final class History private[State](val executed: Seq[String], val maxSize: Int)
+ {
+ def :: (command: String): History =
+ {
+ val prependTo = if(executed.size >= maxSize) executed.take(maxSize - 1) else executed
+ new History(command +: prependTo, maxSize)
+ }
+ def setMaxSize(size: Int): History =
+ new History(executed.take(size), size)
+ def current: String = executed.head
+ def previous: Option[String] = executed.drop(1).headOption
+ }
+ def newHistory = new History(Vector.empty, complete.HistoryCommands.MaxLines)
+
def defaultReload(state: State): Reboot =
{
val app = state.configuration.provider
@@ -59,7 +84,7 @@ object State
implicit def stateOps(s: State): StateOps = new StateOps {
def process(f: (String, State) => State): State =
s.remainingCommands match {
- case Seq(x, xs @ _*) => f(x, s.copy(remainingCommands = xs))
+ case Seq(x, xs @ _*) => f(x, s.copy(remainingCommands = xs, history = x :: s.history))
case Seq() => exit(true)
}
s.copy(remainingCommands = s.remainingCommands.drop(1))
@@ -68,11 +93,14 @@ 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 setResult(n: Option[xsbti.MainResult]) = s.copy(result = n)
- def continue = setResult(None)
+ def setNext(n: Next) = s.copy(next = n)
+ 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) = throw new xsbti.FullReload(s.remainingCommands.toArray, full)
- def reload = setResult(Some(defaultReload(s)))
- def exit(ok: Boolean) = setResult(Some(Exit(if(ok) 0 else 1)))
+ def reload = setNext(new Return(defaultReload(s)))
+ def clearGlobalLog = setNext(ClearGlobalLog)
+ def keepLastLog = setNext(KeepLastLog)
+ def exit(ok: Boolean) = setNext(new Return(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 update[T](key: AttributeKey[T])(f: Option[T] => T): State = put(key, f(get(key)))
View
9 main/TaskData.scala
@@ -31,7 +31,7 @@ object TaskData
def dataStreams[T](structure: BuildStructure, reader: ScopedKey[_], readFrom: AttributeKey[_])(f: (TaskStreams, ScopedKey[_]) => T): Option[T] =
structure.data.definingScope(reader.scope, readFrom) map { defined =>
val key = ScopedKey(Scope.fillTaskAxis(defined, readFrom), readFrom)
- structure.streams.use(reader)(ts => f(ts, key))
+ structure.streams(fakeState(structure)).use(reader)(ts => f(ts, key))
}
def write[T](i: Initialize[Task[T]], id: String = DefaultDataID)(implicit f: Format[T]): Initialize[Task[T]] = writeRelated(i, id)(idFun[T])(f)
@@ -42,4 +42,11 @@ object TaskData
value
}
}
+ // exists to keep the method signatures the same (since this object is potentially used but deprecated),
+ // but allow the BuildStructure Streams to be constructed from State, which isn't actually needed here
+ private[this] def fakeState(structure: BuildStructure): State =
+ {
+ val config = Keys.appConfiguration in Scope.GlobalScope get structure.data
+ State(config.get, Nil, Set.empty, None, Nil, State.newHistory, AttributeMap.empty, State.Continue)
+ }
}

0 comments on commit fa8fb49

Please sign in to comment.
Something went wrong with that request. Please try again.