Merge pull request #6870 from eatkins/watch-on-termination

Restore watchOnTermination callbacks
This commit is contained in:
eugene yokota 2022-04-11 13:43:23 -04:00 committed by GitHub
commit c00a2eacf2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 79 additions and 30 deletions

View File

@ -1128,7 +1128,28 @@ private[sbt] object Continuous extends DeprecatedContinuous {
val callbacks: Callbacks,
val dynamicInputs: mutable.Set[DynamicInput],
val pending: Boolean,
var failAction: Option[Watch.Action],
) {
def this(
count: Int,
commands: Seq[String],
beforeCommandImpl: (State, mutable.Set[DynamicInput]) => State,
afterCommand: State => State,
afterWatch: State => State,
callbacks: Callbacks,
dynamicInputs: mutable.Set[DynamicInput],
pending: Boolean,
) = this(
count,
commands,
beforeCommandImpl,
afterCommand,
afterWatch,
callbacks,
dynamicInputs,
pending,
None
)
def beforeCommand(state: State): State = beforeCommandImpl(state, dynamicInputs)
def incremented: ContinuousState = withCount(count + 1)
def withPending(p: Boolean) =
@ -1323,7 +1344,8 @@ private[sbt] object ContinuousCommands {
case Watch.Prompt => stop.map(_ :: s"$PromptChannel ${channel.name}" :: Nil mkString ";")
case Watch.Run(commands) =>
stop.map(_ +: commands.map(_.commandLine).filter(_.nonEmpty) mkString "; ")
case Watch.HandleError(_) =>
case a @ Watch.HandleError(_) =>
cs.failAction = Some(a)
stop.map(_ :: s"$failWatch ${channel.name}" :: Nil mkString "; ")
case _ => stop
}
@ -1353,27 +1375,31 @@ private[sbt] object ContinuousCommands {
}
cs.afterCommand(postState)
}
private[sbt] val stopWatchCommand = watchCommand(stopWatch) { (channel, state) =>
state.get(watchStates).flatMap(_.get(channel)) match {
case Some(cs) =>
val afterWatchState = cs.afterWatch(state)
cs.callbacks.onExit()
StandardMain.exchange
.channelForName(channel)
.foreach { c =>
c.terminal.setPrompt(Prompt.Pending)
c.unprompt(ConsoleUnpromptEvent(Some(CommandSource(channel))))
private[this] val exitWatchShared = (error: Boolean) =>
(channel: String, state: State) =>
state.get(watchStates).flatMap(_.get(channel)) match {
case Some(cs) =>
val afterWatchState = cs.afterWatch(state)
cs.callbacks.onExit()
StandardMain.exchange
.channelForName(channel)
.foreach { c =>
c.terminal.setPrompt(Prompt.Pending)
c.unprompt(ConsoleUnpromptEvent(Some(CommandSource(channel))))
}
val newState = afterWatchState.get(watchStates) match {
case None => afterWatchState
case Some(w) => afterWatchState.put(watchStates, w - channel)
}
afterWatchState.get(watchStates) match {
case None => afterWatchState
case Some(w) => afterWatchState.put(watchStates, w - channel)
}
case _ => state
}
}
private[sbt] val failWatchCommand = watchCommand(failWatch) { (channel, state) =>
state.fail
}
val commands = cs.commands.mkString("; ")
val count = cs.count
val action = cs.failAction.getOrElse(Watch.CancelWatch)
val st = cs.callbacks.onTermination(action, commands, count, newState)
if (error) st.fail else st
case _ => if (error) state.fail else state
}
private[sbt] val stopWatchCommand = watchCommand(stopWatch)(exitWatchShared(false))
private[sbt] val failWatchCommand = watchCommand(failWatch)(exitWatchShared(true))
/*
* Creates a FileTreeRepository where it is safe to call close without inadvertently cancelling
* still active watches.

View File

@ -0,0 +1,3 @@
import sbt.watch.task.Build
val root = Build.root

View File

@ -0,0 +1,7 @@
# This tests that we can override the state transformation in the watch task
# In the build, watchOnEvent should return CancelWatch which should be successful, but we
# override watchTasks to fail the state instead
-> ~ root / setStringValue foo.txt bar
> checkStringValue foo.txt bar

View File

@ -1,3 +1,15 @@
import sbt.watch.task.Build
val root = Build.root
watchOnIteration := { (count, project, commands) =>
Watch.CancelWatch
}
watchOnTermination := { (action, count, command, state) =>
action match {
case Watch.CancelWatch =>
java.nio.file.Files.delete(java.nio.file.Paths.get("foo.txt"))
case Watch.HandleError(e) =>
if (e.getMessage == "fail")
java.nio.file.Files.delete(java.nio.file.Paths.get("bar.txt"))
else
throw new IllegalStateException("unexpected error")
}
state
}

View File

@ -1,7 +1,8 @@
# This tests that we can override the state transformation in the watch task
# In the build, watchOnEvent should return CancelWatch which should be successful, but we
# override watchTasks to fail the state instead
$ exists foo.txt
> ~compile
$ absent foo.txt
> set watchOnIteration := { (_, _, _) => new Watch.HandleError(new IllegalStateException("fail")) }
$ exists bar.txt
-> ~compile
$ absent bar.txt
-> ~ root / setStringValue foo.txt bar
> checkStringValue foo.txt bar