From 155f7649433a81b8b484af4ed75245c75edb2325 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 16 Mar 2017 18:44:22 +0000 Subject: [PATCH 1/3] Write sbt.version to project/build.properties Have sbt.version set in project/build.properties is a best practice because it makes the build more deterministic and reproducible. With this change sbt, after ensuring that the base directory is probably an sbt project, writes out sbt.version in project/build.properties if it is missing. Fixes #754 --- main/src/main/scala/sbt/Main.scala | 34 ++++++++++++++++++++++++++++-- notes/0.13.14.markdown | 3 +++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/main/src/main/scala/sbt/Main.scala b/main/src/main/scala/sbt/Main.scala index 75f67893a..19d093af3 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,42 @@ final class xMain extends xsbti.AppMain { import BasicCommandStrings.runEarly import BuiltinCommands.{ initialize, defaults } import CommandStrings.{ BootCommand, DefaultsCommand, InitCommand } + 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 newBuildPropsLines = s"sbt.version=$sbtVersion" :: buildPropsLines + IO.writeLines(buildProps, newBuildPropsLines) + } 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 From 465a9be63548dcd7d5d36296413485b38436dc29 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 16 Mar 2017 19:42:17 +0000 Subject: [PATCH 2/3] Add -Dsbt.skip.version.write=true opt-out --- main/src/main/scala/sbt/Main.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main/src/main/scala/sbt/Main.scala b/main/src/main/scala/sbt/Main.scala index 19d093af3..d679610f0 100644 --- a/main/src/main/scala/sbt/Main.scala +++ b/main/src/main/scala/sbt/Main.scala @@ -26,7 +26,8 @@ final class xMain extends xsbti.AppMain { import BasicCommandStrings.runEarly import BuiltinCommands.{ initialize, defaults } import CommandStrings.{ BootCommand, DefaultsCommand, InitCommand } - setSbtVersion(configuration.baseDirectory(), configuration.provider().id().version()) + 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) From aaaf254375a3ef5185b55e8482f94511372b5ba8 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 16 Mar 2017 21:49:15 +0000 Subject: [PATCH 3/3] Tell the user we're setting sbt.version --- main/src/main/scala/sbt/Main.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/main/src/main/scala/sbt/Main.scala b/main/src/main/scala/sbt/Main.scala index d679610f0..eee3ef79b 100644 --- a/main/src/main/scala/sbt/Main.scala +++ b/main/src/main/scala/sbt/Main.scala @@ -52,8 +52,9 @@ final class xMain extends xsbti.AppMain { val errorMessage = s"WARN: No sbt.version set in project/build.properties, base directory: $baseDir" try { if (isSbtProject(baseDir, projectDir)) { - val newBuildPropsLines = s"sbt.version=$sbtVersion" :: buildPropsLines - IO.writeLines(buildProps, newBuildPropsLines) + 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 {