From 07c09ec3e9cb0eb5fdfa00adbd1865ea29d1e1f4 Mon Sep 17 00:00:00 2001 From: atsunatsu Date: Mon, 7 Sep 2026 06:11:31 +0800 Subject: [PATCH] fix: VersionComparator parses multi-level suffixes (4.4.6-ba7opf.9.1) by comparing all numeric segments, not just the last one --- .../core/domain/utility/VersionComparator.kt | 30 +++++++++++-------- .../core/domain/VersionComparatorTest.kt | 18 ++++++++--- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/utility/VersionComparator.kt b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/utility/VersionComparator.kt index c3f001f9..de33d668 100644 --- a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/utility/VersionComparator.kt +++ b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/utility/VersionComparator.kt @@ -2,11 +2,12 @@ package com.rtbishop.look4sat.core.domain.utility /** * Compares two version strings of the form "..[-]" used by the - * BA7OPF fork releases (e.g. "4.4.6-ba7opf.6" or "v4.4.6-ba7opf.7"). + * BA7OPF fork releases (e.g. "4.4.6-ba7opf.6" or "v4.4.6-ba7opf.9.1"). * * The comparison is done on the numeric version segments first; when the base versions are - * equal, the trailing build number (if any) decides. This lets a "4.4.6-ba7opf.7" release be - * detected as newer than "4.4.6-ba7opf.6" while "4.5.0" trumps any "4.4.x" build. + * equal, the trailing build numbers of the suffix decide. All numeric segments of the suffix + * are compared as a sequence, so multi-level suffixes work correctly: + * "4.4.6-ba7opf.9.1" > "4.4.6-ba7opf.9" > "4.4.6-ba7opf.8". */ object VersionComparator { @@ -20,25 +21,28 @@ object VersionComparator { val k = curr.first.getOrElse(i) { 0 } if (c != k) return c > k } - return cand.second > curr.second + val maxBuild = maxOf(cand.second.size, curr.second.size) + for (i in 0 until maxBuild) { + val c = cand.second.getOrElse(i) { 0 } + val k = curr.second.getOrElse(i) { 0 } + if (c != k) return c > k + } + return false } /** - * Parses a version string into (numeric base segments, trailing build number). - * "v4.4.6-ba7opf.7" -> ([4,4,6], 7); "4.4.6" -> ([4,4,6], 0); "4.4.6-ba7opf" -> ([4,4,6], 0). + * Parses a version string into (numeric base segments, numeric suffix segments). + * "v4.4.6-ba7opf.9.1" -> ([4,4,6], [9,1]); "4.4.6-ba7opf.8" -> ([4,4,6], [8]); + * "4.4.6" -> ([4,4,6], []); "4.4.6-ba7opf" -> ([4,4,6], []). */ - fun parse(version: String): Pair, Int> { + fun parse(version: String): Pair, List> { val cleaned = version.trim().removePrefix("v") val dashIndex = cleaned.indexOf('-') val basePart = if (dashIndex >= 0) cleaned.substring(0, dashIndex) else cleaned val suffixPart = if (dashIndex >= 0) cleaned.substring(dashIndex + 1) else "" val base = basePart.split('.').mapNotNull { it.toIntOrNull() } - // The build number is the trailing numeric segment of the suffix (e.g. "ba7opf.7" -> 7). - val build = suffixPart - .split('.') - .lastOrNull() - ?.toIntOrNull() - ?: 0 + // All numeric segments of the suffix, in order (e.g. "ba7opf.9.1" -> [9, 1]). + val build = suffixPart.split('.').mapNotNull { it.toIntOrNull() } return base to build } } diff --git a/core/domain/src/test/java/com/rtbishop/look4sat/core/domain/VersionComparatorTest.kt b/core/domain/src/test/java/com/rtbishop/look4sat/core/domain/VersionComparatorTest.kt index b3bb3996..48e7aa55 100644 --- a/core/domain/src/test/java/com/rtbishop/look4sat/core/domain/VersionComparatorTest.kt +++ b/core/domain/src/test/java/com/rtbishop/look4sat/core/domain/VersionComparatorTest.kt @@ -40,9 +40,19 @@ class VersionComparatorTest { } @Test - fun `parse extracts base and build number`() { - assertEquals(listOf(4, 4, 6) to 7, VersionComparator.parse("v4.4.6-ba7opf.7")) - assertEquals(listOf(4, 4, 6) to 0, VersionComparator.parse("4.4.6")) - assertEquals(listOf(4, 4, 6) to 0, VersionComparator.parse("4.4.6-ba7opf")) + fun `multi level suffixes compare correctly`() { + // The .9.1 hotfix case that exposed the old single-build-number logic. + assertTrue(VersionComparator.isNewer("4.4.6-ba7opf.9.1", "4.4.6-ba7opf.9")) + assertTrue(VersionComparator.isNewer("v4.4.6-ba7opf.9.1", "4.4.6-ba7opf.8")) + assertFalse(VersionComparator.isNewer("4.4.6-ba7opf.9", "4.4.6-ba7opf.9.1")) + assertTrue(VersionComparator.isNewer("4.4.6-ba7opf.10", "4.4.6-ba7opf.9.1")) + } + + @Test + fun `parse extracts base and suffix segments`() { + assertEquals(listOf(4, 4, 6) to listOf(7), VersionComparator.parse("v4.4.6-ba7opf.7")) + assertEquals(listOf(4, 4, 6) to listOf(9, 1), VersionComparator.parse("v4.4.6-ba7opf.9.1")) + assertEquals(listOf(4, 4, 6) to emptyList(), VersionComparator.parse("4.4.6")) + assertEquals(listOf(4, 4, 6) to emptyList(), VersionComparator.parse("4.4.6-ba7opf")) } }