From 88ded6cb214c17e82c5e7529cb7d8c723c53969a Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Wed, 11 Jan 2017 17:06:05 +0000 Subject: [PATCH 1/7] Fix triggeredBy with := Fixes #1444 --- .../sbt-test/actions/triggeredby/build.sbt | 21 +++++++++++++++++++ sbt/src/sbt-test/actions/triggeredby/test | 7 +++++++ .../src/main/scala/sbt/std/TaskExtra.scala | 8 ++++++- 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 sbt/src/sbt-test/actions/triggeredby/build.sbt create mode 100644 sbt/src/sbt-test/actions/triggeredby/test diff --git a/sbt/src/sbt-test/actions/triggeredby/build.sbt b/sbt/src/sbt-test/actions/triggeredby/build.sbt new file mode 100644 index 000000000..08367b448 --- /dev/null +++ b/sbt/src/sbt-test/actions/triggeredby/build.sbt @@ -0,0 +1,21 @@ +val taskA = taskKey[File]("") +val taskB = taskKey[File]("") +val taskC = taskKey[File]("") +val taskD = taskKey[File]("") + +taskA := touch(target.value / "a") +taskB := touch(target.value / "b") +taskC := touch(target.value / "c") +taskD := touch(target.value / "d") + +// 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 + + + +// test utils +def touch(f: File): File = { IO touch f; f } diff --git a/sbt/src/sbt-test/actions/triggeredby/test b/sbt/src/sbt-test/actions/triggeredby/test new file mode 100644 index 000000000..063b1fbb1 --- /dev/null +++ b/sbt/src/sbt-test/actions/triggeredby/test @@ -0,0 +1,7 @@ +> taskB +$ exists target/b +$ exists target/a + +> taskD +$ exists target/d +$ exists target/c diff --git a/tasks-standard/src/main/scala/sbt/std/TaskExtra.scala b/tasks-standard/src/main/scala/sbt/std/TaskExtra.scala index cf5aa7c34..15a37aa93 100644 --- a/tasks-standard/src/main/scala/sbt/std/TaskExtra.scala +++ b/tasks-standard/src/main/scala/sbt/std/TaskExtra.scala @@ -120,8 +120,14 @@ trait TaskExtra { def failure: Task[Incomplete] = mapFailure(idFun) def result: Task[Result[S]] = mapR(idFun) + private val triggeredByKey = AttributeKey[Seq[Task[_]]]("triggered-by") + private def newInfo[A]: Info[A] = { + val i = Info[A]() + (in.info get triggeredByKey).fold(i)(i.set(triggeredByKey, _)) + } + 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 mapR[T](f: Result[S] => T): Task[T] = Task(newInfo, new Mapped[T, K](in, f, ml)) def dependsOn(tasks: Task[_]*): Task[S] = Task(Info(), new DependsOn(in, tasks)) def flatMap[T](f: S => Task[T]): Task[T] = flatMapR(f compose successM) From 570ef0a379c64f5b1119bbfd8634923687d5d001 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 12 Jan 2017 14:41:12 +0000 Subject: [PATCH 2/7] Fix runBefore with := --- .../actions/{triggeredby => task-map}/build.sbt | 17 +++++++++++++++++ sbt/src/sbt-test/actions/task-map/test | 15 +++++++++++++++ sbt/src/sbt-test/actions/triggeredby/test | 7 ------- .../src/main/scala/sbt/std/TaskExtra.scala | 9 +++++---- 4 files changed, 37 insertions(+), 11 deletions(-) rename sbt/src/sbt-test/actions/{triggeredby => task-map}/build.sbt (53%) create mode 100644 sbt/src/sbt-test/actions/task-map/test delete mode 100644 sbt/src/sbt-test/actions/triggeredby/test diff --git a/sbt/src/sbt-test/actions/triggeredby/build.sbt b/sbt/src/sbt-test/actions/task-map/build.sbt similarity index 53% rename from sbt/src/sbt-test/actions/triggeredby/build.sbt rename to sbt/src/sbt-test/actions/task-map/build.sbt index 08367b448..34c26b3b9 100644 --- a/sbt/src/sbt-test/actions/triggeredby/build.sbt +++ b/sbt/src/sbt-test/actions/task-map/build.sbt @@ -3,11 +3,21 @@ 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" @@ -15,6 +25,13 @@ taskD := touch(target.value / "d") 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 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/sbt/src/sbt-test/actions/triggeredby/test b/sbt/src/sbt-test/actions/triggeredby/test deleted file mode 100644 index 063b1fbb1..000000000 --- a/sbt/src/sbt-test/actions/triggeredby/test +++ /dev/null @@ -1,7 +0,0 @@ -> taskB -$ exists target/b -$ exists target/a - -> taskD -$ exists target/d -$ exists target/c diff --git a/tasks-standard/src/main/scala/sbt/std/TaskExtra.scala b/tasks-standard/src/main/scala/sbt/std/TaskExtra.scala index 15a37aa93..b803e097e 100644 --- a/tasks-standard/src/main/scala/sbt/std/TaskExtra.scala +++ b/tasks-standard/src/main/scala/sbt/std/TaskExtra.scala @@ -121,10 +121,11 @@ trait TaskExtra { def result: Task[Result[S]] = mapR(idFun) private val triggeredByKey = AttributeKey[Seq[Task[_]]]("triggered-by") - private def newInfo[A]: Info[A] = { - val i = Info[A]() - (in.info get triggeredByKey).fold(i)(i.set(triggeredByKey, _)) - } + private val runBeforeKey = AttributeKey[Seq[Task[_]]]("run-before") + private def newInfo[A]: Info[A] = + Seq(triggeredByKey, runBeforeKey) + .flatMap(k => (in.info get k) map (k -> _)) + .foldLeft(Info[A]()) { case (i, (k, v)) => i.set(k, v) } 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(newInfo, new Mapped[T, K](in, f, ml)) From 7cd285f1b087f7e1da8f894d8a46f4b564e78b61 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 12 Jan 2017 16:00:44 +0000 Subject: [PATCH 3/7] Copy all attributes for all methods in SingleInTask For when := is used over <<= for 'triggeredBy', 'runBefore', etc.. --- tasks-standard/src/main/scala/sbt/std/TaskExtra.scala | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/tasks-standard/src/main/scala/sbt/std/TaskExtra.scala b/tasks-standard/src/main/scala/sbt/std/TaskExtra.scala index b803e097e..d14b1fad0 100644 --- a/tasks-standard/src/main/scala/sbt/std/TaskExtra.scala +++ b/tasks-standard/src/main/scala/sbt/std/TaskExtra.scala @@ -120,16 +120,11 @@ trait TaskExtra { def failure: Task[Incomplete] = mapFailure(idFun) def result: Task[Result[S]] = mapR(idFun) - private val triggeredByKey = AttributeKey[Seq[Task[_]]]("triggered-by") - private val runBeforeKey = AttributeKey[Seq[Task[_]]]("run-before") - private def newInfo[A]: Info[A] = - Seq(triggeredByKey, runBeforeKey) - .flatMap(k => (in.info get k) map (k -> _)) - .foldLeft(Info[A]()) { case (i, (k, v)) => i.set(k, v) } + private def newInfo[A]: Info[A] = Info[A](in.info.attributes) - def flatMapR[T](f: Result[S] => Task[T]): Task[T] = Task(Info(), new FlatMapped[T, K](in, f, ml)) + 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(Info(), new DependsOn(in, tasks)) + 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) From 7d5dd9999dc22fb158f3b2b871d11f64fb1528ed Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 12 Jan 2017 16:13:51 +0000 Subject: [PATCH 4/7] Remove some code duplication between TaskInstance and MultiInTask --- main-settings/src/main/scala/sbt/std/TaskMacro.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main-settings/src/main/scala/sbt/std/TaskMacro.scala b/main-settings/src/main/scala/sbt/std/TaskMacro.scala index 11604e0a6..a0c2beda7 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) From 7ca327fc08351e27692c18652f685db2864e3212 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Fri, 13 Jan 2017 12:05:03 +0000 Subject: [PATCH 5/7] Migrate actions/depends-on to fix it Seems following the deprecation warning info and the website documentation and avoiding the BuildCommon inputTask method avoids whatever problem was causing it to fail... Strange.. but ok? --- sbt/src/sbt-test/actions/depends-on/build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From c9ba9502a77a1ed2bf3328b21173165c56d7d14b Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Fri, 13 Jan 2017 14:22:49 +0000 Subject: [PATCH 6/7] Work-around actions/depends-on failure --- tasks-standard/src/main/scala/sbt/std/TaskExtra.scala | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tasks-standard/src/main/scala/sbt/std/TaskExtra.scala b/tasks-standard/src/main/scala/sbt/std/TaskExtra.scala index d14b1fad0..96c2678ee 100644 --- a/tasks-standard/src/main/scala/sbt/std/TaskExtra.scala +++ b/tasks-standard/src/main/scala/sbt/std/TaskExtra.scala @@ -6,7 +6,7 @@ package std import scala.sys.process.{ BasicIO, ProcessIO, ProcessBuilder } -import sbt.internal.util.AList +import sbt.internal.util.{ AList, AttributeMap } import sbt.internal.util.Types._ import java.io.{ BufferedInputStream, BufferedReader, File, InputStream } import sbt.io.IO @@ -120,7 +120,10 @@ trait TaskExtra { def failure: Task[Incomplete] = mapFailure(idFun) def result: Task[Result[S]] = mapR(idFun) - private def newInfo[A]: Info[A] = Info[A](in.info.attributes) + // 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)) From 690f1c4470cca11eedbd5e4d64540597fafaa587 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Tue, 4 Apr 2017 19:12:00 -0400 Subject: [PATCH 7/7] Adjust actions/task-map --- sbt/src/sbt-test/actions/task-map/build.sbt | 16 ++-------------- sbt/src/sbt-test/actions/task-map/test | 8 -------- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/sbt/src/sbt-test/actions/task-map/build.sbt b/sbt/src/sbt-test/actions/task-map/build.sbt index 34c26b3b9..57a7dcc3a 100644 --- a/sbt/src/sbt-test/actions/task-map/build.sbt +++ b/sbt/src/sbt-test/actions/task-map/build.sbt @@ -1,38 +1,26 @@ 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 +taskA := (taskA triggeredBy taskB).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 - - +taskE := (taskE runBefore taskF).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 index 0617f3abe..3a88d40a7 100644 --- a/sbt/src/sbt-test/actions/task-map/test +++ b/sbt/src/sbt-test/actions/task-map/test @@ -2,14 +2,6 @@ $ 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