diff --git a/.gitignore b/.gitignore index 63b2bf7..1c9b0f0 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,4 @@ Thumbs.db /.gradle/ /build/ +/local.properties diff --git a/.run/publishToMavenLocal.run.xml b/.run/publishToMavenLocal.run.xml new file mode 100644 index 0000000..075fca5 --- /dev/null +++ b/.run/publishToMavenLocal.run.xml @@ -0,0 +1,24 @@ + + + + + + + true + true + false + false + + + \ No newline at end of file diff --git a/.run/testGitMavenVersion.run.xml b/.run/testGitMavenVersion.run.xml new file mode 100644 index 0000000..66fc19c --- /dev/null +++ b/.run/testGitMavenVersion.run.xml @@ -0,0 +1,26 @@ + + + + + + + false + true + false + true + + + \ No newline at end of file diff --git a/.run/testGitVersion.run.xml b/.run/testGitVersion.run.xml new file mode 100644 index 0000000..7fe7423 --- /dev/null +++ b/.run/testGitVersion.run.xml @@ -0,0 +1,26 @@ + + + + + + + false + true + false + true + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 5add2bf..0000000 --- a/build.gradle +++ /dev/null @@ -1,71 +0,0 @@ -buildscript { - ext { - myRepos = { - mavenLocal() - jcenter() - maven { - url "https://aminocom2.jfrog.io/artifactory/FokusOnPublic" - credentials { - username = gradleUsername - password = gradlePassword - } - } - } - } - repositories myRepos - dependencies { - classpath "com.24i:gitVersion:1.+" - } -} -plugins { - id "com.jfrog.artifactory" version "4.33.1" -} - -apply plugin: 'com.jfrog.artifactory' -apply plugin: 'groovy' -apply plugin: 'maven-publish' -apply plugin: 'com.24i.gitVersion' -apply plugin: 'java-gradle-plugin' -dependencies { - implementation gradleApi() - implementation localGroovy() -} - -repositories myRepos - -artifactory { - contextUrl = 'https://aminocom2.jfrog.io/artifactory/' - publish { - repository { - repoKey = 'fokuson-public-release-local' - username = gradleUsername - password = gradlePassword - maven = true - } - defaults { - publications ('mavenJava') - } - } -} - -publishing { - publications { - mavenJava(MavenPublication) { - from components.java - } - } -} - -dependencies { - testImplementation 'junit:junit:4.11' -} -group = 'com.24i' - -gradlePlugin { - plugins { - simplePlugin { - id = 'com.24i.gitVersion' - implementationClass = 'com._24i.VersionManagerPlugin' - } - } -} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..7b2f2f9 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,75 @@ +import com.nordija.VersionManagerPlugin +// ------------------------------------------------------------------------------------------------- +buildscript { + dependencies { + classpath("com.nordija:gitMavenVersioning:2.2.+") + classpath("org.jfrog.buildinfo:build-info-extractor-gradle:4.29.0") + } +} +// ------------------------------------------------------------------------------------------------- +plugins { + `kotlin-dsl` + `maven-publish` + `java-gradle-plugin` + id("com.jfrog.artifactory") version ("4.33.1") +} +kotlin { + jvmToolchain(17) +} +dependencies { + implementation(gradleApi()) + implementation(localGroovy()) + implementation(gradleKotlinDsl()) + testImplementation("junit:junit:4.11") +} +// ------------------------------------------------------------------------------------------------- +plugins.apply (VersionManagerPlugin::class) +// ------------------------------------------------------------------------------------------------- +val pluginGroup = "com.24i" +val pluginVersion = "1.1.2" +val pluginName = "gitVersion" +val pluginDescription = "Versioning plugin 24i" +// ------------------------------------------------------------------------------------------------- +val pluginId = "$pluginGroup.$pluginName" +val pluginClass = "com._24i.VersionManagerPlugin" +val userName = project.property("gradleUsername") as String +val password = project.property("gradlePassword") as String +// ------------------------------------------------------------------------------------------------- +group = pluginGroup +version = pluginVersion +// ------------------------------------------------------------------------------------------------- +gradlePlugin { + plugins { + register(pluginName) { + id = pluginId + implementationClass = pluginClass + displayName = pluginName + description = pluginDescription + } + } +} +// ------------------------------------------------------------------------------------------------- +artifactory { + setContextUrl("https://aminocom2.jfrog.io/artifactory/") + publish { + repository { + setRepoKey("fokuson-public-release-local") + setUsername(userName) + setPassword(password) + setMavenCompatible(true) + setVersion(pluginVersion) + } + defaults { + publications("mavenJava") + } + } +} +// ------------------------------------------------------------------------------------------------- +publishing { + publications { + create("mavenJava") { + from(components["java"]) + } + } +} +// ------------------------------------------------------------------------------------------------- diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 05679dc..2733ed5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index b6a402b..0000000 --- a/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'gitVersion' diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..1e6f9ba --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,33 @@ +pluginManagement { + repositories { + mavenLocal() + mavenCentral() + gradlePluginPortal() + maven("https://aminocom2.jfrog.io/artifactory/FokusOnCentral") { + val gradleUsername: String by settings + val gradlePassword: String by settings + credentials { + username = gradleUsername + password = gradlePassword + } + } + } +} + +dependencyResolutionManagement { + repositories { + mavenLocal() + mavenCentral() + gradlePluginPortal() + maven("https://aminocom2.jfrog.io/artifactory/FokusOnCentral") { + val gradleUsername: String by settings + val gradlePassword: String by settings + credentials { + username = gradleUsername + password = gradlePassword + } + } + } +} + +rootProject.name = "gitVersion" diff --git a/src/main/groovy/com/_24i/VersionManagerPlugin.groovy b/src/main/groovy/com/_24i/VersionManagerPlugin.groovy deleted file mode 100644 index 9181775..0000000 --- a/src/main/groovy/com/_24i/VersionManagerPlugin.groovy +++ /dev/null @@ -1,64 +0,0 @@ -package com._24i - -import com._24i.VersionManagerTask -import org.gradle.api.Plugin -import org.gradle.api.Project - -class VersionManagerPlugin implements Plugin { - Project project; - - - void apply(Project target) { - this.project = target; - - final myTask = target.task('version', type: VersionManagerTask) - project.allprojects.each { proj -> - proj.tasks.all { - // Make sure to not add a circular dependency - if (it != myTask) { - it.dependsOn(myTask) - } - } - } - project.task('showVersion') { - group = 'Help' - description = 'Show the project version' - } - project.task('findVersion') { - group = 'task' - description = 'Find the version from git system' - } - project.task('printVersion') { - group = 'task' - description = 'Print the version from git system' - } - project.tasks.showVersion { - doLast { - println "Version (project.version): " + project.version - println "Branch (System.properties.gitBranch): " + System.properties.gitBranch; - println "Parent Branch (System.properties.gitParentBranch): " + System.properties.gitParentBranch; - println "Highest tag hash (System.properties.gitHighestTagHash): " + System.properties.gitHighestTagHash; - println "Highest tag (System.properties.gitHighestTag): " + System.properties.gitHighestTag; - println "Highest tag count (System.properties.gitHighestTagCount): " + System.properties.gitHighestTagCount; - println "Current commit short hash (System.properties.gitCurrentShortCommitHash): " + System.properties.gitCurrentShortCommitHash; - println "Current commit hash (System.properties.gitCurrentCommitHash): " + System.properties.gitCurrentCommitHash; - println "Derived values based on above information: " - println "Use in maven version and gradle version (System.properties.mavenVersion): " + System.properties.mavenVersion; - println "Use in app version (System.properties.appVersion): " + System.properties.appVersion; - println "Use as part of artifact name (System.properties.gitDescribe): " + System.properties.gitDescribe; - println "Use as part of artifact name (System.properties.gitAppDescribe): " + System.properties.gitAppDescribe; - println "Use as versionGitNumber (System.properties.gitPaddedVersionCount): " + System.properties.gitPaddedVersionCount; - println "Use as part of artifact name (System.properties.versionSnapshot): " + System.properties.versionSnapshot; - } - } - project.tasks.findVersion { -// println "Version (project.version): " + project.version - } - project.tasks.printVersion { - doLast { - println "Version (project.version): " + project.version - } - } - - } -} diff --git a/src/main/groovy/com/_24i/VersionManagerTask.groovy b/src/main/groovy/com/_24i/VersionManagerTask.groovy deleted file mode 100644 index 4e419dd..0000000 --- a/src/main/groovy/com/_24i/VersionManagerTask.groovy +++ /dev/null @@ -1,489 +0,0 @@ -package com._24i - -import org.gradle.api.DefaultTask -import org.gradle.api.Task -import org.gradle.api.tasks.Internal -import org.gradle.api.tasks.TaskAction -import org.gradle.process.ExecResult - -class VersionManagerTask extends DefaultTask { - @Internal - String branch = ""; - @Internal - String parentBranch = ""; - @Internal - String closestHighestTagHash; - @Internal - String closestTag; - @Internal - String currentShortCommitHash; - @Internal - String currentCommitHash; - @Internal - String mavenVersion; - @Internal - String appVersion; - @Internal - String gitDescribe; - @Internal - String gitAppDescribe; - @Internal - String gitPaddedVersionCount; - @Internal - boolean snapshot = true; - @Internal - boolean initialized = false; - @Internal - Task superConfigureTask = null; - - @Override - Task configure(Closure closure) { - if (!initialized) { - findGitVersions() - setVersions() - initialized = true; - superConfigureTask = super.configure(closure) - } - return superConfigureTask; - } - - @TaskAction - def findGitVersions() { - findBranch() - findCurrentCommitHash() - if (!branch.equals('HEAD')) { - findParentBranch() - } - findCurrentCommitShortHash() - findClosestTagHash() - findGitClosestTag() - findVersion() - findGitDescribeVersion() - findGitAppDescribeVersion() - setVersions() - } - - - private String execGitCommand(Object... commands) { - try { - def stderr = new ByteArrayOutputStream() - def stdout = new ByteArrayOutputStream() - ExecResult result = this.project.exec({ - it.commandLine = commands - it.standardOutput = stdout - it.errorOutput = stderr; - }) - return stdout.toString().trim() - } catch (Exception e) { - return null; - } - } - - private void findParentBranch() { - if (branch != null && !branch.equals('main') && !branch.startsWith("bugfix_")) { - def foundHash = parentBranchCommitHash() - if (foundHash == null || foundHash.isEmpty()) { - foundHash = currentCommitHash - } - if (foundHash != null && !foundHash.isEmpty()) { - def hashes = foundHash.split(' ') - def parentBranchFound = '' - for (String hash : hashes) { - String foundBranch = findLowestBranchForHash(hash) - if (foundBranch != null && !foundBranch.isEmpty() && !parentBranchFound.equals(foundBranch)) { - if (foundBranch.startsWith('bugfix')) { - parentBranchFound = findLowestBranch(foundBranch,parentBranchFound) - } else if (!parentBranchFound.startsWith('bugfix') && foundBranch.equals('main')) { - parentBranchFound = foundBranch - } - } - } - parentBranch = parentBranchFound - } - } - } - - private String findLowestBranch(String branchA, String branchB) { - if (branchA.equals('')) { - return branchB - } - if (branchB.equals('')) { - return branchA - } - if (branchA.startsWith('bugfix') && branchB.startsWith('bugfix')) { - int compare = branchA.compareTo(branchB) - if (comare < 0 || compare == 0) { - return branchA - } - else { - return branchB - } - } else if (branchA.startsWith('bugfix')) { - return branchA - } else if (branchB.startsWith('bugfix')) { - return branchB - } - if (branchA.equals('main')) { - return branchA - } - if (branchB.equals('main')) { - return branchB - } - return '' - } - - private String findLowestBranchForHash(String hash) { - def stderr = new ByteArrayOutputStream() - def stdout = new ByteArrayOutputStream() - String outputString; - if (project.hasProperty('CI') && Boolean.valueOf(project.properties['CI'])) { - outputString = execGitCommand('git', 'branch', '--contains', hash) - } else { - outputString = execGitCommand('git', 'branch', '-r', '--contains', hash) - } - if (outputString == null) { - return '' - } - def branches = outputString; - if (outputString.contains('\n')) { - branches = outputString.split('\n'); - def branchFound = '' - for (final String item : branches) { - if (item.startsWith("*")) { - branchFound = item.substring(1); - } else { - branchFound = item - } - branchFound = branchFound.trim().replaceAll('origin\\/','') - if (branchFound.startsWith('bugfix_') || branchFound.equals('main')) { - return branchFound - } - } - } else { - if (branches.startsWith('*')) { - return branches.replaceAll('origin/','').substring(1).trim() - } - return outputString.replaceAll('origin/','').trim() - } - return ''; - } - - private String parentBranchCommitHash() { - def stderr = new ByteArrayOutputStream() - def stdout = new ByteArrayOutputStream() - - def outputString; - if (project.hasProperty('CI') && Boolean.valueOf(project.properties['CI'])) { - outputString = execGitCommand( 'git', 'log', branch, '--not', 'main', '--pretty=format:%P') - } else { - outputString = execGitCommand( 'git', 'log', branch, '--not', 'origin/main', '--pretty=format:%P') - } - def hashes; - def version = ''; - if (outputString != null && outputString.contains('\n')) { - hashes = outputString.split('\n'); - for (String item : hashes) { - version = item; - } - } else if (outputString != null) { - version = outputString - } - return version; - } - - - - void setVersions() { - System.setProperty("gitBranch",branch); - if (parentBranch == null) { - parentBranch = 'N/A' - } - System.setProperty("gitParentBranch",parentBranch); - System.setProperty("gitHighestTagHash",closestHighestTagHash); - System.setProperty("gitHighestTag",closestTag); - System.setProperty("gitCurrentShortCommitHash",currentShortCommitHash); - System.setProperty("gitCurrentCommitHash",currentCommitHash); - System.setProperty("mavenVersion",mavenVersion); - System.setProperty("appVersion",appVersion); - System.setProperty("gitDescribe",gitDescribe); - System.setProperty("gitAppDescribe",gitAppDescribe); - if (gitPaddedVersionCount != null) { - System.setProperty("gitPaddedVersionCount", gitPaddedVersionCount); - } - - System.setProperty("versionSnapshot",''+snapshot); - if (mavenVersion != null) { - getProject().version = mavenVersion - } - - - } - - void findCurrentCommitShortHash() { - currentShortCommitHash = execGitCommand('git', 'rev-parse', '--short','HEAD') - if (currentShortCommitHash == null || currentShortCommitHash.isEmpty()) { - currentShortCommitHash = "0" - } - logger.debug("Found currentShortCommitHash: " + currentShortCommitHash) - } - - void findCurrentCommitHash() { - currentCommitHash = execGitCommand('git', 'rev-parse', 'HEAD') - if (currentCommitHash == null || currentCommitHash.isEmpty()) { - currentCommitHash = "NoHashFound"; - } - logger.debug("Found currentCommitHash: " + currentCommitHash) - } - - - void findBranch() { - branch = execGitCommand('git','rev-parse', '--abbrev-ref', 'HEAD') - if (branch != null) { - branch = branch.replaceAll("[^\\dA-Za-z ]", "_") - } - parentBranch = branch - logger.debug("Found branch: " + branch) - - } - - void findClosestTagHash() { - def branchToFindTag = branch - if (!parentBranch.equals(branch)) { - branchToFindTag = parentBranch - } - if (branchToFindTag.equals('main')) { - logger.info("findClosestTagHash " + branchToFindTag) - def tag = findGitHighestTag() - closestHighestTagHash = execGitCommand('git','log', '-1', '--format=format:%H', tag) - this.closestTag = tag - } else if (branchToFindTag != null) { - if (branchToFindTag.startsWith("bugfix_")) { - String version = highestVersionNumber(branchToFindTag) - this.closestHighestTagHash = execGitCommand('git', 'rev-list', '-n', '1', version) - } else if (branchToFindTag.equals("HEAD")) { - closestHighestTagHash = currentCommitHash; - findGitClosestTag(); - if (closestTag.contains('-') && !closestTag.contains("-RC") && !closestTag.contains("-M")) { - def tag = closestTag.substring(0,closestTag.indexOf('-')) - this.closestHighestTagHash = execGitCommand('git', 'rev-list', '-n', '1', tag) - } - } else { - logger.info("findClosestTagHash else ") - def tag = findGitHighestTag() - this.closestHighestTagHash = execGitCommand('git','log', '-1', '--format=format:%H', tag) - this.closestTag = tag - } - } - if (closestHighestTagHash == null || closestHighestTagHash.empty) { - this.closestHighestTagHash = "0" - } - logger.debug("Found closestHighestTagHash: " + closestHighestTagHash) - - } - - private String highestVersionNumber(String branch) { - def extractedVersion = branch.replaceAll("bugfix_", "").replaceAll("_", "."); - def outputString = execGitCommand('git', 'tag', '-l', extractedVersion + '*', '--sort=v:refname') - def hashes; - def version = '0.0.0'; - if (outputString.contains('\n')) { - hashes = outputString.split('\n'); - for (String item : hashes) { - if (item.matches("[0-9|.|a-z|R|C|M|-]*")) { - if (version.empty || !(item.startsWith(version) && (item.contains("RC") || item.contains("M")))) { - version = item - } - } - } - } else { - version = outputString - } - return version; - } - - String findGitHighestTag () { - def outputString = execGitCommand('git','tag', '-l', '--sort=v:refname') - if (outputString == null || outputString.empty) { - return "0.0.0" - } - def hashes; - if (outputString.contains('\n')) { - hashes = outputString.split('\n'); - } else { - hashes = [outputString]; - } - def closestTag = ''; - for (String item : hashes) { - if (item.matches("[0-9|.|a-z|R|C|M|-]*")) { - if (closestTag.empty || !(item.startsWith(closestTag) && (item.contains("RC") || item.contains("M")))) { - closestTag = item - } - } - - } - return closestTag - } - - void findGitClosestTag () { - closestTag = execGitCommand('git', 'describe', '--tags', closestHighestTagHash) - if (closestTag == null || closestTag.empty) { - closestTag = "0.0.0"; - } - if (branch == null) { - branch = "main" - } - if (branch.startsWith('bugfix_') && closestTag.equals('0.0.0')) { - def extractedVersion = branch.replaceAll("bugfix_", "").replaceAll("_", ".") - closestTag = extractedVersion + '.0' - - } - - logger.debug("Found ClosestTag: " + closestTag) - } - - void findVersion() { - def closestTag = closestTag; - def gitBranch = branch; - def versionSplit = /([0-9]+).([0-9]+).([0-9]+).*/; - def matcher = ( closestTag =~ versionSplit ); - if (closestHighestTagHash.equals(currentCommitHash)) { - mavenVersion = closestTag; - def major = matcher[0][1]; - def minor = matcher[0][2]; - def bugfix = matcher[0][3]; - gitPaddedVersionCount = major + - String.format("%02d", minor.toLong()) + - String.format("%02d", bugfix.toLong()) - snapshot = false; - if (isProjectDirty()) { - mavenVersion += '-dirty' - } - } else { - def major = matcher[0][1]; - def minor = matcher[0][2]; - def bugfix = matcher[0][3]; - def branchToFindVersion = branch - if (!parentBranch.equals(branch)) { - branchToFindVersion = parentBranch - } - if (gitBranch == null) { - mavenVersion = '0.0.0-SNAPSHOT' - branch = 'unknown' - return - } - if (gitBranch.equals("main")) { - if (closestTag.contains("-M")) { - minor = 0; - bugfix = "0.0-SNAPSHOT"; - } else { - major = major.toLong() +1; - minor = 0; - bugfix = "0-SNAPSHOT"; - } - } else if (gitBranch.startsWith("bugfix")) { - if ((closestHighestTagHash.equals('0') && minor.equals('0')) || closestTag.contains("-RC") || closestTag.contains("-M")) { - minor = 0; - bugfix = bugfix + '-SNAPSHOT' - } else { - minor = (minor.toLong() + 1) - bugfix = 0 + "-SNAPSHOT" - } - } else { - def startIdx = 0; - def endIdx = 11; - if (gitBranch == null) { - gitBranch = "-UNKNOWN"; - } else if (gitBranch.length() >= endIdx) { - if (gitBranch.startsWith("SPRINT-")) { - startIdx = 7; - } - gitBranch = "-" + gitBranch.substring(startIdx, endIdx); - } else if (gitBranch.equals("HEAD")) { - gitBranch = ""; - } else { - gitBranch = "-" + gitBranch.substring(startIdx, gitBranch.length()); - } - if (!parentBranch.equals(branch) && parentBranch.startsWith('bugfix')) { - bugfix = (bugfix.toLong() + 1) +gitBranch + "-SNAPSHOT" - } else if (gitBranch.startsWith('-') && closestTag.contains("-M")) { - bugfix = "0" + gitBranch + "-SNAPSHOT"; - } else { - minor = minor.toLong() + 1; - bugfix = "0" + gitBranch + "-SNAPSHOT"; - } - } - def bugfixExtracted = '0'; - if (bugfix.indexOf('-')) { - bugfixExtracted = bugfix.substring(0,bugfix.indexOf('-')); - } else if (bugfix.isNumber()) { - bugfixExtracted = bugfix; - } - - gitPaddedVersionCount = major + - String.format("%02d", minor.toLong()) + - String.format("%02d", bugfixExtracted.toLong()) - mavenVersion = (major + - "." + - minor + - "." + - bugfix); - if (isProjectDirty()) { - mavenVersion += '-dirty' - } - } - if (mavenVersion.equals(closestTag) && branch.equals('HEAD')) { - branch = mavenVersion - } - logger.debug("Found mavenVersion: " + mavenVersion) - logger.debug("Found gitPaddedVersionCount: " + gitPaddedVersionCount) - } - - void findGitDescribeVersion() { - if (currentCommitHash.equals(closestHighestTagHash)) { - gitDescribe = closestTag; - } else { - gitDescribe = getMavenVersion()+ '-'+ currentShortCommitHash; - } - logger.debug("found gitDescribe: " + gitDescribe) - } - - void findGitAppDescribeVersion() { - if (currentCommitHash.equals(closestHighestTagHash)) { - gitAppDescribe = closestTag; - } else { - gitAppDescribe = gitDescribe.replaceAll('-SNAPSHOT',''); - } - appVersion = mavenVersion.replaceAll('-SNAPSHOT',''); - logger.debug("found gitAppDescribe: " + gitAppDescribe) - } - - @Internal - boolean isProjectDirty() { - def resultValue = execGitCommand('git', 'status', '--porcelain') - if (resultValue != null && resultValue.length() > 2) { - return resultValue.split("\n").size() > 0 - } else { - return false - } - } - - int compareVersions(String v1, String v2) { - - if (v1.length() > 0 && v2.length() == 0) return -1; - if (v1.length() == 0 && v2.length() == 0) return 0; - if (v1.length() == 0 && v2.length() < 0) return 1; - - int pos1 = v1.indexOf('.'); - int pos2 = v2.indexOf('.'); - - Integer num1 = (pos1 > 0 ? Integer.valueOf(v1.substring(0, pos1)) : 0); - Integer num2 = (pos2 > 0 ? Integer.valueOf(v2.substring(0, pos2)) : 0); - - if (num1 != num2) return num1.compareTo(num2); - - String tail1 = (pos1 > 0 ? v1.substring(pos1 + 1, v1.length()) : ""); - String tail2 = (pos2 > 0 ? v2.substring(pos2 + 1, v2.length()) : ""); - - return compareVersions(tail1, tail2); - } -} diff --git a/src/main/kotlin/com/_24i/TaskGitVersion.kt b/src/main/kotlin/com/_24i/TaskGitVersion.kt new file mode 100644 index 0000000..a4832f7 --- /dev/null +++ b/src/main/kotlin/com/_24i/TaskGitVersion.kt @@ -0,0 +1,481 @@ +package com._24i + +import groovy.lang.Closure +import org.gradle.api.DefaultTask +import org.gradle.api.Task +import org.gradle.api.tasks.TaskAction +import java.util.regex.Pattern +import java.lang.Boolean.parseBoolean as javaParseBoolean + +open class TaskGitVersion : DefaultTask() { + private var branch: String? = "" + private var parentBranch: String? = "" + private var closestHighestTagHash: String? = null + private var closestTag: String? = null + private var currentShortCommitHash: String? = null + private var currentCommitHash: String? = null + private var mavenVersion: String? = null + private var appVersion: String? = null + private var gitDescribe: String? = null + private var gitAppDescribe: String? = null + private var gitPaddedVersionCount: String? = null + private var snapshot: Boolean = true + private var initialized: Boolean = false + + private fun parseBoolean(input: String, default: Boolean = false): Boolean = runCatching { + javaParseBoolean(input) + }.onFailure { e -> + println(e.message) + }.getOrDefault(default) + + private fun execGitCommand(vararg commands: Any): String? { + logger.debug("cmd: ${commands.contentToString()}") + try { + return project.providers.exec { + commandLine(*commands) + }.standardOutput.asText.getOrElse("").trim { it <= ' ' } + } catch (e: Exception) { + logger.debug("E: ${e.message}") + return null + } + } + + override fun configure(closure: Closure<*>): Task { + findGitVersions() + setVersions() + return super.configure(closure) + } + + @TaskAction + fun findGitVersions() { + logger.debug("main task action") + findBranch() + findCurrentCommitHash() + if (branch != "HEAD") { + findParentBranch() + } + findCurrentCommitShortHash() + findClosestTagHash() + findGitClosestTag() + findVersion() + findGitDescribeVersion() + findGitAppDescribeVersion() + setVersions() + } + + private fun isProjectDirty(): Boolean { + val resultValue = execGitCommand("git", "status", "--porcelain") + return if (resultValue != null && resultValue.length > 2) { + resultValue.split("\n".toRegex()).dropLastWhile { + it.isEmpty() + }.toTypedArray().isNotEmpty() + } else { + false + } + } + + private fun findParentBranch() { + logger.debug("findParentBranch of branch: $branch") + if (branch != null && (branch != "main") && !branch!!.startsWith("bugfix_")) { + var foundHash: String? = parentBranchCommitHash() + if (foundHash.isNullOrEmpty()) { + foundHash = currentCommitHash + } + if (!foundHash.isNullOrEmpty()) { + val hashes = foundHash.split(" ".toRegex()).dropLastWhile { + it.isEmpty() + }.toTypedArray() + var parentBranchFound = "" + for (hash in hashes) { + val foundBranch = findLowestBranchForHash(hash) + if (foundBranch.isNotEmpty() && (parentBranchFound != foundBranch)) { + if (foundBranch.startsWith("bugfix")) { + parentBranchFound = findLowestBranch(foundBranch, parentBranchFound) + } else if (!parentBranchFound.startsWith("bugfix") && foundBranch == "main") { + parentBranchFound = foundBranch + } + } + } + parentBranch = parentBranchFound + } + } + logger.debug("Parent branch: $parentBranch") + } + + private fun findLowestBranch(branchA: String, branchB: String): String { + logger.debug("findLowestBranch of ($branchA, $branchB)") + if (branchA == "") return branchB + if (branchB == "") return branchA + if (branchA.startsWith("bugfix") && branchB.startsWith("bugfix")) { + val compare = branchA.compareTo(branchB) + return if (compare < 0 || compare == 0) branchA else branchB + } else if (branchA.startsWith("bugfix")) { + return branchA + } else if (branchB.startsWith("bugfix")) { + return branchB + } + if (branchA == "main") return branchA + if (branchB == "main") return branchB + return "" + } + + private fun findLowestBranchForHash(hash: String): String { + logger.debug("findLowestBranchForHash: $hash") + val hasCI = project.hasProperty("CI") + val isCI = if (hasCI) parseBoolean(project.property("CI").toString()) else false + val outputString = if (isCI) { + execGitCommand("git", "branch", "--contains", hash) + } else { + execGitCommand("git", "branch", "-r", "--contains", hash) + } + if (outputString == null) return "" + val branches: String = outputString + if (outputString.contains("\n")) { + val branchesArray = outputString.split("\n").dropLastWhile { + it.isEmpty() + }.toTypedArray() + var branchFound = "" + for (item in branchesArray) { + branchFound = if (item.startsWith("*")) item.substring(1) else item + branchFound = item.trim { it <= ' ' }.replace("origin/", "") + if (branchFound.startsWith("bugfix_") || branchFound == "main") { + return branchFound + } + } + } else { + if (branches.startsWith("*")) { + return branches.replace("origin/", "") + .substring(1) + .trim { it <= ' ' } + } + return outputString.replace("origin/", "") + .trim { it <= ' ' } + } + return "" + } + + private fun parentBranchCommitHash(): String { + logger.debug("parentBranchCommitHash") + val hasCI = project.hasProperty("CI") + val isCI = if (hasCI) parseBoolean(project.property("CI").toString()) else false + val outputString = if (isCI) { + execGitCommand("git", "log", branch!!, "--not", "main", "--pretty=format:%P") + } else { + execGitCommand("git", "log", branch!!, "--not", "origin/main", "--pretty=format:%P") + } + val hashes: Array + var version = "" + if (outputString != null && outputString.contains("\n")) { + hashes = outputString.split("\n").dropLastWhile { + it.isEmpty() + }.toTypedArray() + for (item in hashes) version = item + } else if (outputString != null) { + version = outputString + } + return version + } + + private fun setVersions() { + if (parentBranch == null) { + parentBranch = "N/A" + } + logger.debug("setVersions:") + logger.debug("gitBranch : $branch") + System.setProperty("gitBranch", branch) + logger.debug("gitParentBranch : $parentBranch") + System.setProperty("gitParentBranch", parentBranch) + logger.debug("gitHighestTagHash : $closestHighestTagHash") + System.setProperty("gitHighestTagHash", closestHighestTagHash) + logger.debug("gitHighestTag : $closestTag") + System.setProperty("gitHighestTag", closestTag) + logger.debug("gitCurrentShortCommitHash : $currentShortCommitHash") + System.setProperty("gitCurrentShortCommitHash", currentShortCommitHash) + logger.debug("gitCurrentCommitHash : $currentCommitHash") + System.setProperty("gitCurrentCommitHash", currentCommitHash) + logger.debug("mavenVersion : $mavenVersion") + System.setProperty("mavenVersion", mavenVersion) + logger.debug("appVersion : $appVersion") + System.setProperty("appVersion", appVersion) + logger.debug("gitPaddedVersionCount : $gitPaddedVersionCount") + if (gitPaddedVersionCount != null) { + System.setProperty("gitPaddedVersionCount", gitPaddedVersionCount) + } + logger.debug("gitDescribe : $gitDescribe") + System.setProperty("gitDescribe", gitDescribe) + logger.debug("gitAppDescribe : $gitAppDescribe") + System.setProperty("gitAppDescribe", gitAppDescribe) + logger.debug("versionSnapshot : $snapshot") + System.setProperty("versionSnapshot", "" + snapshot) + logger.debug("project.version : $mavenVersion") + if (mavenVersion != null) { + project.version = mavenVersion!! + } + } + + private fun findCurrentCommitShortHash() { + logger.debug("findCurrentCommitShortHash") + currentShortCommitHash = execGitCommand("git", "rev-parse", "--short", "HEAD") + if (currentShortCommitHash.isNullOrEmpty()) { + currentShortCommitHash = "0" + } + logger.debug("Found currentShortCommitHash: $currentShortCommitHash") + } + + private fun findCurrentCommitHash() { + logger.debug("findCurrentCommitHash") + currentCommitHash = execGitCommand("git", "rev-parse", "HEAD") + if (currentCommitHash.isNullOrEmpty()) { + currentCommitHash = "NoHashFound" + } + logger.debug("Found currentCommitHash: $currentCommitHash") + } + + private fun findBranch() { + logger.debug("findBranch") + branch = execGitCommand("git", "rev-parse", "--abbrev-ref", "HEAD") + branch = branch?.replace("[^\\dA-Za-z ]".toRegex(), "_") + parentBranch = branch + logger.debug("Found branch: $branch") + } + + private fun findClosestTagHash() { + logger.debug("findClosestTagHash") + var branchToFindTag = branch + if (parentBranch != branch) { + branchToFindTag = parentBranch + } + logger.debug("branchToFindTag : $branchToFindTag") + if (branchToFindTag == "main") { + val tag = findGitHighestTag() + closestHighestTagHash = execGitCommand("git", "log", "-1", "--format=format:%H", tag) + closestTag = tag + } else if (branchToFindTag != null) { + if (branchToFindTag.startsWith("bugfix_")) { + val version = highestVersionNumber(branchToFindTag) + this.closestHighestTagHash = execGitCommand("git", "rev-list", "-n", "1", version) + } else if (branchToFindTag == "HEAD") { + closestHighestTagHash = currentCommitHash + findGitClosestTag() + if ( + closestTag!!.contains("-") && + !closestTag!!.contains("-RC") && + !closestTag!!.contains("-M") + ) { + val tag = closestTag!!.substring(0, closestTag!!.indexOf("-")) + this.closestHighestTagHash = execGitCommand("git", "rev-list", "-n", "1", tag) + } + } else { + logger.debug("findClosestTagHash else ") + val tag = findGitHighestTag() + this.closestHighestTagHash = + execGitCommand("git", "log", "-1", "--format=format:%H", tag) + this.closestTag = tag + } + } + if (closestHighestTagHash == null || closestHighestTagHash!!.isEmpty()) { + this.closestHighestTagHash = "0" + } + logger.debug("Found closestHighestTagHash: $closestHighestTagHash") + } + + private fun highestVersionNumber(branch: String): String { + logger.debug("highestVersionNumber for branch: $branch") + val extractedVersion = branch.replace("bugfix_", "") + .replace("_", ".") + val outputString = execGitCommand( + "git", "tag", "-l", + "$extractedVersion*", "--sort=v:refname" + ) + val hashes: Array + var version = "0.0.0" + if (outputString!!.contains("\n")) { + hashes = outputString.split("\n").dropLastWhile { + it.isEmpty() + }.toTypedArray() + for (item in hashes) { + if (item.matches("[0-9|.|a-z|R|C|M|-]*".toRegex())) { + if ( + version.isEmpty() || + !(item.startsWith(version) && (item.contains("RC") || + item.contains("M"))) + ) { + version = item + } + } + } + } else { + version = outputString + } + logger.debug("highestVersionNumber for branch: $branch = $version") + return version + } + + private fun findGitHighestTag(): String { + logger.debug("findGitHighestTag") + val outputString = execGitCommand("git", "tag", "-l", "--sort=v:refname") + if (outputString.isNullOrEmpty()) return "0.0.0" + val hashes = if (outputString.contains("\n")) { + outputString.split("\n").dropLastWhile { + it.isEmpty() + }.toTypedArray() + } else { + arrayOf(outputString) + } + var closestTag = "" + for (item in hashes) { + if (item.matches("[0-9|.|a-z|R|C|M|-]*".toRegex())) { + if ( + closestTag.isEmpty() || + !(item.startsWith(closestTag) && (item.contains("RC") || + item.contains("M"))) + ) { + closestTag = item + } + } + } + logger.debug("findGitHighestTag : $closestTag") + return closestTag + } + + private fun findGitClosestTag() { + logger.debug("findGitClosestTag") + closestTag = execGitCommand("git", "describe", "--tags", closestHighestTagHash!!) + if (closestTag.isNullOrEmpty()) closestTag = "0.0.0" + branch = branch ?: "main" + if (branch!!.startsWith("bugfix_") && closestTag == "0.0.0") { + val extractedVersion = branch!!.replace("bugfix_", "") + .replace("_", ".") + closestTag = "$extractedVersion.0" + } + logger.debug("Found ClosestTag: $closestTag") + } + + private fun findVersion() { + logger.debug("findVersion") + val closestTag = closestTag + var gitBranch = branch + val versionSplit = Pattern.compile("([0-9]+).([0-9]+).([0-9]+).*") + val matcher = versionSplit.matcher(closestTag.toString()) + if (closestHighestTagHash == currentCommitHash) { + mavenVersion = closestTag + if (matcher.find()) { + val major = matcher.group(1) + val minor = matcher.group(2).toLong().let { String.format("%02d", it) } + val bugfix = matcher.group(3).toLong().let { String.format("%02d", it) } + gitPaddedVersionCount = major + minor + bugfix + } + snapshot = false + if (isProjectDirty()) { + mavenVersion += "-dirty" + } + } else { + if (matcher.find()) { + var major = matcher.group(1) + var minor = matcher.group(2) + var bugfix = matcher.group(3) + var branchToFindVersion = branch + if (parentBranch != branch) { + branchToFindVersion = parentBranch + } + if (gitBranch == null) { + mavenVersion = "0.0.0-SNAPSHOT" + branch = "unknown" + return + } + if (gitBranch == "main") { + if (closestTag!!.contains("-M")) { + minor = "0" + bugfix = "0.0-SNAPSHOT" + } else { + major = (major.toLong() + 1).toString() + minor = "0" + bugfix = "0-SNAPSHOT" + } + } else if (gitBranch.startsWith("bugfix")) { + if ((closestHighestTagHash == "0" && minor == "0") || closestTag!!.contains("-RC") || closestTag.contains( + "-M" + ) + ) { + minor = "0" + bugfix = "$bugfix-SNAPSHOT" + } else { + minor = (minor.toLong() + 1).toString() + bugfix = "0-SNAPSHOT" + } + } else { + var startIdx = 0 + val endIdx = 11 + if (gitBranch == null) { + gitBranch = "-UNKNOWN" + } else if (gitBranch.length >= endIdx) { + if (gitBranch.startsWith("SPRINT-")) { + startIdx = 7 + } + gitBranch = "-" + gitBranch.substring(startIdx, endIdx) + } else if (gitBranch == "HEAD") { + gitBranch = "" + } else { + gitBranch = "-" + gitBranch.substring(startIdx, gitBranch.length) + } + if (parentBranch != branch && parentBranch!!.startsWith("bugfix")) { + bugfix = (bugfix.toLong() + 1).toString() + gitBranch + "-SNAPSHOT" + } else if (gitBranch.startsWith("-") && closestTag!!.contains("-M")) { + bugfix = "0$gitBranch-SNAPSHOT" + } else { + minor = (minor.toLong() + 1).toString() + bugfix = "0$gitBranch-SNAPSHOT" + } + } + var bugfixExtracted = "0" + if (bugfix.indexOf("-") > 0) { + bugfixExtracted = bugfix.substring(0, bugfix.indexOf("-")) + } else if (bugfix.matches("\\d+".toRegex())) { + bugfixExtracted = bugfix + } + gitPaddedVersionCount = major + String.format("%02d", minor.toLong()) + String.format("%02d", bugfixExtracted.toLong()) + mavenVersion = "$major.$minor.$bugfix" + if (isProjectDirty()) { + mavenVersion += "-dirty" + } + } + } + if (mavenVersion == closestTag && branch == "HEAD") { + branch = mavenVersion + } + logger.debug("Found mavenVersion: $mavenVersion") + logger.debug("Found gitPaddedVersionCount: $gitPaddedVersionCount") + } + + private fun findGitDescribeVersion() { + logger.debug("findGitDescribeVersion") + gitDescribe = if (currentCommitHash == closestHighestTagHash) { + closestTag + } else { + "$mavenVersion-$currentShortCommitHash" + } + logger.debug("found gitDescribe: $gitDescribe") + } + + private fun findGitAppDescribeVersion() { + logger.debug("findGitAppDescribeVersion") + gitAppDescribe = if (currentCommitHash == closestHighestTagHash) closestTag + else gitDescribe!!.replace("-SNAPSHOT", "") + appVersion = mavenVersion!!.replace("-SNAPSHOT", "") + logger.debug("found gitAppDescribe: $gitAppDescribe") + } + + private fun compareVersions(v1: String, v2: String): Int { + if (v1.isNotEmpty() && v2.isEmpty()) return -1 + if (v1.isEmpty() && v2.isEmpty()) return 0 + if (v1.isEmpty() && v2.isNotEmpty()) return 1 + val pos1 = v1.indexOf('.') + val pos2 = v2.indexOf('.') + val num1 = (if (pos1 > 0) v1.substring(0, pos1).toInt() else 0) + val num2 = (if (pos2 > 0) v2.substring(0, pos2).toInt() else 0) + if (num1 !== num2) return num1.compareTo(num2) + val tail1 = (if (pos1 > 0) v1.substring(pos1 + 1) else "") + val tail2 = (if (pos2 > 0) v2.substring(pos2 + 1) else "") + return compareVersions(tail1, tail2) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/_24i/VersionManagerPlugin.kt b/src/main/kotlin/com/_24i/VersionManagerPlugin.kt new file mode 100644 index 0000000..a59c8ae --- /dev/null +++ b/src/main/kotlin/com/_24i/VersionManagerPlugin.kt @@ -0,0 +1,83 @@ +package com._24i + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.Task + +class VersionManagerPlugin : Plugin { + companion object { + const val TASK_GROUP = "24i" + const val TASK_VERSION_NAME = "version" + const val TASK_VERSION_DESCRIPTION = "Versioning task" + const val TASK_SHOW_VERSION_NAME = "showVersion" + const val TASK_SHOW_VERSION_DESCRIPTION = "Show the project version" + const val TASK_FIND_VERSION_NAME = "findVersion" + const val TASK_FIND_VERSION_DESCRIPTION = "Find the version from git system" + const val TASK_PRINT_VERSION_NAME = "printVersion" + const val TASK_PRINT_VERSION_DESCRIPTION = "Print the version from git system" + } + + override fun apply(target: Project) { + with(target) { + // create main task + val mainTask = tasks.register( + TASK_VERSION_NAME, + TaskGitVersion::class.java + ).apply { + group = TASK_GROUP + description = TASK_VERSION_DESCRIPTION + } + + // all tasks in project depends on main task + allprojects.forEach { proj: Project -> + if (proj.name != "buildSrc") { + proj.tasks.forEach { task: Task -> + if (task != mainTask) { + logger.debug("Task ${task.name} depends on ${mainTask.name}.") + task.dependsOn(mainTask) + } + } + } + } + + // create show version task + task(TASK_SHOW_VERSION_NAME) { + group = TASK_GROUP + description = TASK_SHOW_VERSION_DESCRIPTION + doLast { + println("Version (project.version): " + project.version) + println("Branch (System.properties.gitBranch): " + System.getProperty("gitBranch")) + println("Parent Branch (System.properties.gitParentBranch): " + System.getProperty("gitParentBranch")) + println("Highest tag hash (System.properties.gitHighestTagHash): " + System.getProperty("gitHighestTagHash")) + println("Highest tag (System.properties.gitHighestTag): " + System.getProperty("gitHighestTag")) + println("Highest tag count (System.properties.gitHighestTagCount): " + System.getProperty("gitHighestTagCount")) + println("Current commit short hash (System.properties.gitCurrentShortCommitHash): " + System.getProperty("gitCurrentShortCommitHash")) + println("Current commit hash (System.properties.gitCurrentCommitHash): " + System.getProperty("gitCurrentCommitHash")) + println("Derived values based on above information: ") + println("Use in maven version and gradle version (System.properties.mavenVersion): " + System.getProperty("mavenVersion")) + println("Use in app version (System.properties.appVersion): " + System.getProperty("appVersion")) + println("Use as part of artifact name (System.properties.gitDescribe): " + System.getProperty("gitDescribe")) + println("Use as part of artifact name (System.properties.gitAppDescribe): " + System.getProperty("gitAppDescribe")) + println("Use as versionGitNumber (System.properties.gitPaddedVersionCount): " + System.getProperty("gitPaddedVersionCount")) + println("Use as part of artifact name (System.properties.versionSnapshot): " + System.getProperty("versionSnapshot")) + } + } + + // create find version task + task(TASK_FIND_VERSION_NAME) { + group = TASK_GROUP + description = TASK_FIND_VERSION_DESCRIPTION + // todo : not implemented in previous source + } + + // create print version task + task(TASK_PRINT_VERSION_NAME) { + group = TASK_GROUP + description = TASK_PRINT_VERSION_DESCRIPTION + doLast { + println("Version (project.version): " + project.version) + } + } + } + } +} \ No newline at end of file diff --git a/src/test/groovy/com/_24i/VersionManagerPluginTest.groovy b/src/test/groovy/com/_24i/VersionManagerPluginTest.groovy deleted file mode 100644 index 801d4f9..0000000 --- a/src/test/groovy/com/_24i/VersionManagerPluginTest.groovy +++ /dev/null @@ -1,16 +0,0 @@ -package com._24i - -import org.junit.Test -import org.gradle.testfixtures.ProjectBuilder -import org.gradle.api.Project -import static org.junit.Assert.* - -class VersionManagerPluginTest { - @Test - public void findVersionPluginAddsFindVersionTaskToProject() { - Project project = ProjectBuilder.builder().build() - project.apply plugin: 'com.24i.gitVersion' - - assertTrue(project.tasks.version instanceof VersionManagerTask) - } -} diff --git a/src/test/groovy/com/_24i/VersionManagerTaskTest.groovy b/src/test/groovy/com/_24i/VersionManagerTaskTest.groovy deleted file mode 100644 index 47dcfd3..0000000 --- a/src/test/groovy/com/_24i/VersionManagerTaskTest.groovy +++ /dev/null @@ -1,15 +0,0 @@ -package com._24i - -import org.junit.Test -import org.gradle.testfixtures.ProjectBuilder -import org.gradle.api.Project -import static org.junit.Assert.* - -class VersionManagerTaskTest { - @Test - public void canAddTaskToProject() { - Project project = ProjectBuilder.builder().build() - def task = project.task('testTask', type: VersionManagerTask) - assertTrue(task instanceof VersionManagerTask) - } -} diff --git a/src/test/kotlin/com/_24i/PluginTest.kt b/src/test/kotlin/com/_24i/PluginTest.kt new file mode 100644 index 0000000..77c868f --- /dev/null +++ b/src/test/kotlin/com/_24i/PluginTest.kt @@ -0,0 +1,22 @@ +package com._24i + +import org.gradle.api.Project +import org.gradle.internal.impldep.org.junit.Assert +import org.gradle.testfixtures.ProjectBuilder +import org.junit.Test + +class PluginTest { + + companion object { + private const val TASK_NAME = "version" + private const val PLUGIN_ID_GIT_VERSION = "com.24i.gitVersion" + } + + @Test + fun testGitVersion() { + val project: Project = ProjectBuilder.builder().build() + project.plugins.apply(PLUGIN_ID_GIT_VERSION) + val hasTask = project.tasks.findByName(TASK_NAME) != null + assert(hasTask, { "No task $TASK_NAME found." }) + } +} \ No newline at end of file