From 2bb78c133f32d66510ab3e5061332cd076632679 Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Mon, 12 Dec 2011 19:24:58 -0500 Subject: [PATCH] introduce {sbt,scala}BinaryVersion by default assumes binary compatibility for incremental version bumps for sbt 0.12+ and Scala 2.10+ --- main/Defaults.scala | 35 ++++++++++++++++++++++++++++------- main/Keys.scala | 2 ++ 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/main/Defaults.scala b/main/Defaults.scala index eae8be980..a04a679d2 100644 --- a/main/Defaults.scala +++ b/main/Defaults.scala @@ -53,8 +53,9 @@ object Defaults extends BuildCommon onComplete <<= taskTemporaryDirectory { dir => () => IO.delete(dir); IO.createDirectory(dir) }, concurrentRestrictions <<= concurrentRestrictions or defaultRestrictions, parallelExecution :== true, - sbtVersion in GlobalScope <<= appConfiguration { _.provider.id.version }, - sbtResolver in GlobalScope <<= sbtVersion { sbtV => if(sbtV endsWith "-SNAPSHOT") Classpaths.typesafeSnapshots else Classpaths.typesafeResolver }, + sbtVersion <<= appConfiguration { _.provider.id.version }, + sbtBinaryVersion <<= sbtVersion(v => binaryVersion(v, "0.12")), + sbtResolver <<= sbtVersion { sbtV => if(sbtV endsWith "-SNAPSHOT") Classpaths.typesafeSnapshots else Classpaths.typesafeResolver }, pollInterval :== 500, logBuffered :== false, connectInput :== false, @@ -186,8 +187,9 @@ object Defaults extends BuildCommon scalacOptions in GlobalScope :== Nil, scalaInstance <<= scalaInstanceSetting, scalaVersion in GlobalScope <<= appConfiguration( _.provider.scalaProvider.version), + scalaBinaryVersion <<= scalaVersion(v => binaryVersion(v, "2.10")), crossScalaVersions in GlobalScope <<= Seq(scalaVersion).join, - crossTarget <<= (target, scalaVersion, sbtVersion, sbtPlugin, crossPaths)(makeCrossTarget), + crossTarget <<= (target, scalaBinaryVersion, sbtBinaryVersion, sbtPlugin, crossPaths)(makeCrossTarget), cacheDirectory <<= crossTarget / "cache" ) def makeCrossTarget(t: File, sv: String, sbtv: String, plugin: Boolean, cross: Boolean): File = @@ -375,7 +377,7 @@ object Defaults extends BuildCommon def collectFiles(dirs: ScopedTaskable[Seq[File]], filter: ScopedTaskable[FileFilter], excludes: ScopedTaskable[FileFilter]): Initialize[Task[Seq[File]]] = (dirs, filter, excludes) map { (d,f,excl) => d.descendantsExcept(f,excl).get } - def artifactPathSetting(art: SettingKey[Artifact]) = (crossTarget, projectID, art, scalaVersion in artifactName, artifactName) { (t, module, a, sv, toString) => t / toString(sv, module, a) asFile } + def artifactPathSetting(art: SettingKey[Artifact]) = (crossTarget, projectID, art, scalaBinaryVersion in artifactName, artifactName) { (t, module, a, sv, toString) => t / toString(sv, module, a) asFile } def artifactSetting = ((artifact, artifactClassifier).identity zipWith configuration.?) { case ((a,classifier),cOpt) => val cPart = cOpt flatMap { c => if(c == Compile) None else Some(c.name) } val combined = cPart.toList ++ classifier.toList @@ -595,6 +597,25 @@ object Defaults extends BuildCommon (if(aggregate) p.aggregate else Nil) } + val PartialVersion = """(\d+)\.(\d+)(?:\..+)?""".r + def partialVersion(s: String): Option[(Int,Int)] = + s match { + case PartialVersion(major, minor) => Some(major.toInt, minor.toInt) + case _ => None + } + private[this] def isNewer(major: Int, minor: Int, minMajor: Int, minMinor: Int): Boolean = + major > minMajor || (major == minMajor && minor >= minMinor) + + def binaryVersion(full: String, cutoff: String): String = + { + def sub(major: Int, minor: Int) = major + "." + minor + (partialVersion(full), partialVersion(cutoff)) match { + case (Some((major, minor)), None) => sub(major, minor) + case (Some((major, minor)), Some((minMajor, minMinor))) if isNewer(major, minor, minMajor, minMinor) => sub(major, minor) + case _ => full + } + } + val CompletionsID = "completions" def noAggregation: Seq[Scoped] = Seq(run, console, consoleQuick, consoleProject) @@ -723,7 +744,7 @@ object Classpaths ivyLoggingLevel in GlobalScope :== UpdateLogging.DownloadOnly, ivyXML in GlobalScope :== NodeSeq.Empty, ivyValidate in GlobalScope :== false, - ivyScala <<= ivyScala or (scalaHome, scalaVersion, scalaVersion in update) { (sh,v,vu) => + ivyScala <<= ivyScala or (scalaHome, scalaVersion, scalaBinaryVersion in update) { (sh,v,vu) => Some(new IvyScala(v, Nil, filterImplicit = true, checkExplicit = true, overrideScalaVersion = sh.isEmpty, substituteCross = x => IvySbt.substituteCross(x, vu))) }, moduleConfigurations in GlobalScope :== Nil, @@ -780,7 +801,7 @@ object Classpaths IvySbt.substituteCross(base, app.provider.scalaProvider.version).copy(crossVersion = false) } ) - def pluginProjectID: Initialize[ModuleID] = (sbtVersion in update, scalaVersion, projectID, sbtPlugin) { (sbtV, scalaV, pid, isPlugin) => + def pluginProjectID: Initialize[ModuleID] = (sbtBinaryVersion in update, scalaBinaryVersion in update, projectID, sbtPlugin) { (sbtV, scalaV, pid, isPlugin) => if(isPlugin) sbtPluginExtra(pid, sbtV, scalaV) else pid } def ivySbt0: Initialize[Task[IvySbt]] = @@ -1107,7 +1128,7 @@ trait BuildExtra extends BuildCommon import Defaults._ def addSbtPlugin(dependency: ModuleID): Setting[Seq[ModuleID]] = - libraryDependencies <+= (sbtVersion in update,scalaVersion) { (sbtV, scalaV) => sbtPluginExtra(dependency, sbtV, scalaV) } + libraryDependencies <+= (sbtBinaryVersion in update,scalaBinaryVersion in update) { (sbtV, scalaV) => sbtPluginExtra(dependency, sbtV, scalaV) } def compilerPlugin(dependency: ModuleID): ModuleID = dependency.copy(configurations = Some("plugin->default(compile)")) diff --git a/main/Keys.scala b/main/Keys.scala index 9cd4d3c09..e551e1dbb 100644 --- a/main/Keys.scala +++ b/main/Keys.scala @@ -133,6 +133,7 @@ object Keys val scalaHome = SettingKey[Option[File]]("scala-home", "If Some, defines the local Scala installation to use for compilation, running, and testing.") val scalaInstance = TaskKey[ScalaInstance]("scala-instance", "Defines the Scala instance to use for compilation, running, and testing.") val scalaVersion = SettingKey[String]("scala-version", "The version of Scala used for building.") + val scalaBinaryVersion = SettingKey[String]("scala-binary-version", "The Scala version substring describing binary compatibility.") val crossScalaVersions = SettingKey[Seq[String]]("cross-scala-versions", "The versions of Scala used when cross-building.") val classpathOptions = SettingKey[ClasspathOptions]("classpath-options", "Configures handling of Scala classpaths.") val definedSbtPlugins = TaskKey[Set[String]]("defined-sbt-plugins", "The set of names of Plugin implementations defined by this project.") @@ -296,6 +297,7 @@ object Keys val sbtResolver = SettingKey[Resolver]("sbt-resolver", "Provides a resolver for obtaining sbt as a dependency.") val sbtDependency = SettingKey[ModuleID]("sbt-dependency", "Provides a definition for declaring the current version of sbt.") val sbtVersion = SettingKey[String]("sbt-version", "Provides the version of sbt. This setting should be not be modified.") + val sbtBinaryVersion = SettingKey[String]("sbt-binary-version", "Defines the binary compatibility version substring.") val skip = TaskKey[Boolean]("skip", "For tasks that support it (currently only 'compile'), setting skip to true will force the task to not to do its work. This exact semantics may vary by task.") // special