Command to run multiple tasks concurrently: 'all a b'. Fixes #628.

This commit is contained in:
Mark Harrah 2013-11-26 22:46:49 -05:00
parent 13041bfb9a
commit d38450b41f
6 changed files with 69 additions and 18 deletions

View File

@ -11,7 +11,7 @@ package sbt
import DefaultParsers._
import Types.idFun
import java.net.URI
import CommandStrings.ShowCommand
import CommandStrings.{MultiTaskCommand, ShowCommand}
final class ParsedKey(val key: ScopedKey[_], val mask: ScopeMask)
object Act
@ -234,20 +234,39 @@ object Act
val extracted = Project extract state
import extracted.{showKey, structure}
import Aggregation.evaluatingParser
showParser.flatMap { show =>
actionParser.flatMap { action =>
val akp = aggregatedKeyParser(extracted)
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) =>
evaluate(kvs) map { f => () => tail.map(reconstruct) ::: f() }
def evaluate(kvs: Seq[ScopedKey[_]]): Parser[() => State] = {
val preparedPairs = anyKeyValues(structure, kvs)
val showConfig = Aggregation.defaultShow(state, showTasks = action == ShowAction)
evaluatingParser(state, structure, showConfig)(preparedPairs) map { evaluate =>
() => {
val keyStrings = preparedPairs.map(pp => showKey(pp.key)).mkString(", ")
state.log.debug("Evaluating tasks: " + keyStrings)
evaluate()
}
}
else
akp flatMap evaluate
}
action match {
case SingleAction => akp flatMap evaluate
case ShowAction | MultiAction =>
rep1sep(akp, token(Space)).flatMap( kvss => evaluate(kvss.flatten) )
}
}
}
private[this] final class ActAction
private[this] final val ShowAction, MultiAction, SingleAction = new ActAction
private[this] def actionParser: Parser[ActAction] =
token(
((ShowCommand ^^^ ShowAction) |
(MultiTaskCommand ^^^ MultiAction) ) <~ Space
) ?? SingleAction
@deprecated("No longer used.", "0.13.2")
def showParser = token( (ShowCommand ~ Space) ^^^ true) ?? false
def scopedKeyParser(state: State): Parser[ScopedKey[_]] = scopedKeyParser(Project extract state)
def scopedKeyParser(extracted: Extracted): Parser[ScopedKey[_]] = scopedKeyParser(extracted.structure, extracted.currentRef)
def scopedKeyParser(structure: BuildStructure, currentRef: ProjectRef): Parser[ScopedKey[_]] =
@ -265,6 +284,11 @@ object Act
keys.flatMap { key =>
getValue(structure.data, key.scope, key.key) map { value => KeyValue(key, value) }
}
private[this] def anyKeyValues(structure: BuildStructure, keys: Seq[ScopedKey[_]]): Seq[KeyValue[_]] =
keys.flatMap { key =>
getValue(structure.data, key.scope, key.key) map { value => KeyValue(key, value) }
}
private[this] def getValue[T](data: Settings[Scope], scope: Scope, key: AttributeKey[T]): Option[T] =
if(java.lang.Boolean.getBoolean("sbt.cli.nodelegation")) data.getDirect(scope, key) else data.get(scope, key)

View File

@ -19,7 +19,7 @@ final object Aggregation
final case class KeyValue[+T](key: ScopedKey[_], value: T)
def defaultShow(state: State, showTasks: Boolean): ShowConfig = ShowConfig(settingValues = true, taskValues = showTasks, s => state.log.info(s), success = true)
def printSettings[T](xs: Seq[KeyValue[T]], print: String => Unit)(implicit display: Show[ScopedKey[_]]) =
def printSettings(xs: Seq[KeyValue[_]], print: String => Unit)(implicit display: Show[ScopedKey[_]]) =
xs match
{
case KeyValue(_,x) :: Nil => print(x.toString)
@ -33,7 +33,7 @@ final object Aggregation
Command.applyEffect(seqParser(ps)) { ts =>
runTasks(s, structure, ts, DummyTaskMap(Nil), show)
}
@deprecated("Use `timedRun` and `showRun` directly or use `runTasks`.", "0.13.0")
def runTasksWithResult[T](s: State, structure: BuildStructure, ts: Values[Task[T]], extra: DummyTaskMap, show: ShowConfig)(implicit display: Show[ScopedKey[_]]): (State, Result[Seq[KeyValue[T]]]) =
{
@ -120,7 +120,7 @@ final object Aggregation
}
}
def evaluatingParser[T](s: State, structure: BuildStructure, show: ShowConfig)(keys: Seq[KeyValue[T]])(implicit display: Show[ScopedKey[_]]): Parser[() => State] =
def evaluatingParser(s: State, structure: BuildStructure, show: ShowConfig)(keys: Seq[KeyValue[_]])(implicit display: Show[ScopedKey[_]]): Parser[() => State] =
keys.toList match
{
case Nil => failure("No such setting/task")
@ -166,7 +166,7 @@ final object Aggregation
val resolved = Resolve(extra, Global, key.key, mask)(toResolve)
ScopedKey(resolved, key.key)
}
def aggregationEnabled(key: ScopedKey[_], data: Settings[Scope]): Boolean =
Keys.aggregate in Scope.fillTaskAxis(key.scope, key.key) get data getOrElse true

View File

@ -12,6 +12,7 @@ object CommandStrings
val ProjectCommand = "project"
val ProjectsCommand = "projects"
val ShowCommand = "show"
val MultiTaskCommand = "all"
val BootCommand = "boot"
val EvalCommand = "eval"
@ -21,10 +22,26 @@ EvalCommand + """ <expression>
Evaluates the given Scala expression and prints the result and type."""
@deprecated("Misnomer: was only for `show`. Use showBrief.", "0.13.2")
def actBrief = showBrief
@deprecated("Misnomer: was only for `show`. Use showDetailed.", "0.13.2")
def actDetailed = showDetailed
def actHelp = showHelp ++ multiTaskHelp
def multiTaskHelp = Help(MultiTaskCommand, (multiTaskSyntax, multiTaskBrief), multiTaskDetailed)
def multiTaskDetailed =
s"""$multiTaskSyntax
$multiTaskBrief"""
def multiTaskSyntax = s"""$MultiTaskCommand <task>+"""
def multiTaskBrief = """Executes all of the specified tasks concurrently."""
def showHelp = Help(ShowCommand, (ShowCommand + " <key>", actBrief), actDetailed)
def actBrief = "Displays the result of evaluating the setting or task associated with 'key'."
def actDetailed =
s"""ShowCommand <setting>
def showBrief = "Displays the result of evaluating the setting or task associated with 'key'."
def showDetailed =
s"""$ShowCommand <setting>
Displays the value of the specified setting.

View File

@ -368,7 +368,7 @@ object BuiltinCommands
}
def act = Command.customHelp(Act.actParser, actHelp)
def actHelp = (s: State) => CommandStrings.showHelp ++ keysHelp(s)
def actHelp = (s: State) => CommandStrings.showHelp ++ CommandStrings.multiTaskHelp ++ keysHelp(s)
def keysHelp(s: State): Help =
if(Project.isProjectLoaded(s))
Help.detailOnly(taskDetail(allTaskAndSettingKeys(s)))

View File

@ -0,0 +1,7 @@
lazy val a = taskKey[Unit]("a")
lazy val b = taskKey[Unit]("b")
a := IO.touch(baseDirectory.value / "a")
b := IO.touch(baseDirectory.value / "b")

View File

@ -0,0 +1,3 @@
$ absent a b
> all a b
$ exists a b