This is an automated email from the ASF dual-hosted git repository.
cstamas 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 7ea795b789 [MNG-8256] FilteredProjectDependencyGraph fix for
non-transitive case (#1723)
7ea795b789 is described below
commit 7ea795b789cb7b9b360408557acbae29aeb5732b
Author: Tamas Cservenak <[email protected]>
AuthorDate: Thu Sep 12 22:50:39 2024 +0200
[MNG-8256] FilteredProjectDependencyGraph fix for non-transitive case
(#1723)
The `FilteredProjectDependencyGraph` class fix for non-transitive case and
an UT. Also contains some improvement in classes, making them immutable as
intended.
---
https://issues.apache.org/jira/browse/MNG-8256
---
.../apache/maven/graph/DefaultGraphBuilder.java | 6 ++--
.../graph/FilteredProjectDependencyGraph.java | 40 ++++++++++++++--------
.../graph/DefaultProjectDependencyGraphTest.java | 17 +++++++++
3 files changed, 47 insertions(+), 16 deletions(-)
diff --git
a/maven-core/src/main/java/org/apache/maven/graph/DefaultGraphBuilder.java
b/maven-core/src/main/java/org/apache/maven/graph/DefaultGraphBuilder.java
index 02d935df4f..93c81d830d 100644
--- a/maven-core/src/main/java/org/apache/maven/graph/DefaultGraphBuilder.java
+++ b/maven-core/src/main/java/org/apache/maven/graph/DefaultGraphBuilder.java
@@ -120,8 +120,10 @@ public class DefaultGraphBuilder implements GraphBuilder {
Result<ProjectDependencyGraph> result = null;
if (session.getProjectDependencyGraph() != null ||
session.getProjects() != null) {
- final ProjectDependencyGraph graph =
- new
DefaultProjectDependencyGraph(session.getAllProjects(), session.getProjects());
+ ProjectDependencyGraph graph = new
DefaultProjectDependencyGraph(session.getAllProjects());
+ if (session.getProjects() != null) {
+ graph = new FilteredProjectDependencyGraph(graph,
session.getProjects());
+ }
result = Result.success(graph);
}
diff --git
a/maven-core/src/main/java/org/apache/maven/graph/FilteredProjectDependencyGraph.java
b/maven-core/src/main/java/org/apache/maven/graph/FilteredProjectDependencyGraph.java
index 2d6612e3aa..feb06ec7c2 100644
---
a/maven-core/src/main/java/org/apache/maven/graph/FilteredProjectDependencyGraph.java
+++
b/maven-core/src/main/java/org/apache/maven/graph/FilteredProjectDependencyGraph.java
@@ -34,11 +34,11 @@ import org.apache.maven.project.MavenProject;
*/
class FilteredProjectDependencyGraph implements ProjectDependencyGraph {
- private ProjectDependencyGraph projectDependencyGraph;
+ private final ProjectDependencyGraph projectDependencyGraph;
- private Map<MavenProject, ?> whiteList;
+ private final Map<MavenProject, ?> whiteList;
- private List<MavenProject> sortedProjects;
+ private final List<MavenProject> sortedProjects;
/**
* Creates a new project dependency graph from the specified graph.
@@ -50,46 +50,58 @@ class FilteredProjectDependencyGraph implements
ProjectDependencyGraph {
ProjectDependencyGraph projectDependencyGraph, Collection<?
extends MavenProject> whiteList) {
this.projectDependencyGraph =
Objects.requireNonNull(projectDependencyGraph,
"projectDependencyGraph cannot be null");
-
this.whiteList = new IdentityHashMap<>();
-
for (MavenProject project : whiteList) {
this.whiteList.put(project, null);
}
+ this.sortedProjects =
projectDependencyGraph.getSortedProjects().stream()
+ .filter(this.whiteList::containsKey)
+ .toList();
}
/**
* @since 3.5.0
*/
+ @Override
public List<MavenProject> getAllProjects() {
return this.projectDependencyGraph.getAllProjects();
}
+ @Override
public List<MavenProject> getSortedProjects() {
- if (sortedProjects == null) {
- sortedProjects =
applyFilter(projectDependencyGraph.getSortedProjects());
- }
-
return new ArrayList<>(sortedProjects);
}
+ @Override
public List<MavenProject> getDownstreamProjects(MavenProject project,
boolean transitive) {
- return
applyFilter(projectDependencyGraph.getDownstreamProjects(project, transitive));
+ return
applyFilter(projectDependencyGraph.getDownstreamProjects(project, transitive),
transitive, false);
}
+ @Override
public List<MavenProject> getUpstreamProjects(MavenProject project,
boolean transitive) {
- return applyFilter(projectDependencyGraph.getUpstreamProjects(project,
transitive));
+ return applyFilter(projectDependencyGraph.getUpstreamProjects(project,
transitive), transitive, true);
}
- private List<MavenProject> applyFilter(Collection<? extends MavenProject>
projects) {
+ /**
+ * Filter out whitelisted projects with a big twist:
+ * Assume we have all projects {@code a, b, c} while active are {@code a,
c} and relation among all projects
+ * is {@code a -> b -> c}. This method handles well the case for
transitive list. But, for non-transitive we need
+ * to "pull in" transitive dependencies of eliminated projects, as for
case above, the properly filtered list would
+ * be {@code a -> c}.
+ * <p>
+ * Original code would falsely report {@code a} project as "without
dependencies", basically would lose link due
+ * filtering. This causes build ordering issues in concurrent builders.
+ */
+ private List<MavenProject> applyFilter(
+ Collection<? extends MavenProject> projects, boolean transitive,
boolean upstream) {
List<MavenProject> filtered = new ArrayList<>(projects.size());
-
for (MavenProject project : projects) {
if (whiteList.containsKey(project)) {
filtered.add(project);
+ } else if (!transitive) {
+ filtered.addAll(upstream ? getUpstreamProjects(project, false)
: getDownstreamProjects(project, false));
}
}
-
return filtered;
}
diff --git
a/maven-core/src/test/java/org/apache/maven/graph/DefaultProjectDependencyGraphTest.java
b/maven-core/src/test/java/org/apache/maven/graph/DefaultProjectDependencyGraphTest.java
index 9d68de0190..fab4c1cfb1 100644
---
a/maven-core/src/test/java/org/apache/maven/graph/DefaultProjectDependencyGraphTest.java
+++
b/maven-core/src/test/java/org/apache/maven/graph/DefaultProjectDependencyGraphTest.java
@@ -29,6 +29,7 @@ import org.apache.maven.project.MavenProject;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
/**
*/
@@ -36,6 +37,10 @@ class DefaultProjectDependencyGraphTest {
private final MavenProject aProject = createA();
+ private final MavenProject bProject =
createProject(Arrays.asList(toDependency(aProject)), "bProject");
+
+ private final MavenProject cProject =
createProject(Arrays.asList(toDependency(bProject)), "cProject");
+
private final MavenProject depender1 =
createProject(Arrays.asList(toDependency(aProject)), "depender1");
private final MavenProject depender2 =
createProject(Arrays.asList(toDependency(aProject)), "depender2");
@@ -47,6 +52,18 @@ class DefaultProjectDependencyGraphTest {
private final MavenProject transitiveOnly =
createProject(Arrays.asList(toDependency(depender3)), "depender5");
+ @Test
+ void testNonTransitiveFiltering() throws DuplicateProjectException,
CycleDetectedException {
+ ProjectDependencyGraph graph = new FilteredProjectDependencyGraph(
+ new DefaultProjectDependencyGraph(Arrays.asList(aProject,
bProject, cProject)),
+ Arrays.asList(aProject, cProject));
+ final List<MavenProject> sortedProjects = graph.getSortedProjects();
+ assertEquals(aProject, sortedProjects.get(0));
+ assertEquals(cProject, sortedProjects.get(1));
+
+ assertTrue(graph.getDownstreamProjects(aProject,
false).contains(cProject));
+ }
+
@Test
void testGetSortedProjects() throws DuplicateProjectException,
CycleDetectedException {
ProjectDependencyGraph graph = new
DefaultProjectDependencyGraph(Arrays.asList(depender1, aProject));