Skip to content

Instantly share code, notes, and snippets.

@joelanford
Last active August 2, 2017 19:48
Show Gist options
  • Save joelanford/5427e54a018171b031ef7fd834f3313b to your computer and use it in GitHub Desktop.
Save joelanford/5427e54a018171b031ef7fd834f3313b to your computer and use it in GitHub Desktop.
A (not quite working) groovy script to generate a sane version string from a git repository
#!/usr/bin/env groovy
class GitVersion {
static String initialVersion = "0.0.1"
String repoDir
Boolean isGitRepository
Boolean hasCommit
Boolean isClean
String lastTag
String lastVersion
String lastLabel
String nextMajorVersion
String nextMinorVersion
String nextPatchVersion
String branch
String commitHash
String shortCommitHash
Integer commitsSinceLastTag
Integer commitsSinceDevelop
GitVersion(repoDir) {
this.repoDir = repoDir
this.isGitRepository = this.initIsGitRepository()
if (!this.isGitRepository) {
throw new Exception("not a git repository")
}
this.hasCommit = this.initHasCommit()
if (!this.hasCommit) {
throw new Exception("repository has no commits")
}
this.isClean = this.initIsClean()
this.lastTag = this.initLastTag()
this.lastVersion = this.initLastVersion()
this.lastLabel = this.initLastLabel()
if (this.lastVersion == "") {
this.nextMajorVersion = this.nextMajorVersionFrom(GitVersion.initialVersion)
this.nextMinorVersion = this.nextMinorVersionFrom(GitVersion.initialVersion)
this.nextPatchVersion = this.nextPatchVersionFrom(GitVersion.initialVersion)
} else {
this.nextMajorVersion = this.nextMajorVersionFrom(this.lastVersion)
this.nextMinorVersion = this.nextMinorVersionFrom(this.lastVersion)
this.nextPatchVersion = this.nextPatchVersionFrom(this.lastVersion)
}
this.branch = this.initBranch()
this.commitHash = this.initCommitHash()
this.shortCommitHash = this.commitHash[0..Math.min(this.commitHash.length()-1,7)]
this.commitsSinceLastTag = this.commitsSince(this.lastTag)
this.commitsSinceDevelop = this.commitsSince("develop")
}
Boolean initIsGitRepository() {
def cmd = "git status".execute()
cmd.waitFor()
return cmd.exitValue() == 0
}
Boolean initHasCommit() {
return this.initCommitHash() != "HEAD"
}
Boolean initIsClean() {
return "git status --porcelain".execute().text == ""
}
String initLastTag() {
return "git rev-list --tags --no-walk --max-count=1".execute().text.trim()
}
String initLastVersion() {
def lastVersionLabel = "git describe --abbrev=0".execute().text.trim()
if (lastVersionLabel == "") {
return ""
}
return lastVersionLabel.tokenize("-")[0]
}
String initLastLabel() {
def lastVersionLabel = "git describe --abbrev=0".execute().text.trim()
if (lastVersionLabel == "") {
return ""
}
def lvSplit = lastVersionLabel.tokenize("-")
if (lvSplit.size() > 1) {
return lvSplit[1..-1].join("-")
} else {
return ""
}
}
String nextMajorVersionFrom(fromVersion) {
def (major, minor, patch) = fromVersion.tokenize(".")*.toInteger()
return "${major+1}.0.0"
}
String nextMinorVersionFrom(fromVersion) {
def (major, minor, patch) = fromVersion.tokenize(".")*.toInteger()
return "${major}.${minor+1}.0"
}
String nextPatchVersionFrom(fromVersion) {
def (major, minor, patch) = fromVersion.tokenize(".")*.toInteger()
return "${major}.${minor}.${patch+1}"
}
String initBranch() {
def branch = "git symbolic-ref HEAD".execute().text.replace("refs/heads/", "").trim()
if (branch == "") {
branch = "undefined"
}
return branch
}
String initCommitHash() {
def commitHash = "git rev-parse HEAD".execute().text.trim()
if (commitHash == "") {
commitHash = "undefined"
}
return commitHash
}
Integer commitsSince(rev) {
if (rev == "") {
return -1
}
def commitsSince = "git rev-list ${rev}..HEAD --count".execute().text.trim()
if (commitsSince == "") {
return -1
}
return commitsSince.toInteger()
}
String masterVersion() {
if (this.lastTag == "") {
return GitVersion.initialVersion
}
return this.lastVersion
}
String masterLabel() {
def labelSegments = [this.lastLabel]
if (this.commitsSinceLastTag < 0) {
labelSegments += this.shortCommitHash
} else if (this.commitsSinceLastTag > 0) {
labelSegments += "untagged+${this.commitsSinceLastTag}"
}
return this.joinLabelSegments(labelSegments)
}
String developVersion() {
return this.nextMinorVersion
}
String developLabel() {
def labelSegments = []
if (this.commitsSinceLastTag < 0) {
labelSegments += this.shortCommitHash
} else if (this.commitsSinceLastTag > 0) {
if (lastLabel.startsWith("alpha")) {
labelSegments += "${lastLabel}+${this.commitsSinceLastTag}"
} else {
labelSegments += "alpha0+${this.commitsSinceLastTag}"
}
}
return this.joinLabelSegments(labelSegments)
}
String releaseCandidateVersion() {
return branch - "release/"
}
String releaseCandidateLabel() {
def labelSegments = []
if (this.commitsSinceLastTag < 0) {
labelSegments += this.shortCommitHash
} else if (this.commitsSinceLastTag > 0) {
if (lastLabel.startsWith("beta")) {
labelSegments += "${lastLabel}+${this.commitsSinceLastTag}"
} else {
labelSegments += "beta0+${this.commitsSinceLastTag}"
}
}
return this.joinLabelSegments(labelSegments)
}
String hotfixVersion() {
return branch - "hotfix/"
}
String hotfixLabel() {
return this.releaseCandidateLabel()
}
String featureVersion() {
this.nextMinorVersion
}
String featureLabel() {
def feature = (this.branch - "feature/").toLowerCase().replace("-", "_")
return this.joinLabelSegments(["feature-${feature}", this.shortCommitHash])
}
String joinLabelSegments(segments) {
segments.removeAll([""])
if (segments.size() == 0) {
return ""
}
return "-${segments.join("-")}"
}
void printInfo() {
println "Is Git Repository: ${this.isGitRepository}"
println "Has commit: ${this.hasCommit}"
println "Last version: ${this.lastVersion}"
println "Last label: ${this.lastLabel}"
println "Next major version: ${this.nextMajorVersion}"
println "Next minor version: ${this.nextMinorVersion}"
println "Next patch version: ${this.nextPatchVersion}"
println "Branch: ${this.branch}"
println "Commit hash: ${this.commitHash}"
println "Is Clean: ${this.isClean}"
println "Last tag: ${this.lastTag}"
println "Commits since last tag: ${this.commitsSinceLastTag}"
println "Commits since develop: ${this.commitsSinceDevelop}"
}
String computedVersionLabel() {
def version = ""
def label = ""
if (commitsSinceLastTag == 0) {
version = this.lastVersion
label = this.joinLabelSegments([this.lastLabel])
} else if (branch == "master") {
version = this.masterVersion()
label = this.masterLabel()
} else if (branch == "develop") {
version = this.developVersion()
label = this.developLabel()
} else if (branch.startsWith("release/")) {
version = this.releaseCandidateVersion()
label = this.releaseCandidateLabel()
} else if (branch.startsWith("hotfix/")) {
version = this.hotfixVersion()
label = this.hotfixLabel()
} else if (branch.startsWith("feature/")) {
version = this.featureVersion()
label = this.featureLabel()
} else {
throw new Exception("unsupported branch name!")
}
if (!isClean) {
label += "-dirty"
}
return "${version}${label}"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment