diff --git a/main/settings/src/main/scala/sbt/std/TaskMacro.scala b/main/settings/src/main/scala/sbt/std/TaskMacro.scala index 6c48613dd..76392716b 100644 --- a/main/settings/src/main/scala/sbt/std/TaskMacro.scala +++ b/main/settings/src/main/scala/sbt/std/TaskMacro.scala @@ -18,7 +18,7 @@ object TaskInstance extends MonadInstance { import TaskExtra._ final type M[x] = Task[x] - def app[K[L[x]], Z](in: K[Task], f: K[Id] => Z)(implicit a: AList[K]): Task[Z] = Task(Info(), new Mapped[Z, K](in, f compose allM, a)) + def app[K[L[x]], Z](in: K[Task], f: K[Id] => Z)(implicit a: AList[K]): Task[Z] = in map f def map[S, T](in: Task[S], f: S => T): Task[T] = in map f def flatten[T](in: Task[Task[T]]): Task[T] = in flatMap idFun[Task[T]] def pure[T](t: () => T): Task[T] = toTask(t) diff --git a/sbt/src/sbt-test/actions/depends-on/build.sbt b/sbt/src/sbt-test/actions/depends-on/build.sbt index c20f79671..8a319ce52 100644 --- a/sbt/src/sbt-test/actions/depends-on/build.sbt +++ b/sbt/src/sbt-test/actions/depends-on/build.sbt @@ -14,7 +14,7 @@ lazy val d = taskKey[Unit]("") lazy val input = (project in file("input")). settings( - f := (inputTask { _ map { args => if (args(0) == "succeed") () else sys.error("fail") } }).evaluated, + f := (if (Def.spaceDelimited().parsed.head == "succeed") () else sys.error("fail")), j := sys.error("j"), g := (f dependsOn(j)).evaluated, h := (f map { _ => IO.touch(file("h")) }).evaluated diff --git a/sbt/src/sbt-test/actions/task-map/build.sbt b/sbt/src/sbt-test/actions/task-map/build.sbt new file mode 100644 index 000000000..34c26b3b9 --- /dev/null +++ b/sbt/src/sbt-test/actions/task-map/build.sbt @@ -0,0 +1,38 @@ +val taskA = taskKey[File]("") +val taskB = taskKey[File]("") +val taskC = taskKey[File]("") +val taskD = taskKey[File]("") + +val taskE = taskKey[File]("") +val taskF = taskKey[File]("") +val taskG = taskKey[File]("") +val taskH = taskKey[File]("") + +taskA := touch(target.value / "a") +taskB := touch(target.value / "b") +taskC := touch(target.value / "c") +taskD := touch(target.value / "d") + +taskE := touch(target.value / "e") +taskF := touch(target.value / "f") +taskG := touch(target.value / "g") +taskH := touch(target.value / "h") + +// a <<= a triggeredBy b +// means "a" will be triggered by "b" +// said differently, invoking "b" will run "b" and then run "a" + +taskA <<= taskA triggeredBy taskB +taskC := (taskC triggeredBy taskD).value + +// e <<= e runBefore f +// means "e" will be run before running "f" +// said differently, invoking "f" will run "e" and then run "f" + +taskE <<= taskE runBefore taskF +taskG := (taskG runBefore taskH).value + + + +// test utils +def touch(f: File): File = { IO touch f; f } diff --git a/sbt/src/sbt-test/actions/task-map/test b/sbt/src/sbt-test/actions/task-map/test new file mode 100644 index 000000000..0617f3abe --- /dev/null +++ b/sbt/src/sbt-test/actions/task-map/test @@ -0,0 +1,15 @@ +> taskB +$ exists target/b +$ exists target/a + +> taskD +$ exists target/d +$ exists target/c + +> taskF +$ exists target/e +$ exists target/f + +> taskH +$ exists target/g +$ exists target/h diff --git a/tasks/standard/src/main/scala/sbt/std/TaskExtra.scala b/tasks/standard/src/main/scala/sbt/std/TaskExtra.scala index 10914daee..716686241 100644 --- a/tasks/standard/src/main/scala/sbt/std/TaskExtra.scala +++ b/tasks/standard/src/main/scala/sbt/std/TaskExtra.scala @@ -117,9 +117,14 @@ trait TaskExtra { def failure: Task[Incomplete] = mapFailure(idFun) def result: Task[Result[S]] = mapR(idFun) - def flatMapR[T](f: Result[S] => Task[T]): Task[T] = Task(Info(), new FlatMapped[T, K](in, f, ml)) - def mapR[T](f: Result[S] => T): Task[T] = Task(Info(), new Mapped[T, K](in, f, ml)) - def dependsOn(tasks: Task[_]*): Task[S] = Task(Info(), new DependsOn(in, tasks)) + // The "taskDefinitionKey" is used, at least, by the ".previous" functionality. + // But apparently it *cannot* survive a task map/flatMap/etc. See actions/depends-on. + private def newInfo[A]: Info[A] = + Info[A](AttributeMap(in.info.attributes.entries.filter(_.key.label != "taskDefinitionKey"))) + + def flatMapR[T](f: Result[S] => Task[T]): Task[T] = Task(newInfo, new FlatMapped[T, K](in, f, ml)) + def mapR[T](f: Result[S] => T): Task[T] = Task(newInfo, new Mapped[T, K](in, f, ml)) + def dependsOn(tasks: Task[_]*): Task[S] = Task(newInfo, new DependsOn(in, tasks)) def flatMap[T](f: S => Task[T]): Task[T] = flatMapR(f compose successM) def flatFailure[T](f: Incomplete => Task[T]): Task[T] = flatMapR(f compose failM)