Improve supershell appender management

To avoid reliance on jvm global variables, we need to share the super
shell state with each of the console appenders that write to the console
out. We only set the progress state for the console appenders for the
screen. This prevents messages that are below the global logging level
from modifying the progress state without preventing them from being
written to other appenders.

The ability to set the ProgressState for each of the console appenders
is added in a companion util PR.

I verified that the test output of io/test was correctly written to the
streams after this change (there were no progress lines in the output).
This commit is contained in:
Ethan Atkins 2019-09-02 23:58:42 -07:00
parent 4f2ffe9b36
commit 7c31e03d27
6 changed files with 26 additions and 19 deletions

View File

@ -298,14 +298,13 @@ object Defaults extends BuildCommon {
turbo :== SysProp.turbo, turbo :== SysProp.turbo,
useSuperShell := { if (insideCI.value) false else SysProp.supershell }, useSuperShell := { if (insideCI.value) false else SysProp.supershell },
progressReports := { progressReports := {
val progress = (ThisBuild / useSuperShell).value val rs = EvaluateTask.taskTimingProgress.toVector ++ EvaluateTask.taskTraceEvent.toVector
val rs = EvaluateTask.taskTimingProgress.toVector ++
EvaluateTask.taskTraceEvent.toVector ++ {
if (progress) Vector(EvaluateTask.taskProgress)
else Vector()
}
rs map { Keys.TaskProgress(_) } rs map { Keys.TaskProgress(_) }
}, },
progressState := {
if ((ThisBuild / useSuperShell).value) Some(new ProgressState(SysProp.supershellBlankZone))
else None
},
Previous.cache := new Previous( Previous.cache := new Previous(
Def.streamsManagerKey.value, Def.streamsManagerKey.value,
Previous.references.value.getReferences Previous.references.value.getReferences

View File

@ -165,12 +165,6 @@ object EvaluateTask {
Some(sharedTraceEvent) Some(sharedTraceEvent)
} else None } else None
def taskProgress: ExecuteProgress[Task] = {
val appender = MainAppender.defaultScreen(StandardMain.console)
val log = LogManager.progressLogger(appender)
new TaskProgress(log)
}
// sbt-pgp calls this // sbt-pgp calls this
@deprecated("No longer used", "1.3.0") @deprecated("No longer used", "1.3.0")
private[sbt] def defaultProgress(): ExecuteProgress[Task] = ExecuteProgress.empty[Task] private[sbt] def defaultProgress(): ExecuteProgress[Task] = ExecuteProgress.empty[Task]
@ -236,12 +230,19 @@ object EvaluateTask {
extracted, extracted,
structure structure
) )
val reporters = maker.map(_.progress) ++ val progressReporter = extracted.get(progressState in ThisBuild).map { ps =>
ps.reset()
ConsoleAppender.setShowProgress(true)
val appender = MainAppender.defaultScreen(StandardMain.console)
appender match {
case c: ConsoleAppender => c.setProgressState(ps)
case _ =>
}
val log = LogManager.progressLogger(appender)
new TaskProgress(log)
}
val reporters = maker.map(_.progress) ++ progressReporter ++
(if (SysProp.taskTimings) new TaskTimings(reportOnShutdown = false) :: Nil else Nil) (if (SysProp.taskTimings) new TaskTimings(reportOnShutdown = false) :: Nil else Nil)
// configure the logger for super shell
ConsoleAppender.setShowProgress((reporters collect {
case p: TaskProgress => ()
}).nonEmpty)
reporters match { reporters match {
case xs if xs.isEmpty => ExecuteProgress.empty[Task] case xs if xs.isEmpty => ExecuteProgress.empty[Task]
case xs if xs.size == 1 => xs.head case xs if xs.size == 1 => xs.head

View File

@ -24,7 +24,7 @@ import sbt.internal.inc.ScalaInstance
import sbt.internal.io.WatchState import sbt.internal.io.WatchState
import sbt.internal.librarymanagement.{ CompatibilityWarningOptions, IvySbt } import sbt.internal.librarymanagement.{ CompatibilityWarningOptions, IvySbt }
import sbt.internal.server.ServerHandler import sbt.internal.server.ServerHandler
import sbt.internal.util.{ AttributeKey, SourcePosition } import sbt.internal.util.{ AttributeKey, ProgressState, SourcePosition }
import sbt.io._ import sbt.io._
import sbt.librarymanagement.Configurations.CompilerPlugin import sbt.librarymanagement.Configurations.CompilerPlugin
import sbt.librarymanagement.LibraryManagementCodec._ import sbt.librarymanagement.LibraryManagementCodec._
@ -484,6 +484,7 @@ object Keys {
val turbo = settingKey[Boolean]("Enables (true) or disables optional performance features.") val turbo = settingKey[Boolean]("Enables (true) or disables optional performance features.")
// This key can be used to add custom ExecuteProgress instances // This key can be used to add custom ExecuteProgress instances
val progressReports = settingKey[Seq[TaskProgress]]("A function that returns a list of progress reporters.").withRank(DTask) val progressReports = settingKey[Seq[TaskProgress]]("A function that returns a list of progress reporters.").withRank(DTask)
private[sbt] val progressState = settingKey[Option[ProgressState]]("The optional progress state if supershell is enabled.").withRank(Invisible)
private[sbt] val postProgressReports = settingKey[Unit]("Internally used to modify logger.").withRank(DTask) private[sbt] val postProgressReports = settingKey[Unit]("Internally used to modify logger.").withRank(DTask)
@deprecated("No longer used", "1.3.0") @deprecated("No longer used", "1.3.0")
private[sbt] val executeProgress = settingKey[State => TaskProgress]("Experimental task execution listener.").withRank(DTask) private[sbt] val executeProgress = settingKey[State => TaskProgress]("Experimental task execution listener.").withRank(DTask)

View File

@ -140,7 +140,12 @@ object LogManager {
val screenTrace = getOr(traceLevel.key, data, scope, state, defaultTraceLevel(state)) val screenTrace = getOr(traceLevel.key, data, scope, state, defaultTraceLevel(state))
val backingTrace = getOr(persistTraceLevel.key, data, scope, state, Int.MaxValue) val backingTrace = getOr(persistTraceLevel.key, data, scope, state, Int.MaxValue)
val extraBacked = state.globalLogging.backed :: relay :: Nil val extraBacked = state.globalLogging.backed :: relay :: Nil
val ps = Project.extract(state).get(sbt.Keys.progressState in ThisBuild)
val consoleOpt = consoleLocally(state, console) val consoleOpt = consoleLocally(state, console)
consoleOpt foreach {
case a: ConsoleAppender => ps.foreach(a.setProgressState)
case _ =>
}
val config = MainAppender.MainAppenderConfig( val config = MainAppender.MainAppenderConfig(
consoleOpt, consoleOpt,
backed, backed,

View File

@ -91,6 +91,7 @@ object SysProp {
def supershell: Boolean = booleanOpt("sbt.supershell").getOrElse(color) def supershell: Boolean = booleanOpt("sbt.supershell").getOrElse(color)
def supershellSleep: Long = long("sbt.supershell.sleep", 100L) def supershellSleep: Long = long("sbt.supershell.sleep", 100L)
def supershellBlankZone: Int = int("sbt.supershell.blankzone", 5)
def defaultUseCoursier: Boolean = { def defaultUseCoursier: Boolean = {
val coursierOpt = booleanOpt("sbt.coursier") val coursierOpt = booleanOpt("sbt.coursier")

View File

@ -11,7 +11,7 @@ object Dependencies {
// sbt modules // sbt modules
private val ioVersion = nightlyVersion.getOrElse("1.3.0-M17") private val ioVersion = nightlyVersion.getOrElse("1.3.0-M17")
private val utilVersion = nightlyVersion.getOrElse("1.3.0-M12") private val utilVersion = nightlyVersion.getOrElse("1.3.0")
private val lmVersion = private val lmVersion =
sys.props.get("sbt.build.lm.version") match { sys.props.get("sbt.build.lm.version") match {
case Some(version) => version case Some(version) => version