You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by gn...@apache.org on 2026/05/18 06:45:44 UTC

(maven) branch fix-milestone-version-comparison created (now 2dc04e08ee)

This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a change to branch fix-milestone-version-comparison
in repository https://gitbox.apache.org/repos/asf/maven.git


      at 2dc04e08ee Use ComparableVersion for mvnup plugin version comparison

This branch includes the following new commits:

     new 2dc04e08ee Use ComparableVersion for mvnup plugin version comparison

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(maven) 01/01: Use ComparableVersion for mvnup plugin version comparison

Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch fix-milestone-version-comparison
in repository https://gitbox.apache.org/repos/asf/maven.git

commit 2dc04e08ee7a2550d5b8c79afac45d348ac7eeac
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Mon May 18 08:45:28 2026 +0200

    Use ComparableVersion for mvnup plugin version comparison
    
    Replace hand-rolled version comparison with ComparableVersion which
    correctly handles milestone/pre-release qualifiers. The previous
    implementation stripped qualifiers (e.g., 3.0.0-M1 → 3.0.0) causing
    pre-release versions to be incorrectly considered sufficient.
    
    This fixes 19 projects (flink-connectors, sling) using enforcer
    3.0.0-M1 that mvnup failed to upgrade to 3.0.0.
    
    Co-Authored-By: Claude Opus 4.6 (1M context) <no...@anthropic.com>
---
 .../invoker/mvnup/goals/PluginUpgradeStrategy.java | 29 ++--------------
 .../mvnup/goals/PluginUpgradeStrategyTest.java     | 39 ++++++++++++++++++++++
 2 files changed, 41 insertions(+), 27 deletions(-)

diff --git a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategy.java b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategy.java
index e9d145bdc5..188405cfdb 100644
--- a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategy.java
+++ b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategy.java
@@ -51,6 +51,7 @@
 import org.apache.maven.api.services.ModelBuilderResult;
 import org.apache.maven.api.services.RepositoryFactory;
 import org.apache.maven.api.services.Sources;
+import org.apache.maven.artifact.versioning.ComparableVersion;
 import org.apache.maven.cling.invoker.mvnup.UpgradeContext;
 import org.apache.maven.impl.standalone.ApiRunner;
 import org.codehaus.plexus.components.secdispatcher.Dispatcher;
@@ -378,33 +379,7 @@ private boolean isVersionBelow(String currentVersion, String minVersion) {
         if (currentVersion == null || minVersion == null) {
             return false;
         }
-
-        // Remove any qualifiers like -SNAPSHOT, -alpha, etc. for comparison
-        String cleanCurrent = currentVersion.split("-")[0];
-        String cleanMin = minVersion.split("-")[0];
-
-        try {
-            String[] currentParts = cleanCurrent.split("\\.");
-            String[] minParts = cleanMin.split("\\.");
-
-            int maxLength = Math.max(currentParts.length, minParts.length);
-
-            for (int i = 0; i < maxLength; i++) {
-                int currentPart = i < currentParts.length ? Integer.parseInt(currentParts[i]) : 0;
-                int minPart = i < minParts.length ? Integer.parseInt(minParts[i]) : 0;
-
-                if (currentPart < minPart) {
-                    return true;
-                } else if (currentPart > minPart) {
-                    return false;
-                }
-            }
-
-            return false; // Versions are equal
-        } catch (NumberFormatException e) {
-            // Fallback to string comparison if parsing fails
-            return currentVersion.compareTo(minVersion) < 0;
-        }
+        return new ComparableVersion(currentVersion).compareTo(new ComparableVersion(minVersion)) < 0;
     }
 
     /**
diff --git a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategyTest.java b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategyTest.java
index 49abdf2be5..b577036539 100644
--- a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategyTest.java
+++ b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategyTest.java
@@ -184,6 +184,45 @@ void shouldNotModifyPluginWhenVersionAlreadySufficient() throws Exception {
             // POM might still be marked as modified due to other plugin management additions
         }
 
+        @Test
+        @DisplayName("should upgrade milestone version below release minimum")
+        void shouldUpgradeMilestoneVersionBelowRelease() throws Exception {
+            String pomXml = """
+                <?xml version="1.0" encoding="UTF-8"?>
+                <project xmlns="http://maven.apache.org/POM/4.0.0">
+                    <modelVersion>4.0.0</modelVersion>
+                    <groupId>test</groupId>
+                    <artifactId>test</artifactId>
+                    <version>1.0.0</version>
+                    <build>
+                        <plugins>
+                            <plugin>
+                                <groupId>org.apache.maven.plugins</groupId>
+                                <artifactId>maven-enforcer-plugin</artifactId>
+                                <version>3.0.0-M1</version>
+                            </plugin>
+                        </plugins>
+                    </build>
+                </project>
+                """;
+
+            Document document = Document.of(pomXml);
+            Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);
+
+            UpgradeContext context = createMockContext();
+            UpgradeResult result = strategy.doApply(context, pomMap);
+
+            assertTrue(result.success(), "Plugin upgrade should succeed");
+            assertTrue(result.modifiedCount() > 0, "Should have upgraded 3.0.0-M1 to 3.0.0");
+
+            Editor editor = new Editor(document);
+            String version = editor.root()
+                    .path("build", "plugins", "plugin", "version")
+                    .map(Element::textContentTrimmed)
+                    .orElse(null);
+            assertEquals("3.0.0", version, "3.0.0-M1 should be upgraded to 3.0.0");
+        }
+
         @Test
         @DisplayName("should upgrade plugin in pluginManagement")
         void shouldUpgradePluginInPluginManagement() throws Exception {