diff --git a/main/src/main/scala/sbt/Main.scala b/main/src/main/scala/sbt/Main.scala index 75f67893a..eee3ef79b 100644 --- a/main/src/main/scala/sbt/Main.scala +++ b/main/src/main/scala/sbt/Main.scala @@ -13,12 +13,12 @@ import scala.annotation.tailrec import Path._ import StandardMain._ -import java.io.File +import java.io.{ File, IOException } import java.net.URI import java.util.Locale import scala.util.control.NonFatal -/** This class is the entry point for sbt.*/ +/** This class is the entry point for sbt. */ final class xMain extends xsbti.AppMain { def run(configuration: xsbti.AppConfiguration): xsbti.MainResult = { @@ -26,12 +26,44 @@ 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()) runManaged(initialState(configuration, Seq(defaults, early), runEarly(DefaultsCommand) :: runEarly(InitCommand) :: BootCommand :: Nil) ) } + + 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) + } + } + } } + final class ScriptMain extends xsbti.AppMain { def run(configuration: xsbti.AppConfiguration): xsbti.MainResult = { diff --git a/notes/0.13.14.markdown b/notes/0.13.14.markdown index 2d5df5bed..10210419c 100644 --- a/notes/0.13.14.markdown +++ b/notes/0.13.14.markdown @@ -8,6 +8,7 @@ - Adds "local-preloaded" repository for offline installation. See below. - Notifies and enables users to stay in sbt's shell on the warm JVM by hitting `[ENTER]` while sbt is running. [#2987][2987]/[#2996][2996] by [@dwijnand][@dwijnand] - Adds an `Append` instance to support `sourceGenerators += Def.task { ... }`, instead of needing `.taskValue`. [#2943][2943] by [@eed3si9n][@eed3si9n] +- Writes out the sbt.version in project/build.properties if it is missing. [#754][]/[#3025][] by [@dwijnand][] - XML generated by JUnitXmlTestsListener now correctly flags ignored, skipped and pending tests. [#2198][2198]/[#2854][2854] by [@ashleymercer][@ashleymercer] - When sbt detects that the project is compiled with dotty, it now automatically sets `scalaCompilerBridgeSource` correctly, this reduces the boilerplate needed @@ -63,6 +64,7 @@ Special thanks to the contributors for making this release a success. According [143]: https://github.com/sbt/sbt-launcher-package/pull/143 [145]: https://github.com/sbt/sbt-launcher-package/pull/145 + [754]: https://github.com/sbt/sbt/issues/754 [2766]: https://github.com/sbt/sbt/issues/2766 [1855]: https://github.com/sbt/sbt/issues/1855 [1466]: https://github.com/sbt/sbt/issues/1466 @@ -86,6 +88,7 @@ Special thanks to the contributors for making this release a success. According [2993]: https://github.com/sbt/sbt/pull/2993 [2943]: https://github.com/sbt/sbt/pull/2943 [3011]: https://github.com/sbt/sbt/issues/3011 + [3025]: https://github.com/sbt/sbt/issues/3025 [@eed3si9n]: https://github.com/eed3si9n [@dwijnand]: https://github.com/dwijnand [@Duhemm]: https://github.com/Duhemm