From fb27f5558c92fa0cabd3b079e46f0d12f34fe17f Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Sat, 15 Jun 2013 23:55:05 -0400 Subject: [PATCH] Propagate taskDefinitionKey in Incompletes from flatMaps. Ref #784. --- main/src/main/scala/sbt/EvaluateTask.scala | 7 ++++++- main/src/main/scala/sbt/Load.scala | 2 +- tasks/src/main/scala/sbt/Execute.scala | 15 ++++++++++++--- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/main/src/main/scala/sbt/EvaluateTask.scala b/main/src/main/scala/sbt/EvaluateTask.scala index 7db2beb9e..a2d795819 100644 --- a/main/src/main/scala/sbt/EvaluateTask.scala +++ b/main/src/main/scala/sbt/EvaluateTask.scala @@ -156,8 +156,13 @@ object EvaluateTask val tags = tagged[Task[_]](_.info get tagsKey getOrElse Map.empty, Tags.predicate(config.restrictions)) val (service, shutdown) = completionService[Task[_], Completed](tags, (s: String) => log.warn(s)) + // propagate the defining key for reporting the origin + def overwriteNode(i: Incomplete): Boolean = i.node match { + case Some(t: Task[_]) => transformNode(t).isEmpty + case _ => true + } def run() = { - val x = new Execute[Task](config.checkCycles, triggers)(taskToNode) + val x = Execute[Task]( Execute.config(config.checkCycles, overwriteNode), triggers)(taskToNode) val (newState, result) = try applyResults(x.runKeep(root)(service), state, root) catch { case inc: Incomplete => (state, Inc(inc)) } diff --git a/main/src/main/scala/sbt/Load.scala b/main/src/main/scala/sbt/Load.scala index 06855c7c2..c89683af2 100755 --- a/main/src/main/scala/sbt/Load.scala +++ b/main/src/main/scala/sbt/Load.scala @@ -146,7 +146,7 @@ object Load // map dependencies on the special tasks: // 1. the scope of 'streams' is the same as the defining key and has the task axis set to the defining key - // 2. the defining key is stored on constructed tasks + // 2. the defining key is stored on constructed tasks: used for error reporting among other things // 3. resolvedScoped is replaced with the defining key as a value // Note: this must be idempotent. def finalTransforms(ss: Seq[Setting[_]]): Seq[Setting[_]] = diff --git a/tasks/src/main/scala/sbt/Execute.scala b/tasks/src/main/scala/sbt/Execute.scala index 432255847..b47309358 100644 --- a/tasks/src/main/scala/sbt/Execute.scala +++ b/tasks/src/main/scala/sbt/Execute.scala @@ -19,6 +19,12 @@ object Execute def process() { p } } def noTriggers[A[_]] = new Triggers[A](Map.empty, Map.empty, idFun) + + def apply[A[_] <: AnyRef](config: Config, triggers: Triggers[A])(implicit view: NodeView[A]): Execute[A] = + new Execute(config, triggers)(view) + + def config(checkCycles: Boolean, overwriteNode: Incomplete => Boolean = const(false)): Config = new Config(checkCycles, overwriteNode) + final class Config private[sbt](val checkCycles: Boolean, val overwriteNode: Incomplete => Boolean) } sealed trait Completed { def process(): Unit @@ -30,8 +36,11 @@ trait NodeView[A[_]] } final class Triggers[A[_]](val runBefore: collection.Map[A[_], Seq[A[_]]], val injectFor: collection.Map[A[_], Seq[A[_]]], val onComplete: RMap[A,Result] => RMap[A,Result]) -final class Execute[A[_] <: AnyRef](checkCycles: Boolean, triggers: Triggers[A])(implicit view: NodeView[A]) +final class Execute[A[_] <: AnyRef] private(config: Config, triggers: Triggers[A])(implicit view: NodeView[A]) { + @deprecated("Use Execute.apply", "0.13.0") + def this(checkCycles: Boolean, triggers: Triggers[A])(implicit view: NodeView[A]) = this(Execute.config(checkCycles), triggers)(view) + type Strategy = CompletionService[A[_], Completed] private[this] val forward = idMap[A[_], IDSet[A[_]] ] @@ -93,7 +102,7 @@ final class Execute[A[_] <: AnyRef](checkCycles: Boolean, triggers: Triggers[A]) def call[T](node: A[T], target: A[T])(implicit strategy: Strategy) { - if(checkCycles) cycleCheck(node, target) + if(config.checkCycles) cycleCheck(node, target) pre { assert( running(node) ) readyInv( node ) @@ -232,7 +241,7 @@ final class Execute[A[_] <: AnyRef](checkCycles: Boolean, triggers: Triggers[A]) def work[T](node: A[T], f: => Either[A[T], T])(implicit strategy: Strategy): Completed = { val result = wideConvert(f).left.map { - case i: Incomplete => if(i.node.isEmpty) i.copy(node = Some(node)) else i + case i: Incomplete => if(config.overwriteNode(i)) i.copy(node = Some(node)) else i case e => Incomplete(Some(node), Incomplete.Error, directCause = Some(e)) } completed {