diff --git a/main/src/main/scala/sbt/LogManager.scala b/main/src/main/scala/sbt/LogManager.scala index bb3a2765b..59e69bbdc 100644 --- a/main/src/main/scala/sbt/LogManager.scala +++ b/main/src/main/scala/sbt/LogManager.scala @@ -105,8 +105,8 @@ object LogManager { // 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] val ref = new java.lang.ref.WeakReference(s.globalLogging.full) private[this] def slog: Logger = Option(ref.get) getOrElse sys.error("Settings logger used after project was loaded.") override val ansiCodesSupported = slog.ansiCodesSupported diff --git a/main/src/main/scala/sbt/Main.scala b/main/src/main/scala/sbt/Main.scala index d7d364472..f2fe6ff6b 100644 --- a/main/src/main/scala/sbt/Main.scala +++ b/main/src/main/scala/sbt/Main.scala @@ -227,7 +227,10 @@ object BuiltinCommands { def reapply(newSession: SessionSettings, structure: BuildStructure, s: State): State = { s.log.info("Reapplying settings...") - val newStructure = Load.reapply(newSession.mergeSettings, structure)(Project.showContextKey(newSession, structure)) + // Here, for correct behavior, we also need to re-inject a settings logger, as we'll be re-evaluating settings. + val loggerInject = LogManager.settingsLogger(s) + val withLogger = newSession.appendRaw(loggerInject :: Nil) + val newStructure = Load.reapply(withLogger.mergeSettings, structure)(Project.showContextKey(newSession, structure)) Project.setProject(newSession, newStructure, s) } def set = Command(SetCommand, setBrief, setDetailed)(setParser) { diff --git a/sbt/src/sbt-test/actions/reload/log-in-setting.sbt b/sbt/src/sbt-test/actions/reload/log-in-setting.sbt new file mode 100644 index 000000000..671118f0b --- /dev/null +++ b/sbt/src/sbt-test/actions/reload/log-in-setting.sbt @@ -0,0 +1,15 @@ + +version := { + sLog.value.info("Version is initializing") + version.value +} + +TaskKey[Unit]("evil-clear-logger") := { + val logger = sLog.value + val cls = logger.getClass + val field = cls.getDeclaredField("ref") + field.setAccessible(true) + val ref = field.get(logger).asInstanceOf[java.lang.ref.WeakReference[_]] + // MUHAHAHHAHAHAHAHHAHA, I am de evil GC, I clear things. + ref.clear() +} \ No newline at end of file diff --git a/sbt/src/sbt-test/actions/reload/test b/sbt/src/sbt-test/actions/reload/test index 69e42a70f..0e8bb10b2 100755 --- a/sbt/src/sbt-test/actions/reload/test +++ b/sbt/src/sbt-test/actions/reload/test @@ -1,3 +1,6 @@ +# Note: We aren't actively running this test, but it checks to make sure the setting-level logger is ok across reloads. +# > evil-clear-logger +# > reload -> f > project sub > f @@ -10,4 +13,4 @@ $ copy-file changes/Changed.scala project/TestProject.scala > g # The current URI should be kept > reload -> g \ No newline at end of file +> g diff --git a/sbt/src/sbt-test/actions/set/build.sbt b/sbt/src/sbt-test/actions/set/build.sbt index 641163ffb..1d4e17374 100644 --- a/sbt/src/sbt-test/actions/set/build.sbt +++ b/sbt/src/sbt-test/actions/set/build.sbt @@ -9,6 +9,16 @@ TaskKey[Unit]("checkBuildSbtDefined", "") := { assert(notExistingThing.?.value == Some(5), "Failed to set a settingKey defined in build.sbt") } +TaskKey[Unit]("evil-clear-logger") := { + val logger = sLog.value + val cls = logger.getClass + val field = cls.getDeclaredField("ref") + field.setAccessible(true) + val ref = field.get(logger).asInstanceOf[java.lang.ref.WeakReference[_]] + // MUHAHAHHAHAHAHAHHAHA, I am de evil GC, I clear things. + ref.clear() +} + commands ++= Seq( Command.command("helloWorldTest") { state: State => """set name := "hello-world"""" :: diff --git a/sbt/src/sbt-test/actions/set/test b/sbt/src/sbt-test/actions/set/test index 8867956d9..7426c5704 100644 --- a/sbt/src/sbt-test/actions/set/test +++ b/sbt/src/sbt-test/actions/set/test @@ -1,2 +1,4 @@ > helloWorldTest -> buildSbtTest \ No newline at end of file +> buildSbtTest +> evil-clear-logger +> set version := { sLog.value.info("yo"); version.value } \ No newline at end of file