provide Logger via Keys.sLog for use by settings during project initialization. Ref #806.

This commit is contained in:
Mark Harrah 2013-10-24 16:34:16 -04:00
parent eeb1ce8884
commit 4e7f30c893
3 changed files with 22 additions and 2 deletions

View File

@ -34,6 +34,7 @@ object Keys
val extraLoggers = SettingKey[ScopedKey[_] => Seq[AbstractLogger]]("extra-loggers", "A function that provides additional loggers for a given setting.", DSetting)
val logManager = SettingKey[LogManager]("log-manager", "The log manager, which creates Loggers for different contexts.", DSetting)
val logBuffered = SettingKey[Boolean]("log-buffered", "True if logging should be buffered until work completes.", CSetting)
val sLog = SettingKey[Logger]("setting-logger", "Logger usable by settings during project loading.", CSetting)
// Project keys
val projectCommand = AttributeKey[Boolean]("project-command", "Marks Commands that were registered for the current Project.", Invisible)

View File

@ -59,6 +59,7 @@ object Load
}
def injectGlobal(state: State): Seq[Setting[_]] =
(appConfiguration in GlobalScope :== state.configuration) +:
LogManager.settingsLogger(state) +:
EvaluateTask.injectSettings
def defaultWithGlobal(state: State, base: File, rawConfig: sbt.LoadBuildConfiguration, globalBase: File, log: Logger): sbt.LoadBuildConfiguration =
{

View File

@ -11,7 +11,7 @@ package sbt
import Scope.GlobalScope
import MainLogging._
import BasicKeys.explicitGlobalLogLevels
import Keys.{logLevel, logManager, persistLogLevel, persistTraceLevel, state, traceLevel}
import Keys.{logLevel, logManager, persistLogLevel, persistTraceLevel, sLog, state, traceLevel}
import scala.Console.{BLUE,RESET}
object LogManager
@ -33,7 +33,7 @@ object LogManager
withLoggers((task,state) => defaultScreen(console, suppressedMessage(task, state)), extra = extra)
def withScreenLogger(mk: (ScopedKey[_], State) => AbstractLogger): LogManager = withLoggers(screen = mk)
def withLoggers(screen: (ScopedKey[_], State) => AbstractLogger = (sk, s) => defaultScreen(s.globalLogging.console),
backed: PrintWriter => AbstractLogger = defaultBacked(),
extra: ScopedKey[_] => Seq[AbstractLogger] = _ => Nil): LogManager = new LogManager {
@ -90,6 +90,24 @@ object LogManager
s.put(BasicKeys.explicitGlobalLogLevels, flag)
private[this] def hasExplicitGlobalLogLevels(s: State): Boolean =
State.getBoolean(s, BasicKeys.explicitGlobalLogLevels, default=false)
private[sbt] def settingsLogger(state: State): Def.Setting[_] =
// strict to avoid retaining a reference to `state`
sLog in GlobalScope :== globalWrapper(state)
// construct a Logger that delegates to the global logger, but only holds a weak reference
// this is an approximation to the ideal that would invalidate the delegate after loading completes
private[this] def globalWrapper(s: State): Logger = {
val ref = new java.lang.ref.WeakReference(s.globalLogging.full)
new Logger {
private[this] def slog: Logger = Option(ref.get) getOrElse sys.error("Settings logger used after project was loaded.")
override val ansiCodesSupported = slog.ansiCodesSupported
override def trace(t: => Throwable) = slog.trace(t)
override def success(message: => String) = slog.success(message)
override def log(level: Level.Value, message: => String) = slog.log(level, message)
}
}
}
trait LogManager