mirror of https://github.com/sbt/sbt.git
Don't use exception for reloading
I completely forgot about the StateTransform class which allows a task to modify the state through its return value.
This commit is contained in:
parent
e3e2f29bdd
commit
f5c8b8aad5
|
|
@ -21,8 +21,6 @@ final case class Reboot(
|
||||||
def arguments = argsList.toArray
|
def arguments = argsList.toArray
|
||||||
}
|
}
|
||||||
|
|
||||||
private[sbt] case object Reload extends Exception(null, null, false, false)
|
|
||||||
|
|
||||||
final case class ApplicationID(
|
final case class ApplicationID(
|
||||||
groupID: String,
|
groupID: String,
|
||||||
name: String,
|
name: String,
|
||||||
|
|
|
||||||
|
|
@ -346,7 +346,7 @@ object EvaluateTask {
|
||||||
ExceptionCategory(ex) match {
|
ExceptionCategory(ex) match {
|
||||||
case AlreadyHandled => ()
|
case AlreadyHandled => ()
|
||||||
case m: MessageOnly => if (msg.isEmpty) log.error(m.message)
|
case m: MessageOnly => if (msg.isEmpty) log.error(m.message)
|
||||||
case f: Full => if (f.exception != Reload) log.trace(f.exception)
|
case f: Full => log.trace(f.exception)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -354,7 +354,7 @@ object EvaluateTask {
|
||||||
val msgString = (msg.toList ++ ex.toList.map(ErrorHandling.reducedToString)).mkString("\n\t")
|
val msgString = (msg.toList ++ ex.toList.map(ErrorHandling.reducedToString)).mkString("\n\t")
|
||||||
val log = getStreams(key, streams).log
|
val log = getStreams(key, streams).log
|
||||||
val display = contextDisplay(state, ConsoleAppender.formatEnabledInEnv)
|
val display = contextDisplay(state, ConsoleAppender.formatEnabledInEnv)
|
||||||
if (!ex.contains(Reload)) log.error("(" + display.show(key) + ") " + msgString)
|
log.error("(" + display.show(key) + ") " + msgString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -144,10 +144,7 @@ object MainLoop {
|
||||||
case Right(s) => s
|
case Right(s) => s
|
||||||
case Left(t: xsbti.FullReload) => throw t
|
case Left(t: xsbti.FullReload) => throw t
|
||||||
case Left(t: RebootCurrent) => throw t
|
case Left(t: RebootCurrent) => throw t
|
||||||
case Left(Reload) =>
|
case Left(t) => state.handleError(t)
|
||||||
val remaining = state.currentCommand.toList ::: state.remainingCommands
|
|
||||||
state.copy(remainingCommands = Exec("reload", None, None) :: remaining)
|
|
||||||
case Left(t) => state.handleError(t)
|
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
case oom: OutOfMemoryError if oom.getMessage.contains("Metaspace") =>
|
case oom: OutOfMemoryError if oom.getMessage.contains("Metaspace") =>
|
||||||
|
|
|
||||||
|
|
@ -9,17 +9,14 @@ package sbt
|
||||||
package internal
|
package internal
|
||||||
|
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
import java.util.{ Collections, IdentityHashMap }
|
|
||||||
|
|
||||||
import Def.ScopedKey
|
import sbt.Def.ScopedKey
|
||||||
import Keys.{ showSuccess, showTiming, timingFormat }
|
import sbt.Keys.{ showSuccess, showTiming, timingFormat }
|
||||||
import sbt.internal.util.complete.Parser
|
import sbt.internal.util.complete.Parser
|
||||||
import sbt.internal.util.{ AttributeKey, Dag, HList, Settings, Util }
|
import sbt.internal.util.complete.Parser.{ failure, seq, success }
|
||||||
|
import sbt.internal.util._
|
||||||
|
import sbt.std.Transform.DummyTaskMap
|
||||||
import sbt.util.{ Logger, Show }
|
import sbt.util.{ Logger, Show }
|
||||||
import Parser.{ failure, seq, success }
|
|
||||||
import std.Transform.DummyTaskMap
|
|
||||||
|
|
||||||
import scala.annotation.tailrec
|
|
||||||
|
|
||||||
sealed trait Aggregation
|
sealed trait Aggregation
|
||||||
object Aggregation {
|
object Aggregation {
|
||||||
|
|
@ -115,25 +112,7 @@ object Aggregation {
|
||||||
)(implicit display: Show[ScopedKey[_]]): State = {
|
)(implicit display: Show[ScopedKey[_]]): State = {
|
||||||
val complete = timedRun[T](s, ts, extra)
|
val complete = timedRun[T](s, ts, extra)
|
||||||
showRun(complete, show)
|
showRun(complete, show)
|
||||||
/*
|
|
||||||
* In the first implementation, we tried to use Set[Incomplete] for visited. It had very poor
|
|
||||||
* performance because hashCode can be expensive on Incomplete -- especially when the
|
|
||||||
* Incomplete has many instances in the causes field.
|
|
||||||
*/
|
|
||||||
lazy val visited = Collections
|
|
||||||
.newSetFromMap[Incomplete](new IdentityHashMap[Incomplete, java.lang.Boolean])
|
|
||||||
@tailrec def findReload(incomplete: Incomplete, remaining: List[Incomplete]): Boolean = {
|
|
||||||
visited.add(incomplete)
|
|
||||||
incomplete.directCause.contains(Reload) || ((remaining ::: incomplete.causes.toList)
|
|
||||||
.filterNot(visited.contains) match {
|
|
||||||
case Nil => false
|
|
||||||
case h :: tail => findReload(h, tail.filterNot(visited.contains))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
complete.results match {
|
complete.results match {
|
||||||
case Inc(i) if findReload(i, i.causes.toList) =>
|
|
||||||
val remaining = s.currentCommand.toList ::: s.remainingCommands
|
|
||||||
complete.state.copy(remainingCommands = Exec("reload", None, None) :: remaining)
|
|
||||||
case Inc(i) => complete.state.handleError(i)
|
case Inc(i) => complete.state.handleError(i)
|
||||||
case Value(_) => complete.state
|
case Value(_) => complete.state
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,12 @@ import sbt.nio.Keys._
|
||||||
import sbt.nio.file.{ ChangedFiles, Glob, RecursiveGlob }
|
import sbt.nio.file.{ ChangedFiles, Glob, RecursiveGlob }
|
||||||
|
|
||||||
private[sbt] object CheckBuildSources {
|
private[sbt] object CheckBuildSources {
|
||||||
private[sbt] def needReloadImpl: Def.Initialize[Task[Unit]] = Def.task {
|
private[sbt] def needReloadImpl: Def.Initialize[Task[StateTransform]] = Def.task {
|
||||||
val logger = streams.value.log
|
val logger = streams.value.log
|
||||||
val checkMetaBuildParam = state.value.get(hasCheckedMetaBuild)
|
val st: State = state.value
|
||||||
val firstTime = checkMetaBuildParam.fold(true)(_.get == false)
|
val firstTime = st.get(hasCheckedMetaBuild).fold(true)(_.compareAndSet(false, true))
|
||||||
(onChangedBuildSource in Scope.Global).value match {
|
(onChangedBuildSource in Scope.Global).value match {
|
||||||
case IgnoreSourceChanges => ()
|
case IgnoreSourceChanges => new StateTransform(st)
|
||||||
case o =>
|
case o =>
|
||||||
logger.debug("Checking for meta build source updates")
|
logger.debug("Checking for meta build source updates")
|
||||||
(changedInputFiles in checkBuildSources).value match {
|
(changedInputFiles in checkBuildSources).value match {
|
||||||
|
|
@ -37,18 +37,20 @@ private[sbt] object CheckBuildSources {
|
||||||
val prefix = rawPrefix.linesIterator.filterNot(_.trim.isEmpty).mkString("\n")
|
val prefix = rawPrefix.linesIterator.filterNot(_.trim.isEmpty).mkString("\n")
|
||||||
if (o == ReloadOnSourceChanges) {
|
if (o == ReloadOnSourceChanges) {
|
||||||
logger.info(s"$prefix\nReloading sbt...")
|
logger.info(s"$prefix\nReloading sbt...")
|
||||||
throw Reload
|
val remaining =
|
||||||
|
Exec("reload", None, None) :: st.currentCommand.toList ::: st.remainingCommands
|
||||||
|
new StateTransform(st.copy(currentCommand = None, remainingCommands = remaining))
|
||||||
} else {
|
} else {
|
||||||
val tail = "Apply these changes by running `reload`.\nAutomatically reload the " +
|
val tail = "Apply these changes by running `reload`.\nAutomatically reload the " +
|
||||||
"build when source changes are detected by setting " +
|
"build when source changes are detected by setting " +
|
||||||
"`Global / onChangedBuildSource := ReloadOnSourceChanges`.\nDisable this " +
|
"`Global / onChangedBuildSource := ReloadOnSourceChanges`.\nDisable this " +
|
||||||
"warning by setting `Global / onChangedBuildSource := IgnoreSourceChanges`."
|
"warning by setting `Global / onChangedBuildSource := IgnoreSourceChanges`."
|
||||||
logger.warn(s"$prefix\n$tail")
|
logger.warn(s"$prefix\n$tail")
|
||||||
|
new StateTransform(st)
|
||||||
}
|
}
|
||||||
case _ => ()
|
case _ => new StateTransform(st)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
checkMetaBuildParam.foreach(_.set(true))
|
|
||||||
}
|
}
|
||||||
private[sbt] def buildSourceFileInputs: Def.Initialize[Seq[Glob]] = Def.setting {
|
private[sbt] def buildSourceFileInputs: Def.Initialize[Seq[Glob]] = Def.setting {
|
||||||
if (onChangedBuildSource.value != IgnoreSourceChanges) {
|
if (onChangedBuildSource.value != IgnoreSourceChanges) {
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ object Keys {
|
||||||
taskKey[FileTreeView.Nio[FileAttributes]]("A view of the local file system tree")
|
taskKey[FileTreeView.Nio[FileAttributes]]("A view of the local file system tree")
|
||||||
|
|
||||||
val checkBuildSources =
|
val checkBuildSources =
|
||||||
taskKey[Unit]("Check if any meta build sources have changed").withRank(DSetting)
|
taskKey[StateTransform]("Check if any meta build sources have changed").withRank(DSetting)
|
||||||
|
|
||||||
// watch related settings
|
// watch related settings
|
||||||
val watchAntiEntropyRetentionPeriod = settingKey[FiniteDuration](
|
val watchAntiEntropyRetentionPeriod = settingKey[FiniteDuration](
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue