75 lines
3.2 KiB
Kotlin
75 lines
3.2 KiB
Kotlin
package io.gitlab.jfronny.scripts
|
|
|
|
data class SemanticVersion(val major: Int, val minor: Int, val patch: Int, val type: VersionType, val build: String?): Comparable<SemanticVersion> {
|
|
init {
|
|
require(build == null || buildPattern.matches(build)) { "Illegal build string" }
|
|
}
|
|
|
|
override fun compareTo(other: SemanticVersion): Int =
|
|
when {
|
|
major > other.major -> 1
|
|
major < other.major -> -1
|
|
minor > other.minor -> 1
|
|
minor < other.minor -> -1
|
|
patch > other.patch -> 1
|
|
patch < other.patch -> -1
|
|
else -> when {
|
|
type != other.type -> type.compareTo(other.type)
|
|
build == null && other.build != null -> -1
|
|
build != null && other.build == null -> 1
|
|
build != null && other.build != null -> build.compareTo(other.build)
|
|
else -> 0
|
|
}
|
|
}
|
|
|
|
override fun toString(): String {
|
|
return "$major.$minor.$patch" + when (type) {
|
|
VersionType.RELEASE -> ""
|
|
else -> "-${type.semanticName}"
|
|
} + if (build == null) "" else "+$build"
|
|
}
|
|
|
|
fun unclassifiedToString(): String {
|
|
return "$major.$minor.$patch" + if (build == null) "" else "+$build"
|
|
}
|
|
|
|
fun incrementBy(commitType: CommitType, versionType: VersionType = VersionType.RELEASE, build: String? = null): SemanticVersion = when(commitType) {
|
|
CommitType.FIX -> SemanticVersion(major, minor, patch + 1, versionType, build)
|
|
CommitType.FEAT -> SemanticVersion(major, minor + 1, 0, versionType, build)
|
|
CommitType.BREAKING -> SemanticVersion(major + 1, 0, 0, versionType, build)
|
|
}
|
|
|
|
fun withType(versionType: VersionType) = SemanticVersion(major, minor, patch, versionType, build)
|
|
|
|
companion object {
|
|
private val identifier = Regex("[a-zA-Z1-9][a-zA-Z0-9]*")
|
|
private val buildPattern = Regex("$identifier(?:\\.$identifier)+")
|
|
private val number = Regex("[1-9][0-9]*|0")
|
|
private val versionCore = Regex("($number)\\.($number)\\.($number)")
|
|
private val legacyVersion = Regex("([vba]|rc)$versionCore(\\+$buildPattern)?")
|
|
private val restrictedSemver = Regex("$versionCore(-(?:alpha|beta|rc))?(\\+$buildPattern)?")
|
|
|
|
fun parse(source: String): SemanticVersion {
|
|
val legacyMatch = legacyVersion.matchEntire(source)
|
|
if (legacyMatch != null) {
|
|
val m = legacyMatch.groupValues
|
|
return SemanticVersion(
|
|
m[2].toInt(), m[3].toInt(), m[4].toInt(),
|
|
VersionType.byShorthand(m[1])!!,
|
|
m[5].ifEmpty { null }
|
|
)
|
|
}
|
|
val semverMatch = restrictedSemver.matchEntire(source)
|
|
if (semverMatch != null) {
|
|
val m = semverMatch.groupValues
|
|
return SemanticVersion(
|
|
m[1].toInt(), m[2].toInt(), m[3].toInt(),
|
|
VersionType.byName(m[4].ifEmpty { "release" })!!,
|
|
m[5].ifEmpty { null }
|
|
)
|
|
}
|
|
throw IllegalArgumentException("Source does not match supported version patterns: $source")
|
|
}
|
|
}
|
|
}
|