From fdd3f566941a278e8b8fb1644b2d8bca36071460 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 27 Apr 2017 13:05:58 +0100 Subject: [PATCH] Allow --error to suppress warning messages Specifically: * Make them both commands, so they run after early commands (--error). * Make notifyUsersAboutShell aware of "iflast shell" instead of "boot". * Make writeSbtShell use a logger and tweak the message Refs #3091 --- main/src/main/scala/sbt/Main.scala | 110 ++++++++++++++++------------- 1 file changed, 61 insertions(+), 49 deletions(-) diff --git a/main/src/main/scala/sbt/Main.scala b/main/src/main/scala/sbt/Main.scala index 5bd13fd6a..0ceb4db02 100644 --- a/main/src/main/scala/sbt/Main.scala +++ b/main/src/main/scala/sbt/Main.scala @@ -29,59 +29,11 @@ final class xMain extends xsbti.AppMain { import BasicCommandStrings.runEarly import BuiltinCommands.{ initialize, defaults } import CommandStrings.{ BootCommand, DefaultsCommand, InitCommand } - if (!java.lang.Boolean.getBoolean("sbt.skip.version.write")) - setSbtVersion(configuration.baseDirectory(), configuration.provider().id().version()) val state = initialState(configuration, Seq(defaults, early), runEarly(DefaultsCommand) :: runEarly(InitCommand) :: BootCommand :: Nil) - notifyUsersAboutShell(state) runManaged(state) } - - private val sbtVersionRegex = """sbt\.version\s*=.*""".r - private def isSbtVersionLine(s: String) = sbtVersionRegex.pattern matcher s matches () - - private def isSbtProject(baseDir: File, projectDir: File) = - projectDir.exists() || (baseDir * "*.sbt").get.nonEmpty - - private def setSbtVersion(baseDir: File, sbtVersion: String) = { - val projectDir = baseDir / "project" - val buildProps = projectDir / "build.properties" - - val buildPropsLines = if (buildProps.canRead) IO.readLines(buildProps) else Nil - - val sbtVersionAbsent = buildPropsLines forall (!isSbtVersionLine(_)) - - if (sbtVersionAbsent) { - val errorMessage = s"WARN: No sbt.version set in project/build.properties, base directory: $baseDir" - try { - if (isSbtProject(baseDir, projectDir)) { - val line = s"sbt.version=$sbtVersion" - IO.writeLines(buildProps, line :: buildPropsLines) - println(s"Updated file $buildProps setting sbt.version to: $sbtVersion") - } else - println(errorMessage) - } catch { - case _: IOException => println(errorMessage) - } - } - } - - private def isInteractive = System.console() != null - private def hasShell(state: State) = state.remainingCommands contains Shell - - /** - * The "boot" command adds "iflast shell" ("if last shell") - * which basically means it falls back to shell if there are no further commands - */ - private def endsWithBoot(state: State) = state.remainingCommands.lastOption exists (_ == BootCommand) - - private def notifyUsersAboutShell(state: State) = - if (isInteractive && !hasShell(state) && !endsWithBoot(state)) { - state.log warn "Executing in batch mode." - state.log warn " For better performance, hit [ENTER] to switch to interactive mode, or" - state.log warn " consider launching sbt without any commands, or explicitly passing 'shell'" - } } final class ScriptMain extends xsbti.AppMain { @@ -143,9 +95,11 @@ object BuiltinCommands { projects, project, reboot, read, history, set, sessionCommand, inspect, loadProjectImpl, loadFailed, Cross.crossBuild, Cross.switchVersion, PluginCross.pluginCross, PluginCross.pluginSwitch, setOnFailure, clearOnFailure, stashOnFailure, popOnFailure, setLogLevel, plugin, plugins, + writeSbtVersion, notifyUsersAboutShell, ifLast, multi, shell, continuous, eval, alias, append, last, lastGrep, export, boot, nop, call, exit, early, initialize, act) ++ compatCommands - def DefaultBootCommands: Seq[String] = LoadProject :: (IfLast + " " + Shell) :: Nil + def DefaultBootCommands: Seq[String] = + WriteSbtVersion :: NotifyUsersAboutShell :: LoadProject :: s"$IfLast $Shell" :: Nil def boot = Command.make(BootCommand)(bootParser) @@ -573,4 +527,62 @@ object BuiltinCommands { } s.put(Keys.stateCompilerCache, cache) } + + private val sbtVersionRegex = """sbt\.version\s*=.*""".r + private def isSbtVersionLine(s: String) = sbtVersionRegex.pattern matcher s matches () + + private def isSbtProject(baseDir: File, projectDir: File) = + projectDir.exists() || (baseDir * "*.sbt").get.nonEmpty + + private def writeSbtVersionUnconditionally(state: State) = { + val baseDir = state.baseDir + val sbtVersion = BuiltinCommands.sbtVersion(state) + val projectDir = baseDir / "project" + val buildProps = projectDir / "build.properties" + + val buildPropsLines = if (buildProps.canRead) IO.readLines(buildProps) else Nil + + val sbtVersionAbsent = buildPropsLines forall (!isSbtVersionLine(_)) + + if (sbtVersionAbsent) { + val warnMsg = s"No sbt.version set in project/build.properties, base directory: $baseDir" + try { + if (isSbtProject(baseDir, projectDir)) { + val line = s"sbt.version=$sbtVersion" + IO.writeLines(buildProps, line :: buildPropsLines) + state.log info s"Updated file $buildProps: set sbt.version to $sbtVersion" + } else + state.log warn warnMsg + } catch { + case _: IOException => state.log warn warnMsg + } + } + } + + private def writeSbtVersion(state: State) = + if (!java.lang.Boolean.getBoolean("sbt.skip.version.write")) + writeSbtVersionUnconditionally(state) + + private def WriteSbtVersion = "write-sbt-version" + + private def writeSbtVersion: Command = + Command.command(WriteSbtVersion) { state => writeSbtVersion(state); state } + + private def isInteractive = System.console() != null + + private def intendsToInvokeShell(state: State) = + (state.remainingCommands contains Shell) || + (state.remainingCommands.lastOption exists (_ == s"$IfLast $Shell")) + + private def notifyUsersAboutShell(state: State) = + if (isInteractive && !intendsToInvokeShell(state)) { + state.log warn "Executing in batch mode." + state.log warn " For better performance, hit [ENTER] to switch to interactive mode, or" + state.log warn " consider launching sbt without any commands, or explicitly passing 'shell'" + } + + private def NotifyUsersAboutShell = "notify-users-about-shell" + + private def notifyUsersAboutShell: Command = + Command.command(NotifyUsersAboutShell) { state => notifyUsersAboutShell(state); state } }