mirror of https://github.com/sbt/sbt.git
Part #2 of task cancellation hooks.
* Expose new EvaluateTaskConfig throughout all the APIs * Create a key for cancellation configuration * Add default values for cancellation in GlobalPlugin * Create a test to ensure that cancellation can cancel tasks. * Deprecate all the existing mechanisms of evaluating tasks which use the EvaluateConfig API.
This commit is contained in:
parent
6e480fc2b6
commit
171eb19b96
|
|
@ -59,7 +59,7 @@ final object Aggregation
|
|||
import extracted.structure
|
||||
val toRun = ts map { case KeyValue(k,t) => t.map(v => KeyValue(k,v)) } join;
|
||||
val roots = ts map { case KeyValue(k,_) => k }
|
||||
val config = extractedConfig(extracted, structure, s)
|
||||
val config = extractedTaskConfig(extracted, structure, s)
|
||||
|
||||
val start = System.currentTimeMillis
|
||||
val (newS, result) = withStreams(structure, s){ str =>
|
||||
|
|
|
|||
|
|
@ -120,6 +120,10 @@ object Defaults extends BuildCommon
|
|||
trapExit :== true,
|
||||
connectInput :== false,
|
||||
cancelable :== false,
|
||||
taskCancelHandler := { state: State =>
|
||||
if(cancelable.value) TaskEvaluationCancelHandler.Signal
|
||||
else TaskEvaluationCancelHandler.Null
|
||||
},
|
||||
envVars :== Map.empty,
|
||||
sbtVersion := appConfiguration.value.provider.id.version,
|
||||
sbtBinaryVersion := binarySbtVersion(sbtVersion.value),
|
||||
|
|
|
|||
|
|
@ -79,6 +79,19 @@ final object EvaluateTaskConfig {
|
|||
}
|
||||
AdaptedTaskConfig
|
||||
}
|
||||
/** Raw constructor for EvaluateTaskConfig. */
|
||||
def apply(restrictions: Seq[Tags.Rule],
|
||||
checkCycles: Boolean,
|
||||
progressReporter: ExecuteProgress[Task],
|
||||
cancelHandler: TaskEvaluationCancelHandler): EvaluateTaskConfig = {
|
||||
object SimpleEvaluateTaskConfig extends EvaluateTaskConfig {
|
||||
def restrictions = restrictions
|
||||
def checkCycles = checkCycles
|
||||
def progressReporter = progressReporter
|
||||
def cancelHandler = cancelHandler
|
||||
}
|
||||
SimpleEvaluateTaskConfig
|
||||
}
|
||||
}
|
||||
|
||||
final case class PluginData(dependencyClasspath: Seq[Attributed[File]], definitionClasspath: Seq[Attributed[File]], resolvers: Option[Seq[Resolver]], report: Option[UpdateReport], scalacOptions: Seq[String])
|
||||
|
|
@ -106,24 +119,25 @@ object EvaluateTask
|
|||
|
||||
val SystemProcessors = Runtime.getRuntime.availableProcessors
|
||||
|
||||
@deprecated("Use extractedConfig.", "0.13.0")
|
||||
@deprecated("Use extractedTaskConfig.", "0.13.0")
|
||||
def defaultConfig(state: State): EvaluateConfig =
|
||||
{
|
||||
val extracted = Project.extract(state)
|
||||
extractedConfig(extracted, extracted.structure, state)
|
||||
}
|
||||
|
||||
@deprecated("Use extractedConfig.", "0.13.0")
|
||||
@deprecated("Use extractedTaskConfig.", "0.13.0")
|
||||
def defaultConfig(extracted: Extracted, structure: BuildStructure) =
|
||||
EvaluateConfig(false, restrictions(extracted, structure), progress = defaultProgress)
|
||||
|
||||
@deprecated("Use other extractedConfig", "0.13.2")
|
||||
@deprecated("Use other extractedTaskConfig", "0.13.2")
|
||||
def extractedConfig(extracted: Extracted, structure: BuildStructure): EvaluateConfig =
|
||||
{
|
||||
val workers = restrictions(extracted, structure)
|
||||
val canCancel = cancelable(extracted, structure)
|
||||
EvaluateConfig(cancelable = canCancel, restrictions = workers, progress = defaultProgress)
|
||||
}
|
||||
@deprecated("Use other extractedTaskConfig", "0.13.5")
|
||||
def extractedConfig(extracted: Extracted, structure: BuildStructure, state: State): EvaluateConfig =
|
||||
{
|
||||
val workers = restrictions(extracted, structure)
|
||||
|
|
@ -131,6 +145,13 @@ object EvaluateTask
|
|||
val progress = executeProgress(extracted, structure, state)
|
||||
EvaluateConfig(cancelable = canCancel, restrictions = workers, progress = progress)
|
||||
}
|
||||
def extractedTaskConfig(extracted: Extracted, structure: BuildStructure, state: State): EvaluateTaskConfig =
|
||||
{
|
||||
val rs = restrictions(extracted, structure)
|
||||
val canceller = cancelHandler(extracted, structure, state)
|
||||
val progress = executeProgress(extracted, structure, state)
|
||||
EvaluateTaskConfig(rs, false, progress, canceller)
|
||||
}
|
||||
|
||||
def defaultRestrictions(maxWorkers: Int) = Tags.limitAll(maxWorkers) :: Nil
|
||||
def defaultRestrictions(extracted: Extracted, structure: BuildStructure): Seq[Tags.Rule] =
|
||||
|
|
@ -150,11 +171,13 @@ object EvaluateTask
|
|||
1
|
||||
def cancelable(extracted: Extracted, structure: BuildStructure): Boolean =
|
||||
getSetting(Keys.cancelable, false, extracted, structure)
|
||||
def cancelHandler(extracted: Extracted, structure: BuildStructure, state: State): TaskEvaluationCancelHandler =
|
||||
getSetting(Keys.taskCancelHandler, {(_: State) => TaskEvaluationCancelHandler.Null}, extracted, structure)(state)
|
||||
|
||||
private[sbt] def executeProgress(extracted: Extracted, structure: BuildStructure, state: State): ExecuteProgress[Task] = {
|
||||
import Types.const
|
||||
val maker: State => Keys.TaskProgress = getSetting(Keys.executeProgress, const(new Keys.TaskProgress(defaultProgress)), extracted, structure)
|
||||
maker(state).progress
|
||||
val maker: State => Keys.TaskProgress = getSetting(Keys.executeProgress, const(new Keys.TaskProgress(defaultProgress)), extracted, structure)
|
||||
maker(state).progress
|
||||
}
|
||||
|
||||
def getSetting[T](key: SettingKey[T], default: T, extracted: Extracted, structure: BuildStructure): T =
|
||||
|
|
@ -185,16 +208,20 @@ object EvaluateTask
|
|||
* If the task is not defined, None is returned. The provided task key is resolved against the current project `ref`.
|
||||
* Task execution is configured according to settings defined in the loaded project.*/
|
||||
def apply[T](structure: BuildStructure, taskKey: ScopedKey[Task[T]], state: State, ref: ProjectRef): Option[(State, Result[T])] =
|
||||
apply[T](structure, taskKey, state, ref, extractedConfig(Project.extract(state), structure))
|
||||
apply[T](structure, taskKey, state, ref, extractedTaskConfig(Project.extract(state), structure, state))
|
||||
|
||||
/** Evaluates `taskKey` and returns the new State and the result of the task wrapped in Some.
|
||||
* If the task is not defined, None is returned. The provided task key is resolved against the current project `ref`.
|
||||
* `config` configures concurrency and canceling of task execution. */
|
||||
@deprecated("Use EvalauteTaskConfig option instead.", "0.13.5")
|
||||
def apply[T](structure: BuildStructure, taskKey: ScopedKey[Task[T]], state: State, ref: ProjectRef, config: EvaluateConfig): Option[(State, Result[T])] =
|
||||
apply(structure, taskKey, state, ref, EvaluateTaskConfig(config))
|
||||
def apply[T](structure: BuildStructure, taskKey: ScopedKey[Task[T]], state: State, ref: ProjectRef, config: EvaluateTaskConfig): Option[(State, Result[T])] = {
|
||||
withStreams(structure, state) { str =>
|
||||
for( (task, toNode) <- getTask(structure, taskKey, state, str, ref) ) yield
|
||||
runTask(task, state, str, structure.index.triggers, config)(toNode)
|
||||
}
|
||||
}
|
||||
def logIncResult(result: Result[_], state: State, streams: Streams) = result match { case Inc(i) => logIncomplete(i, state, streams); case _ => () }
|
||||
def logIncomplete(result: Incomplete, state: State, streams: Streams)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -346,6 +346,7 @@ object Keys
|
|||
// wrapper to work around SI-2915
|
||||
private[sbt] final class TaskProgress(val progress: ExecuteProgress[Task])
|
||||
private[sbt] val executeProgress = SettingKey[State => TaskProgress]("executeProgress", "Experimental task execution listener.", DTask)
|
||||
private[sbt] val taskCancelHandler = SettingKey[State => TaskEvaluationCancelHandler]("taskCancelHandler", "Experimental task cancellation handler.", DTask)
|
||||
|
||||
// Experimental in sbt 0.13.2 to enable grabing semantic compile failures.
|
||||
private[sbt] val compilerReporter = TaskKey[Option[xsbti.Reporter]]("compilerReporter", "Experimental hook to listen (or send) compilation failure messages.", DTask)
|
||||
|
|
|
|||
|
|
@ -498,13 +498,25 @@ object Project extends ProjectExtra
|
|||
@deprecated("This method does not apply state changes requested during task execution. Use 'runTask' instead, which does.", "0.11.1")
|
||||
def evaluateTask[T](taskKey: ScopedKey[Task[T]], state: State, checkCycles: Boolean = false, maxWorkers: Int = EvaluateTask.SystemProcessors): Option[Result[T]] =
|
||||
runTask(taskKey, state, EvaluateConfig(true, EvaluateTask.defaultRestrictions(maxWorkers), checkCycles)).map(_._2)
|
||||
|
||||
def runTask[T](taskKey: ScopedKey[Task[T]], state: State, checkCycles: Boolean = false): Option[(State, Result[T])] =
|
||||
runTask(taskKey, state, EvaluateConfig(true, EvaluateTask.restrictions(state), checkCycles))
|
||||
{
|
||||
val extracted = Project.extract(state)
|
||||
val ch = EvaluateTask.cancelHandler(extracted, extracted.structure, state)
|
||||
val p = EvaluateTask.executeProgress(extracted, extracted.structure, state)
|
||||
val r = EvaluateTask.restrictions(state)
|
||||
runTask(taskKey, state, EvaluateTaskConfig(r, checkCycles, p, ch))
|
||||
}
|
||||
@deprecated("Use EvalauteTaskConfig option instead.", "0.13.5")
|
||||
def runTask[T](taskKey: ScopedKey[Task[T]], state: State, config: EvaluateConfig): Option[(State, Result[T])] =
|
||||
{
|
||||
val extracted = Project.extract(state)
|
||||
EvaluateTask(extracted.structure, taskKey, state, extracted.currentRef, config)
|
||||
}
|
||||
def runTask[T](taskKey: ScopedKey[Task[T]], state: State, config: EvaluateTaskConfig): Option[(State, Result[T])] = {
|
||||
val extracted = Project.extract(state)
|
||||
EvaluateTask(extracted.structure, taskKey, state, extracted.currentRef, config)
|
||||
}
|
||||
|
||||
implicit def projectToRef(p: Project): ProjectReference = LocalProject(p.id)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
import sbt.ExposeYourself._
|
||||
|
||||
taskCancelHandler := { (state: State) =>
|
||||
new TaskEvaluationCancelHandler {
|
||||
override def start(canceller: TaskCancel): Unit = canceller.cancel()
|
||||
override def finish(): Unit = ()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package sbt // this API is private[sbt], so only exposed for trusted clients and folks who like breaking.
|
||||
|
||||
object ExposeYourself {
|
||||
val taskCancelHandler = sbt.Keys.taskCancelHandler
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import scala
|
||||
|
||||
object Foo {
|
||||
val x = "this should be long to compile or the test may fail."
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# All tasks should fail.
|
||||
-> compile
|
||||
-> test
|
||||
Loading…
Reference in New Issue