when exporting settings, send the output directly to the console

This commit is contained in:
Mark Harrah 2013-02-28 17:59:38 -05:00
parent dde24d5e5a
commit a263b7e91f
5 changed files with 55 additions and 30 deletions

View File

@ -232,7 +232,8 @@ object Act
import Aggregation.evaluatingParser
showParser.flatMap { show =>
val akp = aggregatedKeyParser(extracted)
def evaluate(kvs: Seq[ScopedKey[T]] forSome { type T}): Parser[() => State] = evaluatingParser(state, structure, show)( keyValues(structure)(kvs) )
def evaluate(kvs: Seq[ScopedKey[T]] forSome { type T}): Parser[() => State] =
evaluatingParser(state, structure, Aggregation.defaultShow(state, show))( keyValues(structure)(kvs) )
def reconstruct(arg: String): String = ShowCommand + " " + arg
if(show)
( akp ~ (token(Space) ~> matched(akp)).* ) flatMap { case (kvs, tail) =>

View File

@ -14,23 +14,25 @@ package sbt
sealed trait Aggregation
final object Aggregation
{
final case class ShowConfig(settingValues: Boolean, taskValues: Boolean, print: String => Unit)
final case class KeyValue[+T](key: ScopedKey[_], value: T)
def printSettings[T](xs: Seq[KeyValue[T]], log: Logger)(implicit display: Show[ScopedKey[_]]) =
def defaultShow(state: State, showTasks: Boolean): ShowConfig = ShowConfig(settingValues = true, taskValues = showTasks, s => state.log.info(s))
def printSettings[T](xs: Seq[KeyValue[T]], print: String => Unit)(implicit display: Show[ScopedKey[_]]) =
xs match
{
case KeyValue(_,x) :: Nil => log.info(x.toString)
case _ => xs foreach { case KeyValue(key, value) => log.info(display(key) + "\n\t" + value.toString) }
case KeyValue(_,x) :: Nil => print(x.toString)
case _ => xs foreach { case KeyValue(key, value) => print(display(key) + "\n\t" + value.toString) }
}
type Values[T] = Seq[KeyValue[T]]
type AnyKeys = Values[_]
def seqParser[T](ps: Values[Parser[T]]): Parser[Seq[KeyValue[T]]] = seq(ps.map { case KeyValue(k,p) => p.map(v => KeyValue(k,v) ) })
def applyTasks[T](s: State, structure: BuildStructure, ps: Values[Parser[Task[T]]], show: Boolean)(implicit display: Show[ScopedKey[_]]): Parser[() => State] =
def applyTasks[T](s: State, structure: BuildStructure, ps: Values[Parser[Task[T]]], show: ShowConfig)(implicit display: Show[ScopedKey[_]]): Parser[() => State] =
Command.applyEffect(seqParser(ps)) { ts =>
runTasks(s, structure, ts, DummyTaskMap(Nil), show)
}
def runTasksWithResult[T](s: State, structure: BuildStructure, ts: Values[Task[T]], extra: DummyTaskMap, show: Boolean)(implicit display: Show[ScopedKey[_]]): (State, Result[Seq[KeyValue[T]]]) =
def runTasksWithResult[T](s: State, structure: BuildStructure, ts: Values[Task[T]], extra: DummyTaskMap, show: ShowConfig)(implicit display: Show[ScopedKey[_]]): (State, Result[Seq[KeyValue[T]]]) =
{
import EvaluateTask._
import std.TaskExtra._
@ -49,25 +51,24 @@ final object Aggregation
val log = newS.log
val success = result match { case Value(_) => true; case Inc(_) => false }
try { onResult(result, log) { results => if(show) printSettings(results, log) } }
try { onResult(result, log) { results => if(show.taskValues) printSettings(results, show.print) } }
finally { printSuccess(start, stop, extracted, success, log) }
(newS, result)
}
def runTasks[HL <: HList, T](s: State, structure: BuildStructure, ts: Values[Task[T]], extra: DummyTaskMap, show: Boolean)(implicit display: Show[ScopedKey[_]]): State = {
runTasksWithResult(s, structure, ts, extra, show)._1
}
def runTasks[HL <: HList, T](s: State, structure: BuildStructure, ts: Values[Task[T]], extra: DummyTaskMap, show: ShowConfig)(implicit display: Show[ScopedKey[_]]): State = {
runTasksWithResult(s, structure, ts, extra, show)._1
}
def printSuccess(start: Long, stop: Long, extracted: Extracted, success: Boolean, log: Logger)
def printSuccess(start: Long, stop: Long, extracted: Extracted, success: Boolean, log: Logger)
{
import extracted._
lazy val enabled = showSuccess in extracted.currentRef get extracted.structure.data getOrElse true
if(enabled)
def get(key: SettingKey[Boolean]): Boolean = key in currentRef get structure.data getOrElse true
if(get(showSuccess))
{
val timingEnabled = showTiming in currentRef get structure.data getOrElse true
if(timingEnabled)
if(get(showTiming))
{
val msg = timingString(start, stop, "", structure.data, currentRef, log)
if(success) log.success(msg) else log.error(msg)
@ -93,7 +94,7 @@ final object Aggregation
DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM)
}
def applyDynamicTasks[I](s: State, structure: BuildStructure, inputs: Values[InputTask[I]], show: Boolean)(implicit display: Show[ScopedKey[_]]): Parser[() => State] =
def applyDynamicTasks[I](s: State, structure: BuildStructure, inputs: Values[InputTask[I]], show: ShowConfig)(implicit display: Show[ScopedKey[_]]): Parser[() => State] =
{
val parsers = for(KeyValue(k,it) <- inputs) yield it.parser(s).map(v => KeyValue(k,v))
Command.applyEffect(seq(parsers)) { roots =>
@ -102,13 +103,13 @@ final object Aggregation
}
}
def evaluatingParser[T](s: State, structure: BuildStructure, show: Boolean)(keys: Seq[KeyValue[T]])(implicit display: Show[ScopedKey[_]]): Parser[() => State] =
def evaluatingParser[T](s: State, structure: BuildStructure, show: ShowConfig)(keys: Seq[KeyValue[T]])(implicit display: Show[ScopedKey[_]]): Parser[() => State] =
keys.toList match
{
case Nil => failure("No such setting/task")
case xs @ KeyValue(_, _: InputTask[t]) :: _ => applyDynamicTasks(s, structure, xs.asInstanceOf[Values[InputTask[t]]], show)
case xs @ KeyValue(_, _: Task[t]) :: _ => applyTasks(s, structure, maps(xs.asInstanceOf[Values[Task[t]]])(x => success(x)), show)
case xs => success(() => { printSettings(xs, s.log); s} )
case xs => success(() => { if(show.settingValues) printSettings(xs, show.print); s} )
}
private[this] def maps[T, S](vs: Values[T])(f: T => S): Values[S] =
vs map { case KeyValue(k,v) => KeyValue(k, f(v)) }

View File

@ -57,15 +57,19 @@ LastCommand + """
See also '""" + LastGrepCommand + "'."
val exportBrief = (ExportCommand, "Displays the equivalent command line(s) for previously executed tasks.")
val exportBrief = (ExportCommand + " <tasks>+", "Executes tasks and displays the equivalent command lines.")
val exportDetailed =
s"""$ExportCommand <task-key>+
Prints the approximate command line(s) for the previously executed tasks.
s"""$ExportCommand [--last] <task>+
Runs the specified tasks and prints the equivalent command lines or other exportable information for those runs.
NOTE: These command lines are necessarily approximate. Usually tasks do not actually
--last
Uses information from the previous execution
NOTES: These command lines are necessarily approximate. Usually tasks do not actually
execute the command line and the actual command line program may not be installed or
on the PATH. Incremental tasks will typically show the command line for the previous
incremental run and not for a full run.
on the PATH. Incremental tasks will typically show the command line for an
incremental run and not for a full run. Many tasks have no direct command line
equivalent and will show nothing at all.
"""
val InspectCommand = "inspect"

View File

@ -49,7 +49,7 @@ final case class Extracted(structure: BuildStructure, session: SessionSettings,
val rkey = resolve(key.scopedKey)
val keys = Aggregation.aggregate(rkey, ScopeMask(), structure.extra)
val tasks = Act.keyValues(structure)(keys)
Aggregation.runTasks(state, structure, tasks, DummyTaskMap(Nil), show = false )(showKey)
Aggregation.runTasks(state, structure, tasks, DummyTaskMap(Nil), show = Aggregation.defaultShow(state,false) )(showKey)
}
private[this] def resolve[T](key: ScopedKey[T]): ScopedKey[T] =

View File

@ -295,8 +295,28 @@ object BuiltinCommands
val spacedKeyParser = (s: State) => Act.requireSession(s, token(Space) ~> Act.scopedKeyParser(s))
val spacedAggregatedParser = (s: State) => Act.requireSession(s, token(Space) ~> Act.aggregatedKeyParser(s))
val exportParser: State => Parser[AnyKeys] = (s: State) => spacedAggregatedParser(s).map(x => Act.keyValues(s)(x) )
val aggregatedKeyValueParser: State => Parser[Option[AnyKeys]] = s => exportParser(s).?
val aggregatedKeyValueParser: State => Parser[Option[AnyKeys]] = (s: State) => spacedAggregatedParser(s).map(x => Act.keyValues(s)(x) ).?
val exportParser: State => Parser[() => State] = (s: State) => Act.requireSession(s, token(Space) ~> exportParser0(s))
private[sbt] def exportParser0(s: State): Parser[() => State] =
{
val extracted = Project extract s
import extracted.{showKey, structure}
val keysParser = token(flag("--last" <~ Space)) ~ Act.aggregatedKeyParser(extracted)
val show = Aggregation.ShowConfig(settingValues = true, taskValues = false, print = println _)
for {
lastOnly_keys <- keysParser
kvs = Act.keyValues(structure)(lastOnly_keys._2)
f <- if(lastOnly_keys._1) success(() => s) else Aggregation.evaluatingParser(s, structure, show)(kvs)
} yield () => {
def export0(s: State): State = lastImpl(s, kvs, Some("export"))
val newS = try f() catch { case e: Exception =>
try export0(s)
finally { throw e }
}
export0(newS)
}
}
def lastGrepParser(s: State) = Act.requireSession(s, (token(Space) ~> token(NotSpace, "<pattern>")) ~ aggregatedKeyValueParser(s))
def last = Command(LastCommand, lastBrief, lastDetailed)(aggregatedKeyValueParser) {
@ -306,9 +326,8 @@ object BuiltinCommands
Output.last( logFile, printLast(s) )
keepLastLog(s)
}
def export = Command(ExportCommand, exportBrief, exportDetailed)(exportParser) { (s, sks) =>
lastImpl(s, sks, Some("export"))
}
def export = Command(ExportCommand, exportBrief, exportDetailed)(exportParser)( (s,f) => f() )
private[this] def lastImpl(s: State, sks: AnyKeys, sid: Option[String]): State =
{
val (str, ref, display) = extractLast(s)