summaryrefslogblamecommitdiff
path: root/project/Versions.scala
blob: fdfc6304fde9c54e4ebd50186ea5b0b0e47121e3 (plain) (tree)












































































































                                                                                                                                    
import sbt._
import Keys._
import java.util.Properties
import scala.util.control.Exception.catching
import java.lang.{NumberFormatException => NFE}
import java.io.FileInputStream
import com.jsuereth.git.GitRunner
import com.jsuereth.git.GitKeys.gitRunner



object Versions {
  val buildNumberFile = SettingKey[File]("scala-build-number-file")
  // TODO - Make this a setting?
  val buildNumberProps = TaskKey[BaseBuildNumber]("scala-build-number-props")
  val buildRelease = SettingKey[Boolean]("scala-build-release", "This is set to true if we're building a release.")
  val mavenSuffix = SettingKey[String]("scala-maven-suffix", "This is set to whatever maven suffix is required.")

  val gitSha = TaskKey[String]("scala-git-sha", "The sha of the current git commit.")
  val gitDate = TaskKey[String]("scala-git-date", "The date of the current git commit.")

  val mavenVersion = TaskKey[String]("scala-maven-version", "The maven version number.")
  val osgiVersion = TaskKey[String]("scala-osgi-version", "The OSGi version number.")
  val canonicalVersion = TaskKey[String]("scala-canonical-version", "The canonical version number.")

  
  def settings: Seq[Setting[_]] = Seq(
    buildNumberFile <<= baseDirectory apply (_ / "build.number"),
    buildNumberProps <<= buildNumberFile map loadBuildNumberProps,
    buildRelease := Option(System.getProperty("build.release")) map (!_.isEmpty) getOrElse false,
    mavenSuffix <<= buildRelease apply pickMavenSuffix,
    mavenVersion <<= (buildNumberProps, mavenSuffix) map makeMavenVersion,
    gitSha <<= (gitRunner, baseDirectory, streams) map getGitSha,
    gitDate <<= (gitRunner, baseDirectory, streams) map getGitDate,
    osgiVersion <<= (buildNumberProps, gitDate, gitSha) map makeOsgiVersion,
    canonicalVersion <<= (buildRelease, mavenVersion, buildNumberProps, gitDate, gitSha) map makeCanonicalVersion
  )

  def makeCanonicalVersion(isRelease: Boolean, mvnVersion: String, base: BaseBuildNumber, gitDate: String, gitSha: String): String =
    if(isRelease) mvnVersion
    else {
      val suffix = if(base.bnum > 0) "-%d".format(base.bnum) else ""
      "%s.%s.%s%s-%s-%s" format (base.major, base.minor, base.patch, suffix, gitDate, gitSha)
    }

  def makeMavenVersion(base: BaseBuildNumber, suffix: String): String = {
    val firstSuffix = if(base.bnum > 0) "-%d".format(base.bnum) else ""
    "%d.%d.%d%s%s" format (base.major, base.minor, base.patch, firstSuffix, suffix)
  }

  def makeOsgiVersion(base: BaseBuildNumber, gitDate: String, gitSha: String): String = {
    val suffix = if(base.bnum > 0) "-%d".format(base.bnum) else ""
    "%s.%s.%s.v%s%s-%s" format (base.major, base.minor, base.patch, gitDate, suffix, gitSha)
  }

  /** Determines what the maven sufffix should be for this build. */
  def pickMavenSuffix(isRelease: Boolean): String = {
    def default = if(isRelease) "" else "-SNAPSHOT"
    Option(System.getProperty("maven.version.suffix")) getOrElse default
  }

  /** Loads the build.number properties file into SBT. */
  def loadBuildNumberProps(file: File): BaseBuildNumber = {
    val fin = new FileInputStream(file)
    try {
      val props = new Properties()
      props.load(fin)
      def getProp(name: String): Int = 
        (for {
          v <- Option(props.getProperty(name))
          v2 <- catching(classOf[NFE]) opt v.toInt
        } yield v2) getOrElse sys.error("Could not convert %s to integer!" format (name))

      BaseBuildNumber(
        major=getProp("version.major"), 
        minor=getProp("version.minor"),
        patch=getProp("version.patch"),
        bnum =getProp("version.bnum")
      )
    } finally fin.close()
  }


  def getGitDate(git: GitRunner, baseDirectory: File, s: TaskStreams): String = {
    val lines = getGitLines("log","-1","--format=\"%ci\"")(git,baseDirectory, s)
    val line = if(lines.isEmpty) sys.error("Could not retreive git commit sha!") else lines.head
    // Lines *always* start with " for some reason...
    line drop 1 split "\\s+" match {
      case Array(date, time, _*) =>  "%s-%s" format (date.replaceAll("\\-", ""), time.replaceAll(":",""))
      case _                     => sys.error("Could not parse git date: " + line)
    }
  }

  def getGitSha(git: GitRunner, baseDirectory: File, s: TaskStreams): String = {
    val lines = getGitLines("log","-1","--format=\"%H\"", "HEAD")(git,baseDirectory, s)
    val line = if(lines.isEmpty) sys.error("Could not retreive git commit sha!") else lines.head
    val noquote = if(line startsWith "\"") line drop 1 else line
    val nog = if(noquote startsWith "g") noquote drop 1 else noquote
    nog take 10
  }

  def getGitLines(args: String*)(git: GitRunner, baseDirectory: File, s: TaskStreams): Seq[String] =
     git(args: _*)(baseDirectory, s.log) split "[\r\n]+"
}


case class BaseBuildNumber(major: Int, minor: Int, patch: Int, bnum: Int) {
  override def toString = "BaseBuildNumber(%d.%d.%d-%d)" format (major, minor, patch, bnum)
}