Copilot commented on code in PR #12771:
URL: https://github.com/apache/maven/pull/12771#discussion_r3815103919


##########
impl/maven-core/src/main/java/org/apache/maven/plugin/version/internal/DefaultPluginVersionResolver.java:
##########
@@ -270,6 +269,61 @@ private void selectVersion(DefaultPluginVersionResult 
result, PluginVersionReque
         }
     }
 
+    /**
+     * Returns the newest version of {@code candidates} that passes {@link 
#isCompatible}, or {@code null}.
+     */
+    private String selectCompatible(PluginVersionRequest request, 
TreeSet<Version> candidates, String kind) {
+        if (candidates.isEmpty()) {
+            return null;
+        }
+        logger.info(
+                "Looking for compatible {} version of plugin {}:{}",
+                kind,
+                request.getGroupId(),
+                request.getArtifactId());
+        for (Version v : candidates) {
+            String ver = v.toString();
+            if (isCompatible(request, ver)) {
+                return ver;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Does the repository offer at least one version that is neither a 
snapshot nor a pre-release?
+     */
+    private boolean hasStableVersion(Versions versions) {
+        for (String ver : versions.versions.keySet()) {
+            if (!ver.endsWith("-SNAPSHOT") && !isPreRelease(ver)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Is this a pre-release version such as {@code 4.0.0-beta-1} or {@code 
1.0-alpha-2}?
+     * <p>
+     * Decided with the version scheme itself rather than with a list of 
qualifier names: a pre-release
+     * qualifier sorts <em>before</em> the version it qualifies ({@code 
1.0-beta-1 < 1.0}), while a build
+     * or vendor qualifier does not ({@code 1.0-jre > 1.0}).
+     */
+    private boolean isPreRelease(String version) {
+        int qualifier = version.indexOf('-');
+        if (qualifier <= 0) {
+            return false;
+        }
+        try {
+            return versionScheme
+                            .parseVersion(version)
+                            
.compareTo(versionScheme.parseVersion(version.substring(0, qualifier)))
+                    < 0;
+        } catch (InvalidVersionSpecificationException e) {
+            return false;
+        }
+    }
+
     private boolean isCompatible(PluginVersionRequest request, String version) 
{

Review Comment:
   The Javadoc defines ‘pre-release’ as alpha/beta/milestone/rc, but the 
implementation classifies any qualifier that sorts before the base version as a 
pre-release, which also includes `-SNAPSHOT` under common Maven version schemes 
(and the new unit test currently asserts that). To avoid confusion, either (a) 
explicitly exclude snapshots in `isPreRelease` and keep snapshot handling 
separate, or (b) update the Javadoc (and related naming/messages) to state that 
this method detects ‘unstable’ versions that sort before the base version, 
including snapshots.



##########
impl/maven-core/src/main/java/org/apache/maven/plugin/version/internal/DefaultPluginVersionResolver.java:
##########
@@ -270,6 +269,61 @@ private void selectVersion(DefaultPluginVersionResult 
result, PluginVersionReque
         }
     }
 
+    /**
+     * Returns the newest version of {@code candidates} that passes {@link 
#isCompatible}, or {@code null}.
+     */
+    private String selectCompatible(PluginVersionRequest request, 
TreeSet<Version> candidates, String kind) {
+        if (candidates.isEmpty()) {
+            return null;
+        }
+        logger.info(
+                "Looking for compatible {} version of plugin {}:{}",
+                kind,
+                request.getGroupId(),
+                request.getArtifactId());
+        for (Version v : candidates) {
+            String ver = v.toString();
+            if (isCompatible(request, ver)) {
+                return ver;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Does the repository offer at least one version that is neither a 
snapshot nor a pre-release?
+     */
+    private boolean hasStableVersion(Versions versions) {
+        for (String ver : versions.versions.keySet()) {
+            if (!ver.endsWith("-SNAPSHOT") && !isPreRelease(ver)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**

Review Comment:
   `hasStableVersion` relies on string checks plus `isPreRelease`, which 
returns `false` on unparseable versions; this can cause unparseable entries to 
be treated as ‘stable’. Consider aligning this with the later parsing logic 
(i.e., only count versions as stable if they are parseable by the configured 
`versionScheme` and are neither snapshot nor pre-release). This keeps the 
‘stable exists’ decision consistent with what can actually be selected.



##########
impl/maven-core/src/main/java/org/apache/maven/plugin/version/internal/DefaultPluginVersionResolver.java:
##########
@@ -186,6 +186,21 @@ private void selectVersion(DefaultPluginVersionResult 
result, PluginVersionReque
             version = versions.latestVersion;
             repo = versions.latestRepository;
         }
+        // A pre-release (alpha/beta/milestone/rc) is a "release" as far as 
repository metadata is
+        // concerned, but it is not what a user asking for an unversioned 
plugin expects: such
+        // versions are typically built against unstable APIs. Prefer a stable 
version whenever the
+        // repository offers one, and fall back to the pre-release only when 
it does not.
+        if (version != null && isPreRelease(version) && 
hasStableVersion(versions)) {
+            logger.info(
+                    "Metadata of plugin {}:{} points at pre-release version 
{}, looking for a stable version",
+                    request.getGroupId(),
+                    request.getArtifactId(),
+                    version);
+            version = null;
+            repo = null;
+            searchPerformed = true;
+        }

Review Comment:
   The new selection behavior is covered by the added integration test, but the 
core unit test class currently doesn’t exercise the `selectVersion` ordering 
(stable → pre-release → snapshot) or the specific branch where `<release>` 
points to a pre-release and a stable exists. Adding a focused unit test around 
the resolver’s selection order would make regressions easier to catch without 
relying on the heavier IT harness.



##########
impl/maven-core/src/main/java/org/apache/maven/plugin/version/internal/DefaultPluginVersionResolver.java:
##########
@@ -214,34 +232,15 @@ private void selectVersion(DefaultPluginVersionResult 
result, PluginVersionReque
                 }
             }
 
-            if (!releases.isEmpty()) {
-                logger.info(
-                        "Looking for compatible RELEASE version of plugin 
{}:{}",
-                        request.getGroupId(),
-                        request.getArtifactId());
-                for (Version v : releases) {
-                    String ver = v.toString();
-                    if (isCompatible(request, ver)) {
-                        version = ver;
-                        repo = versions.versions.get(version);
-                        break;
-                    }
-                }
+            version = selectCompatible(request, releases, "RELEASE");
+            if (version == null) {
+                version = selectCompatible(request, preReleases, 
"pre-release");
             }
-
-            if (version == null && !snapshots.isEmpty()) {
-                logger.info(
-                        "Looking for compatible SNAPSHOT version of plugin 
{}:{}",
-                        request.getGroupId(),
-                        request.getArtifactId());
-                for (Version v : snapshots) {
-                    String ver = v.toString();
-                    if (isCompatible(request, ver)) {
-                        version = ver;
-                        repo = versions.versions.get(version);
-                        break;
-                    }
-                }
+            if (version == null) {
+                version = selectCompatible(request, snapshots, "SNAPSHOT");
+            }

Review Comment:
   The `kind` values used for logging are inconsistent in casing/format 
(`RELEASE`/`SNAPSHOT` vs `pre-release`). Standardizing these strings (e.g., all 
uppercase or all lowercase, or aligning with existing Maven log terminology) 
will keep log output consistent and easier to scan/grep.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to