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

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


The following commit(s) were added to refs/heads/master by this push:
     new 37445d2608 Chore: use ApiRunner repositories in mvnval (#13648)
37445d2608 is described below

commit 37445d2608ef5ba0369166a37a6d8e3411b3ab59
Author: Ivan Khanas <[email protected]>
AuthorDate: Fri Oct 30 21:21:12 2026 +0100

    Chore: use ApiRunner repositories in mvnval (#13648)
    
    * chore: use ApiRunner repositories in mvnval
    
    After #13469, mvnval can use ApiRunner's remote repositories directly.
    Remove the duplicate settings conversion and Central fallback.
    
    Keep the CLI local repository override ahead of settings.xml and test
    both default and configured remote repositories.
    
    * test: clarify mvnval repository contract
    
    Name the test after its settings-or-Central behavior and local repository
    override. Both parameterized cases guard the session contract.
    
    ---------
    
    Co-authored-by: Guillaume Nodet <[email protected]>
---
 .../cling/invoker/mvnval/ValidateInvoker.java      | 51 +------------------
 .../cling/invoker/mvnval/ValidateInvokerTest.java  | 58 ++++++++++++++++++++--
 2 files changed, 57 insertions(+), 52 deletions(-)

diff --git 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnval/ValidateInvoker.java
 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnval/ValidateInvoker.java
index 22ffd3f7e3..5388718646 100644
--- 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnval/ValidateInvoker.java
+++ 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnval/ValidateInvoker.java
@@ -33,7 +33,6 @@
 import java.util.stream.Stream;
 
 import org.apache.maven.api.Constants;
-import org.apache.maven.api.RemoteRepository;
 import org.apache.maven.api.Session;
 import org.apache.maven.api.annotations.Nullable;
 import org.apache.maven.api.cli.InvokerException;
@@ -42,9 +41,6 @@
 import org.apache.maven.api.di.Named;
 import org.apache.maven.api.di.Provides;
 import org.apache.maven.api.model.Model;
-import org.apache.maven.api.model.Profile;
-import org.apache.maven.api.model.Repository;
-import org.apache.maven.api.model.RepositoryPolicy;
 import org.apache.maven.api.services.Lookup;
 import org.apache.maven.api.services.ModelBuilder;
 import org.apache.maven.api.services.ModelBuilder.ModelBuilderSession;
@@ -52,8 +48,6 @@
 import org.apache.maven.api.services.ModelBuilderRequest;
 import org.apache.maven.api.services.ModelBuilderRequest.RequestType;
 import org.apache.maven.api.services.ModelBuilderResult;
-import org.apache.maven.api.services.RepositoryFactory;
-import org.apache.maven.api.services.SettingsBuilder;
 import org.apache.maven.api.services.Sources;
 import org.apache.maven.cling.invoker.LookupContext;
 import org.apache.maven.cling.invoker.LookupInvoker;
@@ -105,9 +99,6 @@
  */
 public class ValidateInvoker extends LookupInvoker<ValidateContext> {
 
-    /** Where Central lives, for the one case where no settings file names a 
repository. */
-    private static final String CENTRAL_URL = 
"https://repo.maven.apache.org/maven2";;
-
     public static final int OK = 0;
     public static final int ERROR = 1;
 
@@ -360,12 +351,10 @@ protected void settings(ValidateContext context) {}
     protected Session createSession(@Nullable Path localRepository) {
         Session session = ApiRunner.createSession(injector -> 
injector.bindImplicit(TransporterFactoryConfig.class));
         if (localRepository != null) {
-            // Set on the session that came back, not passed to createSession, 
which prefers
-            // settings.getLocalRepository() over its argument and may in any 
case hand back a
-            // session another tool built. See derivedRepositories for why 
that happens.
+            // The CLI repository option must override the local repository in 
settings.xml.
             session = 
session.withLocalRepository(session.createLocalRepository(localRepository));
         }
-        return session.withRemoteRepositories(derivedRepositories(session));
+        return session;
     }
 
     /**
@@ -401,42 +390,6 @@ private static Session withWorkspaceReader(Session 
session, BundleWorkspaceReade
         return session;
     }
 
-    /**
-     * The repositories to resolve from, derived here rather than taken as 
they came.
-     * <p>
-     * {@code ApiRunner.createSession} asks its injector for an unqualified 
{@code Session}, and
-     * {@code InjectorImpl} registers a qualified {@code @Provides} under the 
unqualified key as
-     * well, so a provider belonging to a sibling tool can answer it and bring 
its own hardcoded
-     * repositories. Deriving the list from the settings gives the same answer 
whichever session
-     * came back, and keeps the repositories an operator declared: a parent 
that lives only in an
-     * internal repository has to resolve here exactly as it does under {@code 
mvn}.
-     * <p>
-     * The fallback matters only where no settings file declares a repository, 
which for a real
-     * installation means never: {@code conf/settings.xml} ships Central. It 
states Central with
-     * snapshots off, as that file does, because the two-argument
-     * {@link Session#createRemoteRepository(String, String)} takes the 
resolver's defaults
-     * instead, which enable snapshots and lower checksum checking to a 
warning.
-     */
-    private static List<RemoteRepository> derivedRepositories(Session session) 
{
-        RepositoryFactory factory = 
session.getService(RepositoryFactory.class);
-        Profile settingsProfile = session.getService(SettingsBuilder.class)
-                .convert(org.apache.maven.api.settings.Profile.newBuilder()
-                        .repositories(session.getSettings().getRepositories())
-                        .build());
-        List<RemoteRepository> repositories = 
settingsProfile.getRepositories().stream()
-                .map(factory::createRemote)
-                .toList();
-        return repositories.isEmpty()
-                ? List.of(factory.createRemote(Repository.newBuilder()
-                        .id(RemoteRepository.CENTRAL_ID)
-                        .url(CENTRAL_URL)
-                        
.releases(RepositoryPolicy.newBuilder().enabled("true").build())
-                        .snapshots(
-                                
RepositoryPolicy.newBuilder().enabled("false").build())
-                        .build()))
-                : repositories;
-    }
-
     /**
      * The transports resolution needs. {@code ApiRunner.createSession} 
registers none of its own,
      * so a session built without these reports "No transporter factories 
registered" and cannot
diff --git 
a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnval/ValidateInvokerTest.java
 
b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnval/ValidateInvokerTest.java
index 2834a7198f..a04d29577a 100644
--- 
a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnval/ValidateInvokerTest.java
+++ 
b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnval/ValidateInvokerTest.java
@@ -26,17 +26,21 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.Properties;
 import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 
+import org.apache.maven.api.Constants;
 import org.apache.maven.api.ProtoSession;
+import org.apache.maven.api.RemoteRepository;
 import org.apache.maven.api.Session;
 import org.apache.maven.api.cli.InvokerException;
 import org.apache.maven.api.cli.mvnval.ValidateOptions;
 import org.apache.maven.api.services.ModelBuilder;
 import org.apache.maven.cling.invoker.ProtoLookup;
+import org.apache.maven.impl.InternalSession;
 import org.apache.maven.impl.standalone.ApiRunner;
 import org.jline.terminal.Terminal;
 import org.junit.jupiter.api.BeforeEach;
@@ -44,6 +48,7 @@
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.io.TempDir;
+import org.junit.jupiter.api.parallel.ResourceLock;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.ValueSource;
 
@@ -55,6 +60,7 @@
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.parallel.Resources.SYSTEM_PROPERTIES;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
@@ -115,9 +121,6 @@ void setUp() {
         invoker = new ValidateInvoker(ProtoLookup.builder().build(), null) {
             @Override
             protected Session createSession(Path localRepository) {
-                // withLocalRepository is the line production uses, so an 
aimed repository is
-                // exercised rather than stubbed. The transports and the 
settings-derived
-                // repository list production adds are not: this session has 
neither.
                 aimed.add(localRepository);
                 return localRepository == null
                         ? shared
@@ -156,6 +159,55 @@ private int run(List<String> poms, Optional<String> 
format, Optional<String> mod
     @DisplayName("Wiring")
     class WiringTests {
 
+        @ParameterizedTest
+        @ValueSource(booleans = {false, true})
+        @ResourceLock(SYSTEM_PROPERTIES)
+        @DisplayName("should use settings repositories or Central and override 
the local repository")
+        void 
shouldUseSettingsRepositoriesOrCentralWithRequestedLocalRepository(boolean 
configuredRepository)
+                throws Exception {
+            Path settings = 
Files.createDirectories(tempDir.resolve(".m2")).resolve("settings.xml");
+            String repositories = configuredRepository ? """
+                      <repositories>
+                        <repository>
+                          
<id>configured</id><url>https://repository.example.invalid/maven2</url>
+                          <snapshots><enabled>false</enabled></snapshots>
+                        </repository>
+                      </repositories>
+                      """ : "";
+            Files.writeString(settings, """
+                    <settings xmlns="http://maven.apache.org/SETTINGS/2.0.0";>
+                      
<localRepository>${user.home}/settings-local</localRepository>
+                      %s
+                    </settings>
+                    """.formatted(repositories));
+            Path requested = 
Files.createDirectories(tempDir.resolve("requested-%20-repository"));
+            Files.createDirectories(tempDir.resolve("settings-local"));
+            Properties previous = System.getProperties();
+            Properties isolated = (Properties) previous.clone();
+            isolated.setProperty("user.home", tempDir.toString());
+            isolated.setProperty(Constants.MAVEN_HOME, tempDir.toString());
+            isolated.setProperty(
+                    Constants.MAVEN_INSTALLATION_CONF, 
tempDir.resolve("conf").toString());
+            try {
+                System.setProperties(isolated);
+                Session session = new 
ValidateInvoker(ProtoLookup.builder().build(), null).createSession(requested);
+
+                assertTrue(
+                        Files.isSameFile(requested, 
session.getLocalRepository().path()));
+                assertEquals(
+                        List.of(configuredRepository ? "configured" : 
RemoteRepository.CENTRAL_ID),
+                        session.getRemoteRepositories().stream()
+                                .map(RemoteRepository::id)
+                                .toList());
+                assertFalse(InternalSession.from(session)
+                        .toRepository(session.getRemoteRepositories().get(0))
+                        .getPolicy(true)
+                        .isEnabled());
+            } finally {
+                System.setProperties(previous);
+            }
+        }
+
         @Test
         @DisplayName("should register the transports resolution needs")
         void shouldRegisterTransports() throws Exception {

Reply via email to