Skip to content

Commit

Permalink
Updated versioning to provide VersionCode instead of integer
Browse files Browse the repository at this point in the history
That way comparisons through semver are possible to the point where all digits are actually in the constraints of java integers
  • Loading branch information
diareuse committed May 5, 2021
1 parent fca8145 commit 589cde4
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 16 deletions.
4 changes: 4 additions & 0 deletions src/main/kotlin/dev/chainmail/taggy/Helper.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package dev.chainmail.taggy

val characters = Regex("[a-zA-Z]+")
val numbers = Regex("[0-9]+")
19 changes: 3 additions & 16 deletions src/main/kotlin/dev/chainmail/taggy/pattern/Tag.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package dev.chainmail.taggy.pattern

import kotlin.math.abs
import kotlin.math.log10
import dev.chainmail.taggy.characters
import dev.chainmail.taggy.numbers

@Suppress("DataClassPrivateConstructor")
data class Tag(
Expand All @@ -10,17 +10,7 @@ data class Tag(
val separator: String
) {

val code: Int = name.splitToSequence('.')
.map { it.replace(characters, "").toInt() }
.reduce { acc, it ->
val multiplier = when (it) {
// just multiply the acc value by 10
0 -> 1.0
// calculate number of digits in this number and multiply it by 10
else -> log10(abs(it).toDouble()) + 1
}.toInt() * 10
acc * multiplier + it
}
val code = VersionCode(name, postfix)

fun postfixHasNumbers() = postfix?.contains(numbers) == true

Expand Down Expand Up @@ -71,9 +61,6 @@ data class Tag(

companion object {

private val characters = Regex("[a-zA-Z]+")
private val numbers = Regex("[0-9]+")

fun from(tag: String, postfix: String?, separator: String): Tag {
if (
tag.contains(separator) &&
Expand Down
53 changes: 53 additions & 0 deletions src/main/kotlin/dev/chainmail/taggy/pattern/VersionCode.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package dev.chainmail.taggy.pattern

import dev.chainmail.taggy.characters
import kotlin.math.max

class VersionCode(
version: String,
postfix: String?
) : Comparable<VersionCode> {

private val segments = version.splitToSequence(".")
.map { it.replace(characters, "").toInt() }
.toList()

private val revision = postfix
?.replace(characters, "")
?.toIntOrNull()

override operator fun compareTo(other: VersionCode): Int {
if (this === other) {
return 0
}

val segmentCount = max(
segments.size,
other.segments.size
)

// loop through all the segments to establish which of these versions is higher
for (i in 0 until segmentCount) {
val my = segments.getOrElse(i) { 0 }
val their = other.segments.getOrElse(i) { 0 }

return when {
my > their -> 1
my < their -> -1
else -> continue
}
}

// if the versions are identical, then we check for revisions
val my = revision ?: Int.MAX_VALUE
val their = other.revision ?: Int.MAX_VALUE

return my - their
}

override fun equals(other: Any?): Boolean {
if (other !is VersionCode) return false
return compareTo(other) == 0
}

}
71 changes: 71 additions & 0 deletions src/test/kotlin/dev/chainmail/taggy/pattern/VersionCodeTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package dev.chainmail.taggy.pattern

import org.junit.Test
import kotlin.test.assertTrue

class VersionCodeTest {

private fun testComparison(
old: String,
new: String,
postfix: String? = null,
separator: String = "-"
) {
val contenderOld = Tag.from(old, postfix, separator)
val contenderNew = Tag.from(new, postfix, separator)
assertTrue("Codes do not properly handle semantic versioning. $new is newer than $old") {
contenderNew.code > contenderOld.code
}
}

@Test
fun semanticComparison() {
testComparison(old = "1.193.0", new = "2.0.0")
}

@Test
fun semanticUnilateralPostfixComparison() {
testComparison(old = "1.193.0-dev1", new = "1.193.0", postfix = "dev")
}

@Test
fun semanticBilateralPostfixComparison() {
testComparison(old = "1.193.0-dev1", new = "1.193.0-dev2", postfix = "dev")
}

@Test
fun semanticUnilateralStagePostfixComparison() {
testComparison(old = "1.193.0", new = "1.193.1-dev1", postfix = "dev")
}

// ---

private fun testEquality(
old: String,
new: String,
postfix: String? = null,
separator: String = "-"
) {
val contenderOld = Tag.from(old, postfix, separator)
val contenderNew = Tag.from(new, postfix, separator)
assertTrue("Codes do not properly handle semantic versioning. $new is not equal to $old") {
contenderNew.code == contenderOld.code
}
}

@Test
fun semanticEquality() {
testEquality(old = "1.0.0", new = "1.0.0")
}

@Test(expected = AssertionError::class)
fun semanticFailUnilateralPostfixEquality() {
testEquality(old = "1.0.0-dev30", new = "1.0.0", postfix = "dev")
}

@Test(expected = AssertionError::class)
fun semanticFailBilateralPostfixEquality() {
testEquality(old = "1.0.0-dev1", new = "1.0.0-dev2", postfix = "dev")
}

}
Empty file.

0 comments on commit 589cde4

Please sign in to comment.