Skip to content

Commit

Permalink
first pass at implementing customizable version formats
Browse files Browse the repository at this point in the history
  • Loading branch information
philippe-pascal-ck authored and jsuereth committed Mar 19, 2015
1 parent 2aa38c1 commit f05f654
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 42 deletions.
5 changes: 5 additions & 0 deletions .gitignore
@@ -1,3 +1,8 @@
*~
target/
.idea/
/bin/
/.settings/
/.cache
/.classpath
/.project
105 changes: 63 additions & 42 deletions src/main/scala/com/typesafe/sbt/SbtGit.scala
Expand Up @@ -28,7 +28,13 @@ object SbtGit {
// Keys associated with setting a version number.
val useGitDescribe = SettingKey[Boolean]("use-git-describe", "Get version by calling `git describe` on the repository")
val gitTagToVersionNumber = SettingKey[String => Option[String]]("git-tag-to-version-number", "Converts a git tag string to a version number.")
val baseVersion = SettingKey[String]("base-version", "The base version number which we will append the git version to. May be left unspecified.")

// TODO - instead of exposinv functions, we could possibly just have these be `Option[String]` that the user can override.
// WOuld be one less hop, conceptually, when overriding the values, and allow you to pull in any existing setting you want.
val formatShaVersion = SettingKey[(String,String, String) => String]("format-sha-version","Formats the version string when it's built with git sha. Arguemnts are 'prefix', 'sha', 'suffix'.")
val formatDateVersion = SettingKey[(String,java.util.Date) => String]("format-date-version","Formats the version string when it's built with the current date. Arguments are 'prefix', 'date'")

val baseVersion = SettingKey[String]("base-version", "The base version number which we will append the git version to.")
val versionProperty = SettingKey[String]("version-property", "The system property that can be used to override the version number. Defaults to `project.version`.")
val uncommittedSignifier = SettingKey[Option[String]]("uncommitted-signifier", "Optional additional signifier to signify uncommitted changes")

Expand Down Expand Up @@ -119,18 +125,31 @@ object SbtGit {
uncommittedSignifier in ThisBuild := Some("SNAPSHOT"),
useGitDescribe in ThisBuild := false,
version in ThisBuild := {
git.makeVersion(
versionProperty=git.versionProperty.value,
baseVersion = git.baseVersion.?.value,
headCommit = git.gitHeadCommit.value,
useGitDescribe = git.useGitDescribe.value,
gitDescribedVersion = git.gitDescribedVersion.value,
currentTags = git.gitCurrentTags.value,
releaseTagVersion = git.gitTagToVersionNumber.value,
hasUncommittedChanges = git.gitUncommittedChanges.value,
uncommittedSignifier = git.uncommittedSignifier.value
)
}
val base = git.baseVersion.?.value.getOrElse("")
val overrideVersion =
git.overrideVersion(git.versionProperty.value)
val uncommittiedSuffix =
git.makeUncommittedSignifierSuffix(git.gitUncommittedChanges.value, git.uncommittedSignifier.value)
val releaseVersion =
git.releaseVersion(git.gitCurrentTags.value, git.gitTagToVersionNumber.value)
val describedVersion =
git.flaggedOptional(git.useGitDescribe.value, git.gitDescribedVersion.value)
val datedVersion =
git.formatDateVersion.value(base, new java.util.Date)
val commitVersion =
git.gitHeadCommit.value map { sha =>
git.formatShaVersion.value(base, sha, uncommittiedSuffix)
}
//Now we fall through the potential version numbers...
git.makeVersion(Seq(
overrideVersion,
releaseVersion,
describedVersion,
commitVersion
)) getOrElse datedVersion // For when git isn't there at all.
},
formatShaVersion in ThisBuild := (git.defaultFormatShaVersion _),
formatDateVersion in ThisBuild := (git.defaultFormatDateVersion _)
)

/** A holder of keys for simple config. */
Expand All @@ -144,6 +163,8 @@ object SbtGit {
val gitCurrentTags = GitKeys.gitCurrentTags in ThisBuild
val gitCurrentBranch = GitKeys.gitCurrentBranch in ThisBuild
val gitTagToVersionNumber = GitKeys.gitTagToVersionNumber in ThisBuild
val formatShaVersion = GitKeys.formatShaVersion in ThisBuild
val formatDateVersion = GitKeys.formatDateVersion in ThisBuild
val baseVersion = GitKeys.baseVersion in ThisBuild
val versionProperty = GitKeys.versionProperty in ThisBuild
val gitUncommittedChanges = GitKeys.gitUncommittedChanges in ThisBuild
Expand All @@ -153,37 +174,37 @@ object SbtGit {
if(tag matches "v[0-9].*") Some(tag drop 1)
else None
}
// Simple fall-through on how to define the project version.
// TODO - Split this to use multiple settings, perhaps.
def makeVersion(versionProperty: String, baseVersion: Option[String], headCommit: Option[String], useGitDescribe:Boolean, gitDescribedVersion:Option[String], currentTags: Seq[String], releaseTagVersion: String => Option[String], hasUncommittedChanges: Boolean, uncommittedSignifier: Option[String]): String = {
// The version string passed in via command line settings, if desired.
def overrideVersion = Option(sys.props(versionProperty))
// Version string that is computed from tags.
def releaseVersion: Option[String] = {
val releaseVersions =
for {
tag <- currentTags
version <- releaseTagVersion(tag)
} yield version
// NOTE - Selecting the last tag or the first tag should be an option.
releaseVersions.reverse.headOption
}
def describedVersion: Option[String] = if(useGitDescribe) gitDescribedVersion else None

val basePrefix = baseVersion.map(_ + "-").getOrElse("")
val signifierSuffix = uncommittedSignifier.map("-" + _).filter(_ => hasUncommittedChanges).getOrElse("")

// Version string that just uses the commit version.
def commitVersion: Option[String] =
headCommit map (sha => basePrefix + sha + signifierSuffix)
// Version string that just uses the full timestamp.
def datedVersion: String = {

def defaultFormatShaVersion(baseVersion:String, sha:String, suffix: String):String = {
baseVersion + "-" + sha + suffix
}

def defaultFormatDateVersion(baseVersion:String, date:java.util.Date):String = {
val df = new java.text.SimpleDateFormat("yyyyMMdd'T'HHmmss")
df setTimeZone java.util.TimeZone.getTimeZone("GMT")
basePrefix + (df format (new java.util.Date))
}
//Now we fall through the potential version numbers...
overrideVersion orElse releaseVersion orElse describedVersion orElse commitVersion getOrElse datedVersion
baseVersion + "-" + (df format (new java.util.Date))
}

def flaggedOptional(flag: Boolean, value: Option[String]): Option[String] =
if(flag) value
else None

def makeUncommittedSignifierSuffix(hasUncommittedChanges: Boolean, uncommittedSignifier: Option[String]): String =
flaggedOptional(hasUncommittedChanges, uncommittedSignifier).map("-" + _).getOrElse("")

def releaseVersion(currentTags: Seq[String], releaseTagVersion: String => Option[String]): Option[String] = {
val releaseVersions =
for {
tag <- currentTags
version <- releaseTagVersion(tag)
} yield version
// NOTE - Selecting the last tag or the first tag should be an option.
releaseVersions.reverse.headOption
}
def overrideVersion(versionProperty: String) = Option(sys.props(versionProperty))

def makeVersion(versionPossibilities: Seq[Option[String]]): Option[String] = {
versionPossibilities.reduce(_ orElse _)
}
}
}
Expand Down

0 comments on commit f05f654

Please sign in to comment.