Merge pull request #1817 from sbt/wip/sequential

Def.sequential. Fixes #1001
This commit is contained in:
Josh Suereth 2015-01-23 09:38:45 -05:00
commit bd4e57dc66
5 changed files with 189 additions and 1 deletions

View File

@ -1760,7 +1760,7 @@ object Classpaths {
}
}
trait BuildExtra extends BuildCommon {
trait BuildExtra extends BuildCommon with DefExtra {
import Defaults._
/**
@ -1890,6 +1890,10 @@ trait BuildExtra extends BuildCommon {
def filterKeys(ss: Seq[Setting[_]], transitive: Boolean = false)(f: ScopedKey[_] => Boolean): Seq[Setting[_]] =
ss filter (s => f(s.key) && (!transitive || s.dependencies.forall(f)))
}
trait DefExtra {
private[this] val ts: TaskSequential = new TaskSequential {}
implicit def toTaskSequential(d: Def.type): TaskSequential = ts
}
trait BuildCommon {
@deprecated("Use Def.inputTask with the `Def.spaceDelimited()` parser.", "0.13.0")
def inputTask[T](f: TaskKey[Seq[String]] => Initialize[Task[T]]): Initialize[InputTask[T]] =

View File

@ -0,0 +1,104 @@
package sbt
import Def._
/**
* This trait injected to `Def` object to provide `sequential` functions for tasks.
*/
trait TaskSequential {
def sequential[B](last: Initialize[Task[B]]): Initialize[Task[B]] =
sequential(Nil, last)
def sequential[A0, B](task0: Initialize[Task[A0]],
last: Initialize[Task[B]]): Initialize[Task[B]] =
sequential(List(unitTask(task0)), last)
def sequential[A0, A1, B](task0: Initialize[Task[A0]], task1: Initialize[Task[A1]],
last: Initialize[Task[B]]): Initialize[Task[B]] =
sequential(List(unitTask(task0), unitTask(task1)), last)
def sequential[A0, A1, A2, B](task0: Initialize[Task[A0]], task1: Initialize[Task[A1]], task2: Initialize[Task[A2]],
last: Initialize[Task[B]]): Initialize[Task[B]] =
sequential(List(unitTask(task0), unitTask(task1), unitTask(task2)), last)
def sequential[A0, A1, A2, A3, B](task0: Initialize[Task[A0]], task1: Initialize[Task[A1]], task2: Initialize[Task[A2]], task3: Initialize[Task[A3]],
last: Initialize[Task[B]]): Initialize[Task[B]] =
sequential(List(unitTask(task0), unitTask(task1), unitTask(task2), unitTask(task3)), last)
def sequential[A0, A1, A2, A3, A4, B](task0: Initialize[Task[A0]], task1: Initialize[Task[A1]], task2: Initialize[Task[A2]], task3: Initialize[Task[A3]], task4: Initialize[Task[A4]],
last: Initialize[Task[B]]): Initialize[Task[B]] =
sequential(List(unitTask(task0), unitTask(task1), unitTask(task2), unitTask(task3), unitTask(task4)), last)
def sequential[A0, A1, A2, A3, A4, A5, B](task0: Initialize[Task[A0]], task1: Initialize[Task[A1]], task2: Initialize[Task[A2]], task3: Initialize[Task[A3]], task4: Initialize[Task[A4]], task5: Initialize[Task[A5]],
last: Initialize[Task[B]]): Initialize[Task[B]] =
sequential(List(unitTask(task0), unitTask(task1), unitTask(task2), unitTask(task3), unitTask(task4), unitTask(task5)), last)
def sequential[A0, A1, A2, A3, A4, A5, A6, B](task0: Initialize[Task[A0]], task1: Initialize[Task[A1]], task2: Initialize[Task[A2]], task3: Initialize[Task[A3]], task4: Initialize[Task[A4]], task5: Initialize[Task[A5]], task6: Initialize[Task[A6]],
last: Initialize[Task[B]]): Initialize[Task[B]] =
sequential(List(unitTask(task0), unitTask(task1), unitTask(task2), unitTask(task3), unitTask(task4), unitTask(task5), unitTask(task6)), last)
def sequential[A0, A1, A2, A3, A4, A5, A6, A7, B](task0: Initialize[Task[A0]], task1: Initialize[Task[A1]], task2: Initialize[Task[A2]], task3: Initialize[Task[A3]], task4: Initialize[Task[A4]], task5: Initialize[Task[A5]], task6: Initialize[Task[A6]], task7: Initialize[Task[A7]],
last: Initialize[Task[B]]): Initialize[Task[B]] =
sequential(List(unitTask(task0), unitTask(task1), unitTask(task2), unitTask(task3), unitTask(task4), unitTask(task5), unitTask(task6), unitTask(task7)), last)
def sequential[A0, A1, A2, A3, A4, A5, A6, A7, A8, B](task0: Initialize[Task[A0]], task1: Initialize[Task[A1]], task2: Initialize[Task[A2]], task3: Initialize[Task[A3]], task4: Initialize[Task[A4]], task5: Initialize[Task[A5]], task6: Initialize[Task[A6]], task7: Initialize[Task[A7]], task8: Initialize[Task[A8]],
last: Initialize[Task[B]]): Initialize[Task[B]] =
sequential(List(unitTask(task0), unitTask(task1), unitTask(task2), unitTask(task3), unitTask(task4), unitTask(task5), unitTask(task6), unitTask(task7), unitTask(task8)), last)
def sequential[A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, B](task0: Initialize[Task[A0]], task1: Initialize[Task[A1]], task2: Initialize[Task[A2]], task3: Initialize[Task[A3]], task4: Initialize[Task[A4]], task5: Initialize[Task[A5]], task6: Initialize[Task[A6]], task7: Initialize[Task[A7]], task8: Initialize[Task[A8]], task9: Initialize[Task[A9]],
last: Initialize[Task[B]]): Initialize[Task[B]] =
sequential(List(unitTask(task0), unitTask(task1), unitTask(task2), unitTask(task3), unitTask(task4), unitTask(task5), unitTask(task6), unitTask(task7), unitTask(task8), unitTask(task9)), last)
def sequential[A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, B](task0: Initialize[Task[A0]], task1: Initialize[Task[A1]], task2: Initialize[Task[A2]], task3: Initialize[Task[A3]], task4: Initialize[Task[A4]], task5: Initialize[Task[A5]], task6: Initialize[Task[A6]], task7: Initialize[Task[A7]], task8: Initialize[Task[A8]], task9: Initialize[Task[A9]], task10: Initialize[Task[A10]],
last: Initialize[Task[B]]): Initialize[Task[B]] =
sequential(List(unitTask(task0), unitTask(task1), unitTask(task2), unitTask(task3), unitTask(task4), unitTask(task5), unitTask(task6), unitTask(task7), unitTask(task8), unitTask(task9), unitTask(task10)), last)
def sequential[A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, B](task0: Initialize[Task[A0]], task1: Initialize[Task[A1]], task2: Initialize[Task[A2]], task3: Initialize[Task[A3]], task4: Initialize[Task[A4]], task5: Initialize[Task[A5]], task6: Initialize[Task[A6]], task7: Initialize[Task[A7]], task8: Initialize[Task[A8]], task9: Initialize[Task[A9]], task10: Initialize[Task[A10]], task11: Initialize[Task[A11]],
last: Initialize[Task[B]]): Initialize[Task[B]] =
sequential(List(unitTask(task0), unitTask(task1), unitTask(task2), unitTask(task3), unitTask(task4), unitTask(task5), unitTask(task6), unitTask(task7), unitTask(task8), unitTask(task9), unitTask(task10), unitTask(task11)), last)
def sequential[A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, B](task0: Initialize[Task[A0]], task1: Initialize[Task[A1]], task2: Initialize[Task[A2]], task3: Initialize[Task[A3]], task4: Initialize[Task[A4]], task5: Initialize[Task[A5]], task6: Initialize[Task[A6]], task7: Initialize[Task[A7]], task8: Initialize[Task[A8]], task9: Initialize[Task[A9]], task10: Initialize[Task[A10]], task11: Initialize[Task[A11]], task12: Initialize[Task[A12]],
last: Initialize[Task[B]]): Initialize[Task[B]] =
sequential(List(unitTask(task0), unitTask(task1), unitTask(task2), unitTask(task3), unitTask(task4), unitTask(task5), unitTask(task6), unitTask(task7), unitTask(task8), unitTask(task9), unitTask(task10), unitTask(task11), unitTask(task12)), last)
def sequential[A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, B](task0: Initialize[Task[A0]], task1: Initialize[Task[A1]], task2: Initialize[Task[A2]], task3: Initialize[Task[A3]], task4: Initialize[Task[A4]], task5: Initialize[Task[A5]], task6: Initialize[Task[A6]], task7: Initialize[Task[A7]], task8: Initialize[Task[A8]], task9: Initialize[Task[A9]], task10: Initialize[Task[A10]], task11: Initialize[Task[A11]], task12: Initialize[Task[A12]], task13: Initialize[Task[A13]],
last: Initialize[Task[B]]): Initialize[Task[B]] =
sequential(List(unitTask(task0), unitTask(task1), unitTask(task2), unitTask(task3), unitTask(task4), unitTask(task5), unitTask(task6), unitTask(task7), unitTask(task8), unitTask(task9), unitTask(task10), unitTask(task11), unitTask(task12), unitTask(task13)), last)
def sequential[A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, B](task0: Initialize[Task[A0]], task1: Initialize[Task[A1]], task2: Initialize[Task[A2]], task3: Initialize[Task[A3]], task4: Initialize[Task[A4]], task5: Initialize[Task[A5]], task6: Initialize[Task[A6]], task7: Initialize[Task[A7]], task8: Initialize[Task[A8]], task9: Initialize[Task[A9]], task10: Initialize[Task[A10]], task11: Initialize[Task[A11]], task12: Initialize[Task[A12]], task13: Initialize[Task[A13]], task14: Initialize[Task[A14]],
last: Initialize[Task[B]]): Initialize[Task[B]] =
sequential(List(unitTask(task0), unitTask(task1), unitTask(task2), unitTask(task3), unitTask(task4), unitTask(task5), unitTask(task6), unitTask(task7), unitTask(task8), unitTask(task9), unitTask(task10), unitTask(task11), unitTask(task12), unitTask(task13), unitTask(task14)), last)
def sequential[A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, B](task0: Initialize[Task[A0]], task1: Initialize[Task[A1]], task2: Initialize[Task[A2]], task3: Initialize[Task[A3]], task4: Initialize[Task[A4]], task5: Initialize[Task[A5]], task6: Initialize[Task[A6]], task7: Initialize[Task[A7]], task8: Initialize[Task[A8]], task9: Initialize[Task[A9]], task10: Initialize[Task[A10]], task11: Initialize[Task[A11]], task12: Initialize[Task[A12]], task13: Initialize[Task[A13]], task14: Initialize[Task[A14]], task15: Initialize[Task[A15]],
last: Initialize[Task[B]]): Initialize[Task[B]] =
sequential(List(unitTask(task0), unitTask(task1), unitTask(task2), unitTask(task3), unitTask(task4), unitTask(task5), unitTask(task6), unitTask(task7), unitTask(task8), unitTask(task9), unitTask(task10), unitTask(task11), unitTask(task12), unitTask(task13), unitTask(task14), unitTask(task15)), last)
def sequential[A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, B](task0: Initialize[Task[A0]], task1: Initialize[Task[A1]], task2: Initialize[Task[A2]], task3: Initialize[Task[A3]], task4: Initialize[Task[A4]], task5: Initialize[Task[A5]], task6: Initialize[Task[A6]], task7: Initialize[Task[A7]], task8: Initialize[Task[A8]], task9: Initialize[Task[A9]], task10: Initialize[Task[A10]], task11: Initialize[Task[A11]], task12: Initialize[Task[A12]], task13: Initialize[Task[A13]], task14: Initialize[Task[A14]], task15: Initialize[Task[A15]], task16: Initialize[Task[A16]],
last: Initialize[Task[B]]): Initialize[Task[B]] =
sequential(List(unitTask(task0), unitTask(task1), unitTask(task2), unitTask(task3), unitTask(task4), unitTask(task5), unitTask(task6), unitTask(task7), unitTask(task8), unitTask(task9), unitTask(task10), unitTask(task11), unitTask(task12), unitTask(task13), unitTask(task14), unitTask(task15), unitTask(task16)), last)
def sequential[A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, B](task0: Initialize[Task[A0]], task1: Initialize[Task[A1]], task2: Initialize[Task[A2]], task3: Initialize[Task[A3]], task4: Initialize[Task[A4]], task5: Initialize[Task[A5]], task6: Initialize[Task[A6]], task7: Initialize[Task[A7]], task8: Initialize[Task[A8]], task9: Initialize[Task[A9]], task10: Initialize[Task[A10]], task11: Initialize[Task[A11]], task12: Initialize[Task[A12]], task13: Initialize[Task[A13]], task14: Initialize[Task[A14]], task15: Initialize[Task[A15]], task16: Initialize[Task[A16]], task17: Initialize[Task[A17]],
last: Initialize[Task[B]]): Initialize[Task[B]] =
sequential(List(unitTask(task0), unitTask(task1), unitTask(task2), unitTask(task3), unitTask(task4), unitTask(task5), unitTask(task6), unitTask(task7), unitTask(task8), unitTask(task9), unitTask(task10), unitTask(task11), unitTask(task12), unitTask(task13), unitTask(task14), unitTask(task15), unitTask(task16), unitTask(task17)), last)
def sequential[A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, B](task0: Initialize[Task[A0]], task1: Initialize[Task[A1]], task2: Initialize[Task[A2]], task3: Initialize[Task[A3]], task4: Initialize[Task[A4]], task5: Initialize[Task[A5]], task6: Initialize[Task[A6]], task7: Initialize[Task[A7]], task8: Initialize[Task[A8]], task9: Initialize[Task[A9]], task10: Initialize[Task[A10]], task11: Initialize[Task[A11]], task12: Initialize[Task[A12]], task13: Initialize[Task[A13]], task14: Initialize[Task[A14]], task15: Initialize[Task[A15]], task16: Initialize[Task[A16]], task17: Initialize[Task[A17]], task18: Initialize[Task[A18]],
last: Initialize[Task[B]]): Initialize[Task[B]] =
sequential(List(unitTask(task0), unitTask(task1), unitTask(task2), unitTask(task3), unitTask(task4), unitTask(task5), unitTask(task6), unitTask(task7), unitTask(task8), unitTask(task9), unitTask(task10), unitTask(task11), unitTask(task12), unitTask(task13), unitTask(task14), unitTask(task15), unitTask(task16), unitTask(task17), unitTask(task18)), last)
def sequential[A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, B](task0: Initialize[Task[A0]], task1: Initialize[Task[A1]], task2: Initialize[Task[A2]], task3: Initialize[Task[A3]], task4: Initialize[Task[A4]], task5: Initialize[Task[A5]], task6: Initialize[Task[A6]], task7: Initialize[Task[A7]], task8: Initialize[Task[A8]], task9: Initialize[Task[A9]], task10: Initialize[Task[A10]], task11: Initialize[Task[A11]], task12: Initialize[Task[A12]], task13: Initialize[Task[A13]], task14: Initialize[Task[A14]], task15: Initialize[Task[A15]], task16: Initialize[Task[A16]], task17: Initialize[Task[A17]], task18: Initialize[Task[A18]], task19: Initialize[Task[A19]],
last: Initialize[Task[B]]): Initialize[Task[B]] =
sequential(List(unitTask(task0), unitTask(task1), unitTask(task2), unitTask(task3), unitTask(task4), unitTask(task5), unitTask(task6), unitTask(task7), unitTask(task8), unitTask(task9), unitTask(task10), unitTask(task11), unitTask(task12), unitTask(task13), unitTask(task14), unitTask(task15), unitTask(task16), unitTask(task17), unitTask(task18), unitTask(task19)), last)
def sequential[A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, B](task0: Initialize[Task[A0]], task1: Initialize[Task[A1]], task2: Initialize[Task[A2]], task3: Initialize[Task[A3]], task4: Initialize[Task[A4]], task5: Initialize[Task[A5]], task6: Initialize[Task[A6]], task7: Initialize[Task[A7]], task8: Initialize[Task[A8]], task9: Initialize[Task[A9]], task10: Initialize[Task[A10]], task11: Initialize[Task[A11]], task12: Initialize[Task[A12]], task13: Initialize[Task[A13]], task14: Initialize[Task[A14]], task15: Initialize[Task[A15]], task16: Initialize[Task[A16]], task17: Initialize[Task[A17]], task18: Initialize[Task[A18]], task19: Initialize[Task[A19]], task20: Initialize[Task[A20]],
last: Initialize[Task[B]]): Initialize[Task[B]] =
sequential(List(unitTask(task0), unitTask(task1), unitTask(task2), unitTask(task3), unitTask(task4), unitTask(task5), unitTask(task6), unitTask(task7), unitTask(task8), unitTask(task9), unitTask(task10), unitTask(task11), unitTask(task12), unitTask(task13), unitTask(task14), unitTask(task15), unitTask(task16), unitTask(task17), unitTask(task18), unitTask(task19), unitTask(task20)), last)
def sequential[A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, B](task0: Initialize[Task[A0]], task1: Initialize[Task[A1]], task2: Initialize[Task[A2]], task3: Initialize[Task[A3]], task4: Initialize[Task[A4]], task5: Initialize[Task[A5]], task6: Initialize[Task[A6]], task7: Initialize[Task[A7]], task8: Initialize[Task[A8]], task9: Initialize[Task[A9]], task10: Initialize[Task[A10]], task11: Initialize[Task[A11]], task12: Initialize[Task[A12]], task13: Initialize[Task[A13]], task14: Initialize[Task[A14]], task15: Initialize[Task[A15]], task16: Initialize[Task[A16]], task17: Initialize[Task[A17]], task18: Initialize[Task[A18]], task19: Initialize[Task[A19]], task20: Initialize[Task[A20]], task21: Initialize[Task[A21]],
last: Initialize[Task[B]]): Initialize[Task[B]] =
sequential(List(unitTask(task0), unitTask(task1), unitTask(task2), unitTask(task3), unitTask(task4), unitTask(task5), unitTask(task6), unitTask(task7), unitTask(task8), unitTask(task9), unitTask(task10), unitTask(task11), unitTask(task12), unitTask(task13), unitTask(task14), unitTask(task15), unitTask(task16), unitTask(task17), unitTask(task18), unitTask(task19), unitTask(task20), unitTask(task21)), last)
def sequential[B](tasks: Seq[Initialize[Task[Unit]]], last: Initialize[Task[B]]): Initialize[Task[B]] =
tasks.toList match {
case Nil => Def.task { last.value }
case x :: xs =>
Def.taskDyn {
val _ = x.value
sequential(xs, last)
}
}
private def unitTask[A](task: Initialize[Task[A]]): Initialize[Task[Unit]] =
Def.task {
task.value
()
}
}
// for {
// i <- 0 to 21
// } {
// val idx = 0 to i
// val tparams = (idx map { "A" + _ }).mkString(", ")
// val params = (idx map { j => s"task$j: Initialize[Task[A$j]]" }).mkString(", ")
// val args = (idx map { j => s"unitTask(task$j)" }).mkString(", ")
// println(s""" def sequential[$tparams, B]($params,
// | last: Initialize[Task[B]]): Initialize[Task[B]] =
// | sequential(List($args), last)""".stripMargin)
// }

View File

@ -0,0 +1,40 @@
[@cunei]: https://github.com/cunei
[@eed3si9n]: https://github.com/eed3si9n
[@gkossakowski]: https://github.com/gkossakowski
[@jsuereth]: https://github.com/jsuereth
[1817]: https://github.com/sbt/sbt/pull/1817
[1001]: https://github.com/sbt/sbt/issues/1001
[Custom-Settings0]: http://www.scala-sbt.org/0.13/tutorial/Custom-Settings.html
### Fixes with compatibility implications
### Improvements
### Bug fixes
### Sequential tasks
sbt 0.13.8 adds a new `Def.sequential` function to run tasks under semi-sequential semantics.
Here's an example usage:
lazy val root = project.
settings(
testFile := target.value / "test.txt",
sideEffect0 := {
val t = testFile.value
IO.append(t, "0")
t
},
sideEffect1 := {
val t = testFile.value
IO.append(t, "1")
t
},
foo := Def.sequential(compile in Compile, sideEffect0, sideEffect1, test in Test).value
)
Normally sbt's task engine will reorder tasks based on the dependencies among the tasks,
and run as many tasks in parallel (See [Custom settings and tasks][Custom-Settings0] for more details on this).
`Def.sequential` instead tries to run the tasks in the specified order.
However, the task engine will still deduplicate tasks. For instance, when `foo` is executed, it will only compile once,
even though `test in Test` depends on compile. [#1817][1817]/[#1001][1001] by [@eed3si9n][@eed3si9n]

View File

@ -0,0 +1,39 @@
lazy val foo = taskKey[Int]("foo")
lazy val bar = taskKey[Int]("bar")
lazy val sideEffect0 = taskKey[Unit]("side effect 0")
lazy val sideEffect1 = taskKey[Unit]("side effect 1")
lazy val sideEffect2 = taskKey[Unit]("side effect 2")
lazy val testFile = settingKey[File]("test file")
lazy val check = taskKey[Unit]("check")
lazy val root = project.
settings(
check := {
val x = foo.value
if (x == 1) ()
else sys.error("foo did not return 1")
val t = testFile.value
val s = IO.read(t)
val expected = "012"
if (s == expected) ()
else sys.error(s"""test.txt expected '$expected' but was '$s'.""")
},
testFile := target.value / "test.txt",
sideEffect0 := {
Thread.sleep(100)
val t = testFile.value
IO.append(t, "0")
},
sideEffect1 := {
val t = testFile.value
IO.append(t, "1")
},
sideEffect2 := {
// check for deduplication of tasks
val _ = sideEffect1.value
val t = testFile.value
IO.append(t, "2")
},
foo := Def.sequential(compile in Compile, sideEffect0, sideEffect1, sideEffect2, test in Test, bar).value,
bar := 1
)

View File

@ -0,0 +1 @@
> check