Merge pull request #6883 from eed3si9n/bport/6870

[1.7.x] Backport 6870, 6880, and 6882
This commit is contained in:
eugene yokota 2022-04-17 19:35:54 -04:00 committed by GitHub
commit 1ec23fa616
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 86 additions and 37 deletions

View File

@ -46,7 +46,7 @@ ThisBuild / resolvers += Resolver.mavenLocal
Global / semanticdbEnabled := !(Global / insideCI).value
// Change main/src/main/scala/sbt/plugins/SemanticdbPlugin.scala too, if you change this.
Global / semanticdbVersion := "4.4.28"
Global / semanticdbVersion := "4.5.4"
val excludeLint = SettingKey[Set[Def.KeyedInitialize[_]]]("excludeLintKeys")
Global / excludeLint := (Global / excludeLint).?.value.getOrElse(Set.empty)
Global / excludeLint += componentID

View File

@ -67,7 +67,7 @@ trait ConsoleInterface {
}
/**
* A NetworkClient connects to a running an sbt instance or starts a
* A NetworkClient connects to a running sbt instance or starts a
* new instance if there isn't already one running. Once connected,
* it can send commands for sbt to run, it can send completions to sbt
* and print the completions to stdout so that a shell can consume
@ -78,15 +78,15 @@ trait ConsoleInterface {
* needs to start it. It also contains the sbt command
* arguments to send to the server if any are present.
* @param console a logging instance. This can use a ConsoleAppender or
* just simply print to a PrintSream.
* just simply print to a PrintStream.
* @param inputStream the InputStream from which the client reads bytes. It
* is not hardcoded to System.in so that a NetworkClient
* can be remotely controlled by a java process, which
* is useful in test.
* is useful in testing.
* @param errorStream the sink for messages that we always want to be printed.
* It is usually System.err but could be overridden in tests
* or set to a null OutputStream if the NetworkClient needs
* to be silent
* to be silent.
* @param printStream the sink for standard out messages. It is typically
* System.out but in the case of completions, the bytes written
* to System.out are usually treated as completion results
@ -139,7 +139,7 @@ class NetworkClient(
private val rebooting = new AtomicBoolean(false)
private lazy val noTab = arguments.completionArguments.contains("--no-tab")
private lazy val noStdErr = arguments.completionArguments.contains("--no-stderr") &&
!sys.env.contains("SBTC_AUTO_COMPLETE")
!sys.env.contains("SBTN_AUTO_COMPLETE") && !sys.env.contains("SBTC_AUTO_COMPLETE")
private def mkSocket(file: File): (Socket, Option[String]) = ClientSocket.socket(file, useJNI)

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

@ -26,7 +26,7 @@ object SemanticdbPlugin extends AutoPlugin {
semanticdbEnabled := SysProp.semanticdb,
semanticdbIncludeInJar := false,
semanticdbOptions := List(),
semanticdbVersion := "4.4.28"
semanticdbVersion := "4.5.4"
)
override lazy val projectSettings: Seq[Def.Setting[_]] = Seq(

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