From ca8b6b75e31c695aba3c562f2e218452a32f8472 Mon Sep 17 00:00:00 2001 From: Adam Reeve Date: Mon, 14 Mar 2022 13:49:13 +1300 Subject: [PATCH] Account for operators when computing range intersections with same version (#53) --- src/SemanticVersioning/ComparatorSet.cs | 30 +++++++++++++++++-- .../RangeOperations.cs | 4 +++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/SemanticVersioning/ComparatorSet.cs b/src/SemanticVersioning/ComparatorSet.cs index ac8ce2f..4a5c07d 100644 --- a/src/SemanticVersioning/ComparatorSet.cs +++ b/src/SemanticVersioning/ComparatorSet.cs @@ -92,14 +92,40 @@ public ComparatorSet Intersect(ComparatorSet other) c.ComparatorType == Comparator.Operator.LessThan || c.ComparatorType == Comparator.Operator.LessThanOrEqual || c.ComparatorType == Comparator.Operator.LessThanExcludingPrereleases; + // When two comparators have the same version, the one with the more restrictive + // range should take precedence. + Func operatorOrdering = op => + { + switch (op) + { + case Comparator.Operator.LessThanExcludingPrereleases: + return 0; + case Comparator.Operator.LessThan: + return 1; + case Comparator.Operator.LessThanOrEqual: + return 2; + case Comparator.Operator.GreaterThan: + return 0; + case Comparator.Operator.GreaterThanOrEqual: + return 1; + case Comparator.Operator.GreaterThanOrEqualIncludingPrereleases: + return 2; + default: + throw new ArgumentOutOfRangeException(nameof(op), op, "Unexpected comparator operator"); + } + }; var maxOfMins = _comparators.Concat(other._comparators) .Where(operatorIsGreaterThan) - .OrderByDescending(c => c.Version).FirstOrDefault(); + .OrderByDescending(c => c.Version) + .ThenBy(c => operatorOrdering(c.ComparatorType)) + .FirstOrDefault(); var minOfMaxs = _comparators.Concat(other._comparators) .Where(operatorIsLessThan) - .OrderBy(c => c.Version).FirstOrDefault(); + .OrderBy(c => c.Version) + .ThenBy(c => operatorOrdering(c.ComparatorType)) + .FirstOrDefault(); if (maxOfMins != null && minOfMaxs != null && !maxOfMins.Intersects(minOfMaxs)) { return null; diff --git a/test/SemanticVersioning.Tests/RangeOperations.cs b/test/SemanticVersioning.Tests/RangeOperations.cs index bb83688..703a728 100644 --- a/test/SemanticVersioning.Tests/RangeOperations.cs +++ b/test/SemanticVersioning.Tests/RangeOperations.cs @@ -14,6 +14,10 @@ public class RangeOperations [InlineData("~1.2.3 || ~1.3.2", ">=1.2.9 < 1.3.8", "~1.2.9 || >=1.3.2 < 1.3.8")] [InlineData("<3.0.0", ">=3.0.0", "<0.0.0")] [InlineData("^2", "^3", "<0.0.0")] + [InlineData(">=1.0.0 <2.0.0", ">1.0.0", ">1.0.0 <2.0.0")] + [InlineData(">1.0.0", ">=1.0.0 <2.0.0", ">1.0.0 <2.0.0")] + [InlineData(">1.0.0 <2.0.0", "<=2.0.0", ">1.0.0 <2.0.0")] + [InlineData("<=2.0.0", ">1.0.0 <2.0.0", ">1.0.0 <2.0.0")] public void Intersect(string a, string b, string intersect) { var rangeA = new Range(a);