You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by as...@apache.org on 2026/08/19 20:03:13 UTC

(maven) 04/04: Reuse GenericQualifiers for the pre-release check

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

ascheman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven.git

commit 7dc59176c0b0cb09198bef11425b97ece582c606
Author: Gerd Aschemann <as...@apache.org>
AuthorDate: Wed Aug 19 20:57:44 2026 +0200

    Reuse GenericQualifiers for the pre-release check
    
    Resolver already classifies version qualifiers, and it does so more
    carefully than the token scan added here: GenericQualifiers.qualifier()
    returns a negative shift for previews (alpha, beta, milestone, rc/cr,
    snapshot), zero for final versions (ga, final, release) and a positive
    one for service packs, handles the short forms (a1, b2, M1) and avoids
    matching "rc" inside words such as 1.0-arc.
    
    It is public since maven-resolver 2.0.21, which this line already
    depends on, so the whole hand-rolled base-version scan goes away.
    
    No test expectation changed; two cases were added for what the reused
    implementation gets right by construction (1.0-b2, 1.0-arc).
---
 .../internal/DefaultPluginVersionResolver.java     | 52 +++++-----------------
 .../internal/DefaultPluginVersionResolverTest.java |  2 +
 2 files changed, 13 insertions(+), 41 deletions(-)

diff --git a/impl/maven-core/src/main/java/org/apache/maven/plugin/version/internal/DefaultPluginVersionResolver.java b/impl/maven-core/src/main/java/org/apache/maven/plugin/version/internal/DefaultPluginVersionResolver.java
index a527a90121..6d7b294bc0 100644
--- a/impl/maven-core/src/main/java/org/apache/maven/plugin/version/internal/DefaultPluginVersionResolver.java
+++ b/impl/maven-core/src/main/java/org/apache/maven/plugin/version/internal/DefaultPluginVersionResolver.java
@@ -58,6 +58,7 @@
 import org.eclipse.aether.repository.RemoteRepository;
 import org.eclipse.aether.resolution.MetadataRequest;
 import org.eclipse.aether.resolution.MetadataResult;
+import org.eclipse.aether.util.version.GenericQualifiers;
 import org.eclipse.aether.version.InvalidVersionSpecificationException;
 import org.eclipse.aether.version.Version;
 import org.eclipse.aether.version.VersionScheme;
@@ -317,53 +318,22 @@ private boolean isParseable(String version) {
     }
 
     /**
-     * Does this version sort <em>before</em> the version it qualifies, i.e. is it an unstable
-     * precursor of it such as {@code 4.0.0-beta-1}, {@code 1.0-alpha-2} or {@code 1.0-SNAPSHOT}?
+     * Is this an unstable precursor of its base version, such as {@code 4.0.0-beta-1},
+     * {@code 1.0-alpha-2} or {@code 1.0-SNAPSHOT}?
      * <p>
-     * Decided with the version scheme itself rather than with a list of qualifier names: a pre-release
-     * qualifier sorts before its base version ({@code 1.0-beta-1 < 1.0}), while a build or vendor
-     * qualifier does not ({@code 1.0-jre > 1.0}). Snapshots satisfy this too; callers classify them
-     * first, so they never reach the pre-release bucket.
+     * Delegates to the version scheme's own qualifier table: a negative qualifier shift marks a
+     * preview version (alpha, beta, milestone, rc/cr, snapshot), zero a final one (ga, final,
+     * release) and a positive one a service pack. Versions without a recognised qualifier -- and
+     * that includes build or vendor qualifiers such as {@code 33.7.0-jre} -- are not pre-releases.
+     * Snapshots satisfy this too; callers classify them first, so they never reach the pre-release
+     * bucket.
      *
-     * @param version the version to inspect, may be unparseable
+     * @param version the version to inspect, may carry no qualifier at all
      * @return {@code true} if the version is an unstable precursor of its base version
      */
     // package-private for testing
     boolean isPreRelease(String version) {
-        String base = baseVersionOf(version);
-        if (base.isEmpty() || base.length() == version.length()) {
-            return false;
-        }
-        try {
-            return versionScheme.parseVersion(version).compareTo(versionScheme.parseVersion(base)) < 0;
-        } catch (InvalidVersionSpecificationException e) {
-            return false;
-        }
-    }
-
-    /**
-     * The numeric prefix of a version, i.e. everything before its first non-numeric token.
-     * <p>
-     * Tokens are separated by {@code -}, {@code .} or {@code _}, which the version scheme treats
-     * interchangeably: {@code 1.0-beta-1} and {@code 1.0.beta.1} are the same version, and both have
-     * the base version {@code 1.0}.
-     */
-    private static String baseVersionOf(String version) {
-        int end = 0;
-        int token = 0;
-        for (int i = 0; i <= version.length(); i++) {
-            char c = i < version.length() ? version.charAt(i) : '-';
-            if (c == '-' || c == '.' || c == '_') {
-                if (i == token) {
-                    break; // empty token, e.g. a leading or doubled separator
-                }
-                end = i;
-                token = i + 1;
-            } else if (c < '0' || c > '9') {
-                break;
-            }
-        }
-        return version.substring(0, end);
+        return GenericQualifiers.qualifier(version).orElse(GenericQualifiers.QUALIFIER_ZERO) < 0;
     }
 
     private boolean isCompatible(PluginVersionRequest request, String version) {
diff --git a/impl/maven-core/src/test/java/org/apache/maven/plugin/version/internal/DefaultPluginVersionResolverTest.java b/impl/maven-core/src/test/java/org/apache/maven/plugin/version/internal/DefaultPluginVersionResolverTest.java
index d53e8d5956..01498c159a 100644
--- a/impl/maven-core/src/test/java/org/apache/maven/plugin/version/internal/DefaultPluginVersionResolverTest.java
+++ b/impl/maven-core/src/test/java/org/apache/maven/plugin/version/internal/DefaultPluginVersionResolverTest.java
@@ -83,6 +83,7 @@ private static String select(DefaultPluginVersionResolver resolver, DefaultPlugi
                 "1.0-rc-1",
                 "1.0-rc1",
                 "1.0-cr1",
+                "1.0-b2", // short form, as GenericQualifiers reads it
                 "1.0.beta.1", // the scheme treats '.' and '-' as the same separator
                 "1.0_alpha_1",
                 "1.0-SNAPSHOT"
@@ -99,6 +100,7 @@ void preReleaseQualifiersAreExcluded(String version) {
                 "3.15.0",
                 "4.0.0",
                 "33.7.0-jre", // vendor/classifier qualifier, not a pre-release
+                "1.0-arc", // contains "rc" but is not a release candidate
                 "1.0-sp1", // service pack: sorts *after* the release
                 "1.0-final", // alias of the release itself
                 "1.0-ga"