From da4246ad2677f3a91353b6f3024832e4a5aff7b4 Mon Sep 17 00:00:00 2001
From: Swell <5782559+sultan@users.noreply.github.com>
Date: Tue, 20 Dec 2022 18:32:27 +0100
Subject: [PATCH] [MNG-7644] Fix version comparison where .X1 < -X2 for any
string qualifier X
This closes #930
---
.../versioning/ComparableVersion.java | 21 ++++++++++++++++++-
.../versioning/ComparableVersionTest.java | 21 +++++++++++++++++--
2 files changed, 39 insertions(+), 3 deletions(-)
diff --git a/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/ComparableVersion.java b/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/ComparableVersion.java
index 41a9ad153707..17aa8cc7a703 100644
--- a/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/ComparableVersion.java
+++ b/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/ComparableVersion.java
@@ -53,7 +53,10 @@
*
* Unknown qualifiers are considered after known qualifiers, with lexical order (always case insensitive),
*
- *
a hyphen usually precedes a qualifier, and is always less important than something preceded with a dot.
+ * a hyphen usually precedes a qualifier, and is always less important than digits/number, for example
+ * {@code 1.0.RC2 < 1.0-RC3 < 1.0.1}; but prefer {@code 1.0.0-RC1} over {@code 1.0.0.RC1}, and more
+ * generally: {@code 1.0.X2 < 1.0-X3 < 1.0.1} for any string {@code X}; but prefer {@code 1.0.0-X1}
+ * over {@code 1.0.0.X1}.
*
*
* @see "Versioning" on Maven Wiki
@@ -676,6 +679,14 @@ else if ( Character.isDigit( c ) )
{
if ( !isDigit && i > startIndex )
{
+ // 1.0.0.X1 < 1.0.0-X2
+ // treat .X as -X for any string qualifier X
+ if ( !list.isEmpty() )
+ {
+ list.add( list = new ListItem() );
+ stack.push( list );
+ }
+
list.add( new StringItem( version.substring( startIndex, i ), true ) );
startIndex = i;
@@ -702,6 +713,14 @@ else if ( Character.isDigit( c ) )
if ( version.length() > startIndex )
{
+ // 1.0.0.X1 < 1.0.0-X2
+ // treat .X as -X for any string qualifier X
+ if ( !isDigit && !list.isEmpty() )
+ {
+ list.add( list = new ListItem() );
+ stack.push( list );
+ }
+
list.add( parseItem( isDigit, version.substring( startIndex ) ) );
}
diff --git a/maven-artifact/src/test/java/org/apache/maven/artifact/versioning/ComparableVersionTest.java b/maven-artifact/src/test/java/org/apache/maven/artifact/versioning/ComparableVersionTest.java
index 97fb46d55f8b..832ab179b83f 100644
--- a/maven-artifact/src/test/java/org/apache/maven/artifact/versioning/ComparableVersionTest.java
+++ b/maven-artifact/src/test/java/org/apache/maven/artifact/versioning/ComparableVersionTest.java
@@ -51,8 +51,8 @@ private Comparable newComparable( String version )
"1-1", "1-2", "1-123" };
private static final String[] VERSIONS_NUMBER =
- { "2.0", "2-1", "2.0.a", "2.0.0.a", "2.0.2", "2.0.123", "2.1.0", "2.1-a", "2.1b", "2.1-c", "2.1-1", "2.1.0.1",
- "2.2", "2.123", "11.a2", "11.a11", "11.b2", "11.b11", "11.m2", "11.m11", "11", "11.a", "11b", "11c", "11m" };
+ { "2.0", "2.0.a", "2-1", "2.0.2", "2.0.123", "2.1.0", "2.1-a", "2.1b", "2.1-c", "2.1-1", "2.1.0.1", "2.2",
+ "2.123", "11.a2", "11.a11", "11.b2", "11.b11", "11.m2", "11.m11", "11", "11.a", "11b", "11c", "11m" };
private void checkVersionsOrder( String[] versions )
{
@@ -337,4 +337,21 @@ public void testReuse()
assertEquals( "reused instance should be equivalent to new instance", c1, c2 );
}
+
+ /**
+ * Test MNG-7644 edge cases
+ * 1.0.0.RC1 < 1.0.0-RC2 and more generally:
+ * 1.0.0.X1 < 1.0.0-X2 for any string X
+ */
+ public void testMng7644()
+ {
+ for ( String x : new String[]{ "abc", "alpha", "a", "beta", "b", "def", "milestone", "m", "RC" } ) {
+ // 1.0.0.X1 < 1.0.0-X2 for any string x
+ checkVersionsOrder( "1.0.0." + x + "1", "1.0.0-" + x + "2" );
+ // 2.0.X == 2-X == 2.0.0.X for any string x
+ checkVersionsEqual( "2-" + x, "2.0." + x ); // previously ordered, now equals
+ checkVersionsEqual( "2-" + x, "2.0.0." + x ); // previously ordered, now equals
+ checkVersionsEqual( "2.0." + x, "2.0.0." + x ); // previously ordered, now equals
+ }
+ }
}