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

(maven) branch maven-3.10.x updated: Feat: Resolver 2.x update policy control via CLI (#11948)

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

cstamas pushed a commit to branch maven-3.10.x
in repository https://gitbox.apache.org/repos/asf/maven.git


The following commit(s) were added to refs/heads/maven-3.10.x by this push:
     new cf4ec757a8 Feat: Resolver 2.x update policy control via CLI (#11948)
cf4ec757a8 is described below

commit cf4ec757a8aecba721f427d9ab1964d8b0e3f5ae
Author: Tamas Cservenak <ta...@cservenak.net>
AuthorDate: Mon Apr 20 21:08:00 2026 +0200

    Feat: Resolver 2.x update policy control via CLI (#11948)
    
    Resolver 2.x supports split policies for artifacts and metadata. Introduce 4 new CLI options, that if used, renders old "all" options ignored (-U and -nsu). New options are:
    * `-UA` similar to existing `-U` but forces only artifact updates (resolves cached 404)
    * `-UM` similar to existing `-U` but forces only metadata updates (updates ranges and snapshots)
    * two long opts (`--artifacts-update-policy=<policy>` and `--metadata-update-policy=<policy>`) where user can explicitly fine tune override policies for artifacts and metadata.
    
    If any of these 4 above are set, the old `-U` is ignored, and if any of `-UA` or `-UM` is set, the long counterpart is ignored.
    
    Fixes #11918
    
    ---
    
    Explanation: currently Maven had two update policy altering CLI options, `-U` and `-nsu`, and former set global session policy to "always" and latter to "never". Since Resolver 2.x update policies for artifacts and metadata are split and are handled as such.
    
    Why it matters:
    * plugin prefix resolution happens **via metadata** -- "always" policy will refetch only metadata
    * snapshot resolution happens **via metadata** -- "always" makes sure any new ones are discovered
    * "remembered" 404 for missing artifact happens **via artifacts**
    
    Before, when user issued `-U` he triggered all these above (forced refresh). Now, while `-U` still works, first two can be triggered with `--metadata-update-policy=always` (or suppress with never), and last one can be triggered with `--artifact-update-policy=always` without affecting the others (ie. discovery of new snapshots).
---
 .../execution/DefaultMavenExecutionRequest.java    | 30 ++++++++++++++++++++-
 .../maven/execution/MavenExecutionRequest.java     | 22 +++++++++++++++
 .../DefaultRepositorySystemSessionFactory.java     | 22 +++++++++++----
 .../main/java/org/apache/maven/cli/CLIManager.java | 31 +++++++++++++++++++++-
 .../main/java/org/apache/maven/cli/MavenCli.java   | 29 +++++++++++++++-----
 5 files changed, 121 insertions(+), 13 deletions(-)

diff --git a/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java b/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java
index 7788ae85e4..b25991441f 100644
--- a/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java
+++ b/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java
@@ -141,6 +141,10 @@ public class DefaultMavenExecutionRequest implements MavenExecutionRequest {
 
     private boolean updateSnapshots = false;
 
+    private String artifactsUpdatePolicy = null;
+
+    private String metadataUpdatePolicy = null;
+
     private List<ArtifactRepository> remoteRepositories;
 
     private List<ArtifactRepository> pluginArtifactRepositories;
@@ -202,11 +206,13 @@ public static MavenExecutionRequest copy(MavenExecutionRequest original) {
         copy.setLoggingLevel(original.getLoggingLevel());
         copy.setGlobalChecksumPolicy(original.getGlobalChecksumPolicy());
         copy.setUpdateSnapshots(original.isUpdateSnapshots());
+        copy.setNoSnapshotUpdates(original.isNoSnapshotUpdates());
+        copy.setArtifactsUpdatePolicy(original.getArtifactsUpdatePolicy());
+        copy.setMetadataUpdatePolicy(original.getMetadataUpdatePolicy());
         copy.setRemoteRepositories(original.getRemoteRepositories());
         copy.setPluginArtifactRepositories(original.getPluginArtifactRepositories());
         copy.setRepositoryCache(original.getRepositoryCache());
         copy.setWorkspaceReader(original.getWorkspaceReader());
-        copy.setNoSnapshotUpdates(original.isNoSnapshotUpdates());
         copy.setExecutionListener(original.getExecutionListener());
         copy.setUseLegacyLocalRepository(original.isUseLegacyLocalRepository());
         copy.setBuilderId(original.getBuilderId());
@@ -408,6 +414,28 @@ public boolean isNoSnapshotUpdates() {
         return noSnapshotUpdates;
     }
 
+    @Override
+    public MavenExecutionRequest setArtifactsUpdatePolicy(String policy) {
+        this.artifactsUpdatePolicy = policy;
+        return this;
+    }
+
+    @Override
+    public String getArtifactsUpdatePolicy() {
+        return artifactsUpdatePolicy;
+    }
+
+    @Override
+    public MavenExecutionRequest setMetadataUpdatePolicy(String policy) {
+        this.metadataUpdatePolicy = policy;
+        return this;
+    }
+
+    @Override
+    public String getMetadataUpdatePolicy() {
+        return metadataUpdatePolicy;
+    }
+
     @Override
     public String getGlobalChecksumPolicy() {
         return globalChecksumPolicy;
diff --git a/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java b/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java
index 41da250352..4fc94549ce 100644
--- a/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java
+++ b/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java
@@ -219,6 +219,28 @@ public interface MavenExecutionRequest {
 
     boolean isNoSnapshotUpdates();
 
+    // 3.10.x+ artifact and metadata policies
+
+    /**
+     * @since 3.10.0
+     */
+    MavenExecutionRequest setArtifactsUpdatePolicy(String policy);
+
+    /**
+     * @since 3.10.0
+     */
+    String getArtifactsUpdatePolicy();
+
+    /**
+     * @since 3.10.0
+     */
+    MavenExecutionRequest setMetadataUpdatePolicy(String policy);
+
+    /**
+     * @since 3.10.0
+     */
+    String getMetadataUpdatePolicy();
+
     // Checksum policy
     MavenExecutionRequest setGlobalChecksumPolicy(String globalChecksumPolicy);
 
diff --git a/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java b/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java
index 7f6f0ebc00..b26cf86618 100644
--- a/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java
+++ b/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java
@@ -233,12 +233,24 @@ public RepositorySystemSession.SessionBuilder newRepositorySession(MavenExecutio
 
         mainSessionBuilder.setOffline(request.isOffline());
         mainSessionBuilder.setChecksumPolicy(request.getGlobalChecksumPolicy());
-        if (request.isNoSnapshotUpdates()) {
-            mainSessionBuilder.setUpdatePolicy(RepositoryPolicy.UPDATE_POLICY_NEVER);
-        } else if (request.isUpdateSnapshots()) {
-            mainSessionBuilder.setUpdatePolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS);
+
+        if (request.getArtifactsUpdatePolicy() == null && request.getMetadataUpdatePolicy() == null) {
+            // we go "old" way
+            if (request.isNoSnapshotUpdates()) {
+                mainSessionBuilder.setUpdatePolicy(RepositoryPolicy.UPDATE_POLICY_NEVER);
+            } else if (request.isUpdateSnapshots()) {
+                mainSessionBuilder.setUpdatePolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS);
+            } else {
+                mainSessionBuilder.setUpdatePolicy(null);
+            }
         } else {
-            mainSessionBuilder.setUpdatePolicy(null);
+            // we go "new" way
+            if (request.getArtifactsUpdatePolicy() != null) {
+                mainSessionBuilder.setArtifactUpdatePolicy(request.getArtifactsUpdatePolicy());
+            }
+            if (request.getMetadataUpdatePolicy() != null) {
+                mainSessionBuilder.setMetadataUpdatePolicy(request.getMetadataUpdatePolicy());
+            }
         }
 
         int errorPolicy = 0;
diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java b/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java
index 522c69a96c..7e8b662381 100644
--- a/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java
+++ b/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java
@@ -63,6 +63,10 @@ public class CLIManager {
 
     public static final char UPDATE_SNAPSHOTS = 'U';
 
+    public static final String UPDATE_METADATA = "UM";
+
+    public static final String UPDATE_ARTIFACTS = "UA";
+
     public static final char ACTIVATE_PROFILES = 'P';
 
     public static final String SUPRESS_SNAPSHOT_UPDATES = "nsu";
@@ -109,7 +113,11 @@ public class CLIManager {
 
     public static final String IGNORE_TRANSITIVE_REPOSITORIES = "itr";
 
-    private static final String RAW_STREAMS = "raw-streams";
+    public static final String RAW_STREAMS = "raw-streams";
+
+    public static final String ARTIFACTS_UPDATE_POLICY = "artifacts-update-policy";
+
+    public static final String METADATA_UPDATE_POLICY = "metadata-update-policy";
 
     protected Options options;
 
@@ -158,6 +166,15 @@ public CLIManager() {
                 .longOpt("update-snapshots")
                 .desc("Forces a check for missing releases and updated snapshots on remote repositories")
                 .build());
+        options.addOption(Option.builder(UPDATE_METADATA)
+                .longOpt("update-metadata")
+                .desc(
+                        "Forces updates of remote repository metadata (updates plugin prefixes, version ranges and snapshots)")
+                .build());
+        options.addOption(Option.builder(UPDATE_ARTIFACTS)
+                .longOpt("update-artifacts")
+                .desc("Forces checks for missing artifacts (retries cached retrieval errors)")
+                .build());
         options.addOption(Option.builder(Character.toString(ACTIVATE_PROFILES))
                 .longOpt("activate-profiles")
                 .desc("Comma-delimited list of profiles to activate")
@@ -269,6 +286,18 @@ public CLIManager() {
                 .longOpt("ignore-transitive-repositories")
                 .desc("If set, Maven will ignore remote repositories introduced by transitive dependencies.")
                 .build());
+        options.addOption(Option.builder()
+                .longOpt(ARTIFACTS_UPDATE_POLICY)
+                .hasArg(true)
+                .desc(
+                        "The update policy to apply onto artifacts ('always', 'daily', 'never'); The -UA option overrides this option with 'always'")
+                .build());
+        options.addOption(Option.builder()
+                .longOpt(METADATA_UPDATE_POLICY)
+                .hasArg(true)
+                .desc(
+                        "The update policy to apply onto metadata ('always', 'daily', 'never'); The -UM option overrides this option with 'always'")
+                .build());
 
         // Adding this back in for compatibility with the verifier that hard codes this option.
         options.addOption(Option.builder("npr")
diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
index 7c6b6ac3f7..d2821316e7 100644
--- a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
+++ b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
@@ -113,6 +113,7 @@
 import org.codehaus.plexus.util.StringUtils;
 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
 import org.eclipse.aether.DefaultRepositoryCache;
+import org.eclipse.aether.repository.RepositoryPolicy;
 import org.eclipse.aether.transfer.TransferListener;
 import org.slf4j.ILoggerFactory;
 import org.slf4j.Logger;
@@ -1318,6 +1319,26 @@ private MavenExecutionRequest populateRequest(CliRequest cliRequest, MavenExecut
             noSnapshotUpdates = true;
         }
 
+        boolean updateSnapshots = false;
+        if (commandLine.hasOption(CLIManager.UPDATE_SNAPSHOTS)) {
+            updateSnapshots = true;
+        }
+
+        String artifactsUpdatePolicy = null;
+        String metadataUpdatePolicy = null;
+        if (commandLine.hasOption(CLIManager.UPDATE_ARTIFACTS)) {
+            artifactsUpdatePolicy = RepositoryPolicy.UPDATE_POLICY_ALWAYS;
+        }
+        if (artifactsUpdatePolicy == null && commandLine.hasOption(CLIManager.ARTIFACTS_UPDATE_POLICY)) {
+            artifactsUpdatePolicy = commandLine.getOptionValue(CLIManager.ARTIFACTS_UPDATE_POLICY);
+        }
+        if (commandLine.hasOption(CLIManager.UPDATE_METADATA)) {
+            metadataUpdatePolicy = RepositoryPolicy.UPDATE_POLICY_ALWAYS;
+        }
+        if (metadataUpdatePolicy == null && commandLine.hasOption(CLIManager.METADATA_UPDATE_POLICY)) {
+            metadataUpdatePolicy = commandLine.getOptionValue(CLIManager.METADATA_UPDATE_POLICY);
+        }
+
         // ----------------------------------------------------------------------
         //
         // ----------------------------------------------------------------------
@@ -1345,12 +1366,6 @@ private MavenExecutionRequest populateRequest(CliRequest cliRequest, MavenExecut
             request.setOffline(true);
         }
 
-        boolean updateSnapshots = false;
-
-        if (commandLine.hasOption(CLIManager.UPDATE_SNAPSHOTS)) {
-            updateSnapshots = true;
-        }
-
         String globalChecksumPolicy = null;
 
         if (commandLine.hasOption(CLIManager.CHECKSUM_FAILURE_POLICY)) {
@@ -1427,6 +1442,8 @@ private MavenExecutionRequest populateRequest(CliRequest cliRequest, MavenExecut
                 .setTransferListener(transferListener) // default: batch mode which goes along with interactive
                 .setUpdateSnapshots(updateSnapshots) // default: false
                 .setNoSnapshotUpdates(noSnapshotUpdates) // default: false
+                .setArtifactsUpdatePolicy(artifactsUpdatePolicy) // default: null
+                .setMetadataUpdatePolicy(metadataUpdatePolicy) // default: null
                 .setGlobalChecksumPolicy(globalChecksumPolicy) // default: warn
                 .setMultiModuleProjectDirectory(cliRequest.multiModuleProjectDirectory);