You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by gn...@apache.org on 2026/09/15 17:56:58 UTC
(maven) branch maven-4.0.x updated: [MNG-6979] Initialize the current project from the execution root (#13103) (#13143)
This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch maven-4.0.x
in repository https://gitbox.apache.org/repos/asf/maven.git
The following commit(s) were added to refs/heads/maven-4.0.x by this push:
new 7f684137de [MNG-6979] Initialize the current project from the execution root (#13103) (#13143)
7f684137de is described below
commit 7f684137de52b83971c764746288a450552ebc0f
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Tue Sep 15 19:56:53 2026 +0200
[MNG-6979] Initialize the current project from the execution root (#13103) (#13143)
Use the selected execution root as the initial current project, retaining the first selected project as fallback when the root is absent. This keeps lifecycle participants independent of reactor dependency ordering.
Add regression coverage for lifecycle project selection, empty and filtered reactors, thread-local state, and cloned sessions.
Co-authored-by: Goutam Adwant <86...@users.noreply.github.com>
---
.../org/apache/maven/execution/MavenSession.java | 8 +-
.../maven/MavenLifecycleParticipantTest.java | 17 +++
.../apache/maven/execution/MavenSessionTest.java | 118 +++++++++++++++++++++
.../current-project-selection/dependency/pom.xml | 6 ++
.../current-project-selection/pom.xml | 19 ++++
5 files changed, 164 insertions(+), 4 deletions(-)
diff --git a/impl/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java b/impl/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java
index 3d2539f07c..b50b345bfd 100644
--- a/impl/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java
+++ b/impl/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java
@@ -93,12 +93,12 @@ public class MavenSession implements Cloneable {
public void setProjects(List<MavenProject> projects) {
if (!projects.isEmpty()) {
- MavenProject first = projects.get(0);
- this.currentProject = ThreadLocal.withInitial(() -> first);
- this.topLevelProject = projects.stream()
+ MavenProject topLevelProject = projects.stream()
.filter(project -> project.isExecutionRoot())
.findFirst()
- .orElse(first);
+ .orElse(projects.get(0));
+ this.currentProject = ThreadLocal.withInitial(() -> topLevelProject);
+ this.topLevelProject = topLevelProject;
} else {
this.currentProject = new ThreadLocal<>();
this.topLevelProject = null;
diff --git a/impl/maven-core/src/test/java/org/apache/maven/MavenLifecycleParticipantTest.java b/impl/maven-core/src/test/java/org/apache/maven/MavenLifecycleParticipantTest.java
index b56822dda6..8a8b9c21f0 100644
--- a/impl/maven-core/src/test/java/org/apache/maven/MavenLifecycleParticipantTest.java
+++ b/impl/maven-core/src/test/java/org/apache/maven/MavenLifecycleParticipantTest.java
@@ -36,6 +36,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertSame;
class MavenLifecycleParticipantTest extends AbstractCoreMavenComponentTestCase {
@@ -89,6 +90,16 @@ private void injectReactorDependency(List<MavenProject> projects, String moduleF
}
}
+ public static class SelectCurrentProject extends AbstractMavenLifecycleParticipant {
+ @Override
+ public void afterProjectsRead(MavenSession session) {
+ assertEquals("dependency", session.getProjects().get(0).getArtifactId());
+ assertEquals("root", session.getTopLevelProject().getArtifactId());
+ assertSame(session.getTopLevelProject(), session.getCurrentProject());
+ session.setProjects(List.of(session.getCurrentProject()));
+ }
+ }
+
@Override
protected String getProjectsDirectory() {
return "src/test/projects/lifecycle-listener";
@@ -128,6 +139,12 @@ void testReactorDependencyInjection() throws Exception {
assertEquals(Arrays.asList("parent", "module-b", "module-a"), reactorOrder);
}
+ @Test
+ void testCurrentProjectSelection() throws Exception {
+ List<String> reactorOrder = getReactorOrder("current-project-selection", SelectCurrentProject.class);
+ assertEquals(List.of("root"), reactorOrder);
+ }
+
private <T> List<String> getReactorOrder(String testProject, Class<T> participant) throws Exception {
PlexusContainer container = getContainer();
diff --git a/impl/maven-core/src/test/java/org/apache/maven/execution/MavenSessionTest.java b/impl/maven-core/src/test/java/org/apache/maven/execution/MavenSessionTest.java
index 0f768ae4b8..8732d8e193 100644
--- a/impl/maven-core/src/test/java/org/apache/maven/execution/MavenSessionTest.java
+++ b/impl/maven-core/src/test/java/org/apache/maven/execution/MavenSessionTest.java
@@ -21,7 +21,10 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.eclipse.aether.RepositorySystemSession;
@@ -29,6 +32,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -38,6 +42,120 @@
*/
class MavenSessionTest {
+ @Test
+ void testCurrentProjectIsExecutionRootRegardlessOfReactorOrder() {
+ MavenSession session = createSessionWithoutContainer();
+ MavenProject dependency = new MavenProject();
+ MavenProject root = new MavenProject();
+ root.setExecutionRoot(true);
+
+ session.setProjects(List.of(dependency, root));
+ assertSame(root, session.getCurrentProject());
+ assertSame(root, session.getTopLevelProject());
+ assertSame(dependency, session.getProjects().get(0));
+ assertSame(root, session.getProjects().get(1));
+
+ session.setProjects(List.of(root, dependency));
+ assertSame(root, session.getCurrentProject());
+ assertSame(root, session.getTopLevelProject());
+ }
+
+ @Test
+ void testCurrentProjectFallsBackToFirstSelectedProject() {
+ MavenSession session = createSessionWithoutContainer();
+ MavenProject root = new MavenProject();
+ root.setExecutionRoot(true);
+ MavenProject selected = new MavenProject();
+ MavenProject dependency = new MavenProject();
+ session.setAllProjects(List.of(root, selected, dependency));
+
+ session.setProjects(List.of(selected, dependency));
+ assertSame(selected, session.getCurrentProject());
+ assertSame(selected, session.getTopLevelProject());
+
+ session.setProjects(List.of(dependency, selected));
+ assertSame(dependency, session.getCurrentProject());
+ assertSame(dependency, session.getTopLevelProject());
+ }
+
+ @Test
+ void testSetProjectsResetsCurrentProject() {
+ MavenSession session = createSessionWithoutContainer();
+ assertNull(session.getCurrentProject());
+ MavenProject root = new MavenProject();
+ root.setExecutionRoot(true);
+ MavenProject module = new MavenProject();
+ session.setProjects(List.of(module, root));
+
+ session.setCurrentProject(module);
+ assertSame(module, session.getCurrentProject());
+ assertSame(root, session.getTopLevelProject());
+ session.setCurrentProject(null);
+ assertNull(session.getCurrentProject());
+
+ session.setProjects(List.of(module, root));
+ assertSame(root, session.getCurrentProject());
+ session.setProjects(List.of());
+ assertNull(session.getCurrentProject());
+ assertNull(session.getTopLevelProject());
+ assertEquals(List.of(), session.getProjects());
+
+ session.setProjects(List.of(module));
+ assertSame(module, session.getCurrentProject());
+ assertSame(module, session.getTopLevelProject());
+ }
+
+ @Test
+ void testCurrentProjectIsThreadLocal() throws Exception {
+ MavenSession session = createSessionWithoutContainer();
+ MavenProject root = new MavenProject();
+ root.setExecutionRoot(true);
+ MavenProject module = new MavenProject();
+ session.setProjects(List.of(module, root));
+ session.setCurrentProject(module);
+
+ var executor = Executors.newSingleThreadExecutor();
+ try {
+ executor.submit(() -> {
+ assertSame(root, session.getCurrentProject());
+ session.setCurrentProject(null);
+ assertNull(session.getCurrentProject());
+ })
+ .get(10, TimeUnit.SECONDS);
+ assertSame(module, session.getCurrentProject());
+
+ session.setProjects(List.of(module, root));
+ assertSame(root, session.getCurrentProject());
+ assertSame(root, executor.submit(session::getCurrentProject).get(10, TimeUnit.SECONDS));
+ session.setProjects(List.of());
+ assertNull(executor.submit(session::getCurrentProject).get(10, TimeUnit.SECONDS));
+ } finally {
+ executor.shutdownNow();
+ }
+ }
+
+ @Test
+ void testCloneKeepsRuntimeCurrentProject() throws Exception {
+ MavenSession session = createSessionWithoutContainer();
+ MavenProject root = new MavenProject();
+ root.setExecutionRoot(true);
+ MavenProject module = new MavenProject();
+ session.setProjects(List.of(module, root));
+ session.setCurrentProject(module);
+
+ MavenSession clone = session.clone();
+ session.setCurrentProject(root);
+ assertSame(module, clone.getCurrentProject());
+ var executor = Executors.newSingleThreadExecutor();
+ try {
+ assertSame(module, executor.submit(clone::getCurrentProject).get(10, TimeUnit.SECONDS));
+ } finally {
+ executor.shutdownNow();
+ }
+ clone.setCurrentProject(null);
+ assertSame(root, session.getCurrentProject());
+ }
+
/**
* Creates a MavenSession without a PlexusContainer (Maven 4 style).
*/
diff --git a/impl/maven-core/src/test/projects/lifecycle-listener/current-project-selection/dependency/pom.xml b/impl/maven-core/src/test/projects/lifecycle-listener/current-project-selection/dependency/pom.xml
new file mode 100644
index 0000000000..bede517ea0
--- /dev/null
+++ b/impl/maven-core/src/test/projects/lifecycle-listener/current-project-selection/dependency/pom.xml
@@ -0,0 +1,6 @@
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>current-project-selection</groupId>
+ <artifactId>dependency</artifactId>
+ <version>1.0</version>
+</project>
diff --git a/impl/maven-core/src/test/projects/lifecycle-listener/current-project-selection/pom.xml b/impl/maven-core/src/test/projects/lifecycle-listener/current-project-selection/pom.xml
new file mode 100644
index 0000000000..a8e0fc6ffc
--- /dev/null
+++ b/impl/maven-core/src/test/projects/lifecycle-listener/current-project-selection/pom.xml
@@ -0,0 +1,19 @@
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>current-project-selection</groupId>
+ <artifactId>root</artifactId>
+ <version>1.0</version>
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>dependency</module>
+ </modules>
+
+ <dependencies>
+ <dependency>
+ <groupId>current-project-selection</groupId>
+ <artifactId>dependency</artifactId>
+ <version>1.0</version>
+ </dependency>
+ </dependencies>
+</project>