fix(arcup): honor SemVer prerelease precedence in version_gt (fixes #205) - #212
fix(arcup): honor SemVer prerelease precedence in version_gt (fixes #205)#212danilaverbena wants to merge 4 commits into
Conversation
version_gt stripped the prerelease suffix from both operands before comparing, so versions differing only in prerelease (e.g. 0.3.0 vs 0.3.0-rc.1) compared as equal and the installer's self-update check failed to see a stable release as newer than a prerelease. Implement SemVer section 11 precedence: compare core numerically, then apply prerelease rules (no-prerelease outranks prerelease; dot-separated identifiers compared numerically/lexically; more identifiers outrank fewer). Fixes circlefin#205.
|
Good fix — the bug is real and the implementation is substantially correct. A few observations: Correctness checkThe two reported cases from #205 both work correctly with the new code:
The full SemVer §11.4 precedence chain also holds:
One subtle issue:
|
…t glob Address review feedback on circlefin#212: - Strip +build metadata before the '-' split so build metadata containing a hyphen (e.g. 1.0.0+build-123) is not misread as a prerelease. - Split prerelease identifiers with `read -ra` (no pathname/glob expansion) instead of unquoted array assignment.
22 assertions covering the circlefin#205 bug cases, the SemVer 11.4 precedence chain, build-metadata handling, and the build-metadata-with-hyphen edge case. Sources arcup with ARCUP_SKIP_MAIN=1. Run: bash arcup/version_gt_test.sh
|
@osr21 thank you for the thorough review — much appreciated. Pushed a follow-up addressing both points: Build metadata containing a hyphen — fixed. Build metadata is now stripped up front, before the prerelease split: local v1="${1#v}"; v1="${v1%%+*}"So Glob expansion in the array split — fixed by splitting with local -a a1 a2
IFS=. read -ra a1 <<< "$pre1"
IFS=. read -ra a2 <<< "$pre2"
Test harness — added Bash dependency — confirmed; |
|
Both fixes are correct — the implementation is now clean. Build metadata strip — Glob expansion —
One small test gap The test suite covers build-only versions ( # 1.0.0-rc.1+build-123 should equal 1.0.0-rc.1 for precedence purposes
assert_le "1.0.0-rc.1+build-123" "1.0.0-rc.1"
assert_le "1.0.0-rc.1" "1.0.0-rc.1+build-123"
# rc.2 still beats rc.1 regardless of build metadata on either side
assert_gt "1.0.0-rc.2+build-1" "1.0.0-rc.1+build-99"The logic handles these correctly (strip metadata first, then compare prereleases), but the regression suite doesn't explicitly exercise the path where both a prerelease and build metadata are present simultaneously. Worth adding the three assertions above before merge. Everything else is solid. LGTM once those three assertions land. |
Per review on circlefin#212: exercise the path where a prerelease and build metadata are present simultaneously (build metadata is ignored for precedence).
|
@osr21 added the three assertions — thanks for catching the gap. # Prerelease combined with build metadata: build metadata is ignored, so
# precedence is decided purely by the prerelease identifiers.
assert_le "1.0.0-rc.1+build-123" "1.0.0-rc.1"
assert_le "1.0.0-rc.1" "1.0.0-rc.1+build-123"
assert_gt "1.0.0-rc.2+build-1" "1.0.0-rc.1+build-99"The suite now runs 25 passed, 0 failed. Verified locally against the branch's |
|
Traced all three new assertions against the implementation — all correct.
Both operands strip to The key ordering —
Implementation looks good overall
25 passed, 0 failed. LGTM. |
Problem (fixes #205)
version_gt()strips the prerelease suffix from both operands before comparing:So any prerelease information is discarded and versions that differ only in their prerelease compare as equal:
version_gt "0.3.0" "0.3.0-rc.1"returns non-zero → the stable release is not seen as newer than its release candidate.version_gt "0.3.0-rc.2" "0.3.0-rc.1"also returns non-zero → a newer RC is not detected.Because
version_gtdrives the installer's self-update checks (arcup/arcuplines ~413-430 and ~454-462),arcupfails to recognise a stable release as an upgrade over a previously installed prerelease.Fix
Implement SemVer precedence (semver.org §11) in
version_gt:major.minor.patchcore and its prerelease, and drop build metadata (+...), which is ignored for precedence.Testing
Verified with a local harness covering the reported cases plus the full precedence chain from the SemVer spec (§11.4):
All 18 assertions pass, including the two bug reproductions from the issue, existing core-version comparisons, and build-metadata being ignored.
bash -nclean; behaviour for plainmajor.minor.patchinputs is unchanged.Scope: single self-contained function in
arcup/arcup; no other changes.