Skip to content

Commit eeab899

Browse files
author
Joel Mongård
committed
feat: Added possibility to configure a custom build metadata separtor (#80)
1 parent aa072cd commit eeab899

File tree

5 files changed

+114
-34
lines changed

5 files changed

+114
-34
lines changed

src/main/kotlin/git/semver/plugin/gradle/GitSemverPluginExtension.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ abstract class GitSemverPluginExtension(project: Project, providerFactory: Provi
104104
/**
105105
* The semantic version for the project with commit info excluding sha as a string e.g. "1.2.3-Alpha.4+005"
106106
*/
107-
val infoVersion: String by lazy { semVersion.toInfoVersionString() }
107+
val infoVersion: String by lazy { semVersion.toInfoVersionString(metaSeparator = metaSeparator) }
108108

109109
/**
110110
* The semantic version for the project e.g. 1.2.3-Alpha.4

src/main/kotlin/git/semver/plugin/scm/GitProvider.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ internal class GitProvider(private val settings: SemverSettings) {
7070
getHeadCommit(it.repository),
7171
params.preRelease?.trimStart('-')
7272
)
73-
val versionString = version.toInfoVersionString()
73+
val versionString = version.toInfoVersionString(metaSeparator = settings.metaSeparator)
7474
logger.info("Saving new version: {}", versionString)
7575

7676
val isCommit = isFormatEnabled(params.commit, settings.releaseCommitTextFormat)

src/main/kotlin/git/semver/plugin/semver/BaseSettings.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@ abstract class BaseSettings(
1313
var groupVersionIncrements: Boolean = true,
1414
var noDirtyCheck: Boolean = false,
1515
var noAutoBump: Boolean = false,
16-
var gitSigning: Boolean? = null // null means use the jgit default
16+
var gitSigning: Boolean? = null, // null means use the jgit default
17+
var metaSeparator: Char = '+'
1718
) : Serializable {
1819
constructor(settings: BaseSettings) : this(
1920
settings.defaultPreRelease, settings.releasePattern, settings.patchPattern, settings.minorPattern,
2021
settings.majorPattern, settings.releaseCommitTextFormat, settings.releaseTagNameFormat,
21-
settings.groupVersionIncrements, settings.noDirtyCheck, settings.noAutoBump
22+
settings.groupVersionIncrements, settings.noDirtyCheck, settings.noAutoBump,
23+
settings.gitSigning, settings.metaSeparator
2224
)
2325
}

src/main/kotlin/git/semver/plugin/semver/SemInfoVersion.kt

Lines changed: 102 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@ package git.semver.plugin.semver
22

33
import java.io.Serializable
44

5+
/**
6+
* Extended semantic version information that includes Git metadata and commit details.
7+
*
8+
* Provides version information with additional context such as commit SHA, commit count
9+
* since the last version, and the previous semantic version for enhanced versioning workflows.
10+
*
11+
* @property sha The current Git commit SHA hash
12+
* @property major The major version number
13+
* @property minor The minor version number
14+
* @property patch The patch version number
15+
* @property preRelease The pre-release version information
16+
* @property commitCount The number of commits since the previous version
17+
* @property previousVersion The previous semantic version
18+
*/
519
data class SemInfoVersion(
620
val sha: String,
721
override val major: Int,
@@ -11,50 +25,108 @@ data class SemInfoVersion(
1125
val commitCount: Int,
1226
val previousVersion: SemVersion
1327
) : Serializable, Version {
14-
fun toSemVersion() : SemVersion {
28+
/**
29+
* Converts this extended version information to a standard semantic version.
30+
*
31+
* @return A SemVersion containing only the core version components
32+
*/
33+
fun toSemVersion(): SemVersion {
1534
return SemVersion(major, minor, patch, preRelease)
1635
}
1736

18-
fun toVersionString(v2: Boolean = true): String {
19-
return toInfoVersionString("", 0, v2)
20-
}
21-
37+
/**
38+
* Converts to a detailed version string with customizable formatting options.
39+
*
40+
* @param commitCountStringFormat Format string for commit count (default: "%03d")
41+
* @param shaLength Length of SHA to include, 0 to exclude (default: 0)
42+
* @param v2 Whether to use v2 formatting (default: true)
43+
* @param appendPreReleaseLast Whether to append pre-release info at the end (default: false)
44+
* @param metaSeparator Character to separate metadata components (default: '+')
45+
* @return The formatted version string with metadata
46+
*/
2247
fun toInfoVersionString(
2348
commitCountStringFormat: String = "%03d",
2449
shaLength: Int = 0,
2550
v2: Boolean = true,
26-
appendPreReleaseLast: Boolean = false
51+
appendPreReleaseLast: Boolean = false,
52+
metaSeparator: Char = '+'
2753
): String {
28-
val builder = StringBuilder().append(major).append('.').append(minor).append('.').append(patch)
29-
if (v2) {
30-
if (isPreRelease && !appendPreReleaseLast) {
31-
builder.append('-').append(preRelease)
32-
}
33-
var metaSeparator = '+'
34-
if (this.commitCount > 0 && commitCountStringFormat.isNotEmpty()) {
35-
builder.append(metaSeparator).append(commitCountStringFormat.format(this.commitCount))
36-
metaSeparator = '.'
37-
}
38-
val shaTake = sha.take(shaLength)
39-
if (shaTake.isNotEmpty()) {
40-
builder.append(metaSeparator).append("sha.").append(shaTake)
41-
}
42-
if (isPreRelease && appendPreReleaseLast) {
43-
builder.append('-').append(preRelease)
44-
}
45-
} else if (isPreRelease) {
46-
builder.append("-")
47-
.append(preRelease.prefix.replace("[^0-9A-Za-z-]".toRegex(), ""))
48-
.append(preRelease.number ?: "")
54+
if (!v2) {
55+
return toVersionString(false);
4956
}
50-
return builder.toString()
57+
if (appendPreReleaseLast) {
58+
return VersionBuilder()
59+
.appendBuildMetadata(commitCountStringFormat, shaLength, metaSeparator)
60+
.appendPrerelease()
61+
.toString();
62+
}
63+
return VersionBuilder()
64+
.appendPrerelease()
65+
.appendBuildMetadata(commitCountStringFormat, shaLength, metaSeparator)
66+
.toString();
5167
}
5268

53-
override fun toString(): String {
54-
return toInfoVersionString(shaLength = 7)
69+
/**
70+
* Converts to a version string using default formatting.
71+
*
72+
* @param v2 Whether to use v2 formatting (default: true)
73+
* @return The formatted version string
74+
*/
75+
fun toVersionString(v2: Boolean = true): String {
76+
return VersionBuilder().appendPrerelease(v2).toString();
5577
}
5678

79+
/**
80+
* Returns a string representation with a 7-character SHA.
81+
*
82+
* @return The version string including SHA metadata
83+
*/
84+
override fun toString(): String = toInfoVersionString(shaLength = 7)
85+
86+
/**
87+
* Generates a revision string in the format "major.minor.patch.commitCount".
88+
*
89+
* @return The revision string based on the previous version and commit count
90+
*/
5791
fun revisionString(): String {
5892
return "${previousVersion.major}.${previousVersion.minor}.${previousVersion.patch}.$commitCount"
5993
}
94+
95+
private inner class VersionBuilder() {
96+
private val builder: StringBuilder = StringBuilder()
97+
.append(major).append('.').append(minor).append('.').append(patch)
98+
99+
fun appendPrerelease(v2: Boolean = true): VersionBuilder {
100+
if (isPreRelease) {
101+
if (v2) {
102+
builder.append('-').append(preRelease)
103+
} else {
104+
builder.append("-")
105+
.append(preRelease.prefix.replace("[^0-9A-Za-z-]".toRegex(), ""))
106+
.append(preRelease.number ?: "")
107+
}
108+
}
109+
return this
110+
}
111+
112+
fun appendBuildMetadata(
113+
commitCountStringFormat: String,
114+
shaLength: Int,
115+
metaSeparator: Char
116+
): VersionBuilder {
117+
var currentMetaSeparator = metaSeparator
118+
if (commitCount > 0 && commitCountStringFormat.isNotEmpty()) {
119+
val commitCountStr = commitCountStringFormat.format(commitCount)
120+
builder.append(currentMetaSeparator).append(commitCountStr)
121+
currentMetaSeparator = '.'
122+
}
123+
val shaTake = sha.take(shaLength)
124+
if (shaTake.isNotEmpty()) {
125+
builder.append(currentMetaSeparator).append("sha.").append(shaTake)
126+
}
127+
return this
128+
}
129+
130+
override fun toString(): String = builder.toString()
131+
}
60132
}

src/test/kotlin/git/semver/plugin/semver/MutableSemVersionTest.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,4 +124,10 @@ class MutableSemVersionTest {
124124
.isEqualTo("1.2.3+sha.8727a3e-SNAPSHOT")
125125
}
126126

127+
@Test
128+
fun toInfoVersionString_customMetaSeparator() {
129+
val version = MutableSemVersion.tryParse(Tag("1.2.3-SNAPSHOT", SHA))
130+
assertThat(version?.toSemInfoVersion()?.toInfoVersionString(shaLength = 7, metaSeparator = '#'))
131+
.isEqualTo("1.2.3-SNAPSHOT#sha.8727a3e")
132+
}
127133
}

0 commit comments

Comments
 (0)