You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by sl...@apache.org on 2026/09/21 08:55:01 UTC

(maven-invoker-plugin) 02/02: Pin the forked builds to the flat IT local repository layout

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

slachiewicz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-invoker-plugin.git

commit 4ad152ffe72f0a407d872693184ad2b34ecbe2c0
Author: Sylwester Lachiewicz <sl...@apache.org>
AuthorDate: Sun Sep 20 00:32:09 2026 +0200

    Pin the forked builds to the flat IT local repository layout
    
    Writing the IT repository flat is not enough when the forked builds
    read it as split, which mergeUserSettings or the settings file can
    make them do since Maven 3.9.0 feeds settings profile properties into
    the resolver configuration. install cannot see what each forked build
    will be configured with, so run passes the property as a user property,
    which outranks every settings source, and both sides agree by
    construction. The IT enables the split layout on both sides and keeps
    remotePrefix empty so the plugin under test stays resolvable.
---
 pom.xml                                            |  1 -
 .../.mvn/maven.config                              |  1 -
 .../MINVOKER-377-install-ignore-split-repo/pom.xml | 11 ++++--
 .../settings.xml                                   | 35 ++++++++++++++++++
 .../src/it/consumer/invoker.properties             | 20 +++++++++++
 .../{ => src/it/consumer}/pom.xml                  | 41 +++++-----------------
 .../test.properties                                | 23 ++++++++++++
 .../verify.groovy                                  | 13 +++++--
 .../maven/plugins/invoker/AbstractInvokerMojo.java | 16 +++++++++
 .../apache/maven/plugins/invoker/InstallMojo.java  | 12 +++----
 10 files changed, 126 insertions(+), 47 deletions(-)

diff --git a/pom.xml b/pom.xml
index 126dc7d..aa3e815 100644
--- a/pom.xml
+++ b/pom.xml
@@ -296,7 +296,6 @@ under the License.
               <exclude>src/it/staging-dependencies/repo/**/*</exclude>
               <exclude>src/it/**/*.txt</exclude>
               <exclude>src/test/**/*.txt</exclude>
-              <exclude>src/it/**/.mvn/maven.config</exclude>
             </excludes>
           </configuration>
         </plugin>
diff --git a/src/it/MINVOKER-377-install-ignore-split-repo/.mvn/maven.config b/src/it/MINVOKER-377-install-ignore-split-repo/.mvn/maven.config
deleted file mode 100644
index bcc27a6..0000000
--- a/src/it/MINVOKER-377-install-ignore-split-repo/.mvn/maven.config
+++ /dev/null
@@ -1 +0,0 @@
--Daether.enhancedLocalRepository.split=true
diff --git a/src/it/MINVOKER-377-install-ignore-split-repo/pom.xml b/src/it/MINVOKER-377-install-ignore-split-repo/pom.xml
index 0f007b3..66541ec 100644
--- a/src/it/MINVOKER-377-install-ignore-split-repo/pom.xml
+++ b/src/it/MINVOKER-377-install-ignore-split-repo/pom.xml
@@ -31,8 +31,12 @@ under the License.
   <url>https://issues.apache.org/jira/browse/MINVOKER-377</url>
   <description>
     install must write to the flat local repository layout even when the outer build enabled
-    a split local repository (aether.enhancedLocalRepository.split), since the forked IT builds
-    read the plain flat layout.
+    a split local repository (aether.enhancedLocalRepository.split), and run must make the forked
+    IT builds read it that way even when their settings enable the split layout.
+
+    test.properties enables the split layout for this build with an empty remotePrefix, so the
+    cached (remote) artifacts, the plugin under test among them, stay at the flat paths the IT
+    harness populated, while locally installed artifacts would go to installed/.
   </description>
 
   <properties>
@@ -46,12 +50,15 @@ under the License.
         <artifactId>maven-invoker-plugin</artifactId>
         <version>@project.version@</version>
         <configuration>
+          <cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo>
           <localRepositoryPath>${project.build.directory}/local-repo</localRepositoryPath>
+          <settingsFile>settings.xml</settingsFile>
         </configuration>
         <executions>
           <execution>
             <goals>
               <goal>install</goal>
+              <goal>run</goal>
             </goals>
           </execution>
         </executions>
diff --git a/src/it/MINVOKER-377-install-ignore-split-repo/settings.xml b/src/it/MINVOKER-377-install-ignore-split-repo/settings.xml
new file mode 100644
index 0000000..9c3e074
--- /dev/null
+++ b/src/it/MINVOKER-377-install-ignore-split-repo/settings.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<settings>
+  <!-- the settings the forked IT builds run with: a split local repository, as a developer might have in
+       ~/.m2/settings.xml and bring in through mergeUserSettings -->
+  <profiles>
+    <profile>
+      <id>split-repo</id>
+      <activation>
+        <activeByDefault>true</activeByDefault>
+      </activation>
+      <properties>
+        <aether.enhancedLocalRepository.split>true</aether.enhancedLocalRepository.split>
+      </properties>
+    </profile>
+  </profiles>
+</settings>
diff --git a/src/it/MINVOKER-377-install-ignore-split-repo/src/it/consumer/invoker.properties b/src/it/MINVOKER-377-install-ignore-split-repo/src/it/consumer/invoker.properties
new file mode 100644
index 0000000..17680bb
--- /dev/null
+++ b/src/it/MINVOKER-377-install-ignore-split-repo/src/it/consumer/invoker.properties
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+# compile resolves the dependencies, which must come from the flat IT local repository
+invoker.goals = compile
diff --git a/src/it/MINVOKER-377-install-ignore-split-repo/pom.xml b/src/it/MINVOKER-377-install-ignore-split-repo/src/it/consumer/pom.xml
similarity index 58%
copy from src/it/MINVOKER-377-install-ignore-split-repo/pom.xml
copy to src/it/MINVOKER-377-install-ignore-split-repo/src/it/consumer/pom.xml
index 0f007b3..900ae2a 100644
--- a/src/it/MINVOKER-377-install-ignore-split-repo/pom.xml
+++ b/src/it/MINVOKER-377-install-ignore-split-repo/src/it/consumer/pom.xml
@@ -18,45 +18,22 @@ KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 -->
-
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
-
   <groupId>org.apache.maven.plugins.invoker</groupId>
-  <artifactId>minvoker377</artifactId>
+  <artifactId>minvoker377-consumer</artifactId>
   <version>1.0-SNAPSHOT</version>
   <packaging>jar</packaging>
-
-  <url>https://issues.apache.org/jira/browse/MINVOKER-377</url>
-  <description>
-    install must write to the flat local repository layout even when the outer build enabled
-    a split local repository (aether.enhancedLocalRepository.split), since the forked IT builds
-    read the plain flat layout.
-  </description>
-
+  <description>Resolves the artifact invoker:install put into the IT local repository.</description>
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   </properties>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-invoker-plugin</artifactId>
-        <version>@project.version@</version>
-        <configuration>
-          <localRepositoryPath>${project.build.directory}/local-repo</localRepositoryPath>
-        </configuration>
-        <executions>
-          <execution>
-            <goals>
-              <goal>install</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
-
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven.plugins.invoker</groupId>
+      <artifactId>minvoker377</artifactId>
+      <version>1.0-SNAPSHOT</version>
+    </dependency>
+  </dependencies>
 </project>
diff --git a/src/it/MINVOKER-377-install-ignore-split-repo/test.properties b/src/it/MINVOKER-377-install-ignore-split-repo/test.properties
new file mode 100644
index 0000000..fbd18bb
--- /dev/null
+++ b/src/it/MINVOKER-377-install-ignore-split-repo/test.properties
@@ -0,0 +1,23 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+# user properties of this build: a split local repository, with an empty remotePrefix so that the cached
+# (remote) artifacts, the plugin under test among them, stay at the flat paths the IT harness populated,
+# while locally installed artifacts would go to installed/
+aether.enhancedLocalRepository.split = true
+aether.enhancedLocalRepository.remotePrefix =
diff --git a/src/it/MINVOKER-377-install-ignore-split-repo/verify.groovy b/src/it/MINVOKER-377-install-ignore-split-repo/verify.groovy
index 10bcd74..ea27054 100644
--- a/src/it/MINVOKER-377-install-ignore-split-repo/verify.groovy
+++ b/src/it/MINVOKER-377-install-ignore-split-repo/verify.groovy
@@ -17,9 +17,9 @@
  * under the License.
  */
 
-// The outer build enabled a split local repository via .mvn/maven.config, but the forked
-// IT builds only ever read the flat layout, so invoker:install must ignore that setting and
-// write the flat layout regardless (MINVOKER-377).
+// The outer build enabled a split local repository via test.properties and the forked IT build's
+// settings.xml enables it too. invoker:install must write the flat layout regardless, and invoker:run
+// must make the forked build read the flat layout regardless (MINVOKER-377).
 def localRepo = new File(basedir, 'target/local-repo')
 
 def pom = new File(localRepo, 'org/apache/maven/plugins/invoker/minvoker377/1.0-SNAPSHOT/minvoker377-1.0-SNAPSHOT.pom')
@@ -30,3 +30,10 @@ assert jar.isFile()
 
 def splitDir = new File(localRepo, 'installed')
 assert !splitDir.exists()
+
+// the forked build resolved the installed artifact from the flat layout ...
+def consumerLog = new File(basedir, 'target/it/consumer/build.log').text
+assert consumerLog.contains('BUILD SUCCESS')
+
+// ... and did not read the repository as split, which would have put its own downloads under cached/
+assert !new File(localRepo, 'cached').exists()
diff --git a/src/main/java/org/apache/maven/plugins/invoker/AbstractInvokerMojo.java b/src/main/java/org/apache/maven/plugins/invoker/AbstractInvokerMojo.java
index 8420b75..7096a20 100644
--- a/src/main/java/org/apache/maven/plugins/invoker/AbstractInvokerMojo.java
+++ b/src/main/java/org/apache/maven/plugins/invoker/AbstractInvokerMojo.java
@@ -119,6 +119,12 @@ public abstract class AbstractInvokerMojo extends AbstractMojo {
      */
     private static final String INVOKER_TEST_PROPERTY = "invoker.test";
 
+    /**
+     * Resolver configuration property enabling the split local repository layout, see the protected
+     * <code>org.eclipse.aether.internal.impl.LocalPathPrefixComposerFactorySupport.CONF_PROP_SPLIT</code>.
+     */
+    static final String SPLIT_LOCAL_REPOSITORY_PROPERTY = "aether.enhancedLocalRepository.split";
+
     /**
      * The zero-based column index where to print the invoker result.
      */
@@ -155,6 +161,11 @@ public abstract class AbstractInvokerMojo extends AbstractMojo {
      * The local repository for caching artifacts. It is strongly recommended to specify a path to an isolated
      * repository like <code>${project.build.directory}/it-repo</code>. Otherwise, your ordinary local repository will
      * be used, potentially soiling it with broken artifacts.
+     * <p>
+     * The forked builds always read this repository in the flat layout that <code>invoker:install</code> writes:
+     * the plugin passes <code>-Daether.enhancedLocalRepository.split=false</code> to every forked build, which
+     * outranks a split local repository enabled through the merged user settings or the settings file. An IT that
+     * needs the split layout can set that property through {@link #properties} or its user properties file.
      *
      * @since 1.0
      */
@@ -2084,6 +2095,11 @@ public abstract class AbstractInvokerMojo extends AbstractMojo {
             }
         }
 
+        // invoker:install writes the IT local repository in the flat layout; make the forked build read it the same
+        // way, whatever split configuration the outer build or the (merged) settings carry (MINVOKER-377). A user
+        // property outranks system properties and settings profile properties in the resolver configuration.
+        collectedTestProperties.putIfAbsent(SPLIT_LOCAL_REPOSITORY_PROPERTY, "false");
+
         return collectedTestProperties;
     }
 
diff --git a/src/main/java/org/apache/maven/plugins/invoker/InstallMojo.java b/src/main/java/org/apache/maven/plugins/invoker/InstallMojo.java
index 6beae3e..5a4389d 100644
--- a/src/main/java/org/apache/maven/plugins/invoker/InstallMojo.java
+++ b/src/main/java/org/apache/maven/plugins/invoker/InstallMojo.java
@@ -415,14 +415,10 @@ public class InstallMojo extends AbstractMojo {
             if ("enhanced".equals(contentType)) {
                 contentType = "default";
             }
-            // Forked IT builds are invoked with -Dmaven.repo.local pointing at localRepositoryPath and no split
-            // configuration, so they always read it as a flat repository. If the outer build enabled the split
-            // layout (aether.enhancedLocalRepository.split, see the protected
-            // org.eclipse.aether.internal.impl.LocalPathPrefixComposerFactorySupport.CONF_PROP_SPLIT constant,
-            // which is not accessible here), that config would otherwise leak into this cloned session and make
-            // the enhanced local repository manager install artifacts under "installed/..." where the IT build
-            // can never find them (MINVOKER-377).
-            newSession.setConfigProperty("aether.enhancedLocalRepository.split", Boolean.FALSE);
+            // the forked IT builds read localRepositoryPath in the flat layout (invoker:run pins the property to
+            // false), so write it that way as well instead of inheriting a split layout from the outer build,
+            // which would put the artifacts under "installed/..." where the IT builds never look (MINVOKER-377)
+            newSession.setConfigProperty(AbstractInvokerMojo.SPLIT_LOCAL_REPOSITORY_PROPERTY, Boolean.FALSE);
             getLog().debug("Ignoring any split local repository configuration for the IT local repository");
 
             LocalRepositoryManager localRepositoryManager = repositorySystem.newLocalRepositoryManager(