From c748a5583ed0dbdc8f18508ad35379bfa671c216 Mon Sep 17 00:00:00 2001 From: Ethan Atkins Date: Fri, 31 May 2019 09:27:15 -0700 Subject: [PATCH] Restore some legacy watch behavior for play I noticed that ~run in the Play plugin relied on the presence of the ContinuousEventMonitor key. Rather than completely break that feature, I re-added the ContinuousEventMonitor attribute to the state in a continuous build. That being said, the play team does need to update their plugin because reading from the console no longer works in 1.3.0 so the user has to Ctrl-C to exit the watch. I think the best way for them to fix this is to override the '~' command in their plugin and if the input is 'run', then they do their custom thing, otherwise they delegate to the default '~' command. --- .../main/scala/sbt/internal/Continuous.scala | 9 +++-- .../sbt/internal/DeprecatedContinuous.scala | 38 ++++++++++++++++++- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/main/src/main/scala/sbt/internal/Continuous.scala b/main/src/main/scala/sbt/internal/Continuous.scala index 41c59ba1e..5c3d17e19 100644 --- a/main/src/main/scala/sbt/internal/Continuous.scala +++ b/main/src/main/scala/sbt/internal/Continuous.scala @@ -329,9 +329,11 @@ private[sbt] object Continuous extends DeprecatedContinuous { try { val stateWithRepo = state.put(globalFileTreeRepository, repo) val fullState = - if (extracted.get(watchPersistFileStamps)) - stateWithRepo.put(persistentFileStampCache, fileStampCache) - else stateWithRepo + addLegacyWatchSetting( + if (extracted.get(watchPersistFileStamps)) + stateWithRepo.put(persistentFileStampCache, fileStampCache) + else stateWithRepo + ) setup(fullState, command) { (commands, s, valid, invalid) => EvaluateTask.withStreams(extracted.structure, s)(_.use(streams in Global) { streams => implicit val logger: Logger = streams.log @@ -344,6 +346,7 @@ private[sbt] object Continuous extends DeprecatedContinuous { currentCount.getAndIncrement() // abort as soon as one of the tasks fails valid.takeWhile(_._3.apply()) + updateLegacyWatchState(s, configs.flatMap(_.inputs().map(_.glob)), currentCount.get()) () } callbacks.onEnter() diff --git a/main/src/main/scala/sbt/internal/DeprecatedContinuous.scala b/main/src/main/scala/sbt/internal/DeprecatedContinuous.scala index b3c0379d0..1db908859 100644 --- a/main/src/main/scala/sbt/internal/DeprecatedContinuous.scala +++ b/main/src/main/scala/sbt/internal/DeprecatedContinuous.scala @@ -8,8 +8,12 @@ package sbt.internal import java.nio.file.Path +import java.util.concurrent.atomic.AtomicReference -import sbt.internal.io.{ WatchState => WS } +import sbt.{ State, Watched } +import sbt.internal.io.{ EventMonitor, Source, WatchState => WS } +import sbt.internal.util.AttributeKey +import sbt.nio.file.Glob private[internal] trait DeprecatedContinuous { protected type StartMessage = @@ -18,6 +22,38 @@ private[internal] trait DeprecatedContinuous { protected type DeprecatedWatchState = WS protected val deprecatedWatchingMessage = sbt.Keys.watchingMessage protected val deprecatedTriggeredMessage = sbt.Keys.triggeredMessage + protected def watchState(globs: Seq[Glob], count: Int): WS = { + WS.empty(globs).withCount(count) + } + private[this] val legacyWatchState = + AttributeKey[AtomicReference[WS]]("legacy-watch-state", Int.MaxValue) + protected def addLegacyWatchSetting(state: State): State = { + val legacyState = new AtomicReference[WS](WS.empty(Nil).withCount(1)) + state + .put( + Watched.ContinuousEventMonitor, + new EventMonitor { + + /** Block indefinitely until the monitor receives a file event or the user stops the watch. */ + override def awaitEvent(): Boolean = false + + /** A snapshot of the WatchState that includes the number of build triggers and watch sources. */ + override def state(): WS = legacyState.get() + override def close(): Unit = () + } + ) + .put(legacyWatchState, legacyState) + .put(Watched.Configuration, new Watched { + override def watchSources(s: State): Seq[Source] = + s.get(legacyWatchState).map(_.get.sources).getOrElse(Nil) + }) + } + def updateLegacyWatchState(state: State, globs: Seq[Glob], count: Int): Unit = { + state.get(legacyWatchState).foreach { ref => + val ws = WS.empty(globs).withCount(count) + ref.set(ws) + } + } } private[sbt] object DeprecatedContinuous { private[sbt] val taskDefinitions = Seq(