fix: range exact/non-equal matches ignore build metadata

Build metadata does not affect precedence (SemVer 2.0.0 §10), so
the Eq and Neq constraints now use SemanticVersionComparer.Priority
instead of the structural == operator. This makes [1.2.3] match
1.2.3+build, consistent with precedence semantics.

Add a failing-then-passing test.
This commit is contained in:
Louis Seubert 2026-07-11 21:57:12 +02:00
commit 2ea7866e3b
3 changed files with 14 additions and 2 deletions

View file

@ -19,6 +19,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
### Fixed ### Fixed
- Reject invalid SemVer identifiers when parsing versions. - Reject invalid SemVer identifiers when parsing versions.
- Range exact and non-equal comparators ignore build metadata when matching versions.
### Removed ### Removed

View file

@ -248,6 +248,15 @@ internal sealed class SemanticVersionRangeTests
await Assert.That(new string(destination[..charsWritten])).IsEqualTo("^1.2.3"); await Assert.That(new string(destination[..charsWritten])).IsEqualTo("^1.2.3");
} }
[Test]
public async Task I_can_match_exact_range_ignoring_build_metadata()
{
var range = SemanticVersionRange.Parse("[1.2.3]");
await Assert.That(range.Contains(SemanticVersion.Parse("1.2.3+build.7"))).IsTrue();
await Assert.That(range.Contains(SemanticVersion.Parse("1.2.4"))).IsFalse();
}
[Test] [Test]
public async Task I_fail_formatting_when_the_tentative_short_form_overflows() public async Task I_fail_formatting_when_the_tentative_short_form_overflows()
{ {

View file

@ -50,8 +50,10 @@ internal readonly struct Constraint
{ {
return Operation switch return Operation switch
{ {
Comparison.Eq => v == Version, // Build metadata does not affect precedence (SemVer 2.0.0 §10), so exact
Comparison.Neq => v != Version, // and non-equal comparisons on the version part ignore it.
Comparison.Eq => SemanticVersionComparer.Priority.Equals(v, Version),
Comparison.Neq => !SemanticVersionComparer.Priority.Equals(v, Version),
Comparison.Lt => v < Version, Comparison.Lt => v < Version,
Comparison.Lte => v <= Version, Comparison.Lte => v <= Version,
Comparison.Gt => v > Version, Comparison.Gt => v > Version,