This is an automated email from the ASF dual-hosted git repository.
cstamas pushed a commit to branch maven-3.9.x
in repository https://gitbox.apache.org/repos/asf/maven.git
The following commit(s) were added to refs/heads/maven-3.9.x by this push:
new 45201347c4 [MNG-8256] FilteredProjectDependencyGraph fix for
non-transitive case (#1724)
45201347c4 is described below
commit 45201347c417896b57159221130333f5fa4bbfb6
Author: Tamas Cservenak <[email protected]>
AuthorDate: Thu Sep 12 22:50:55 2024 +0200
[MNG-8256] FilteredProjectDependencyGraph fix for non-transitive case
(#1724)
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 | 43 ++++++++++++++--------
.../graph/DefaultProjectDependencyGraphTest.java | 15 ++++++++
3 files changed, 47 insertions(+), 17 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 b2f00adec2..67fad2b6a6 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
@@ -94,8 +94,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 96c008c78b..b05913c76f 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
@@ -24,6 +24,7 @@ import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.stream.Collectors;
import org.apache.maven.execution.ProjectDependencyGraph;
import org.apache.maven.project.MavenProject;
@@ -35,11 +36,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.
@@ -51,46 +52,58 @@ class FilteredProjectDependencyGraph implements
ProjectDependencyGraph {
ProjectDependencyGraph projectDependencyGraph, Collection<?
extends MavenProject> whiteList) {
this.projectDependencyGraph =
Objects.requireNonNull(projectDependencyGraph,
"projectDependencyGraph cannot be null");
-
- this.whiteList = new IdentityHashMap<MavenProject, Object>();
-
+ this.whiteList = new IdentityHashMap<>();
for (MavenProject project : whiteList) {
this.whiteList.put(project, null);
}
+ this.sortedProjects =
projectDependencyGraph.getSortedProjects().stream()
+ .filter(this.whiteList::containsKey)
+ .collect(Collectors.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 ce48390b03..9a5a8568de 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
@@ -35,6 +35,10 @@ public class DefaultProjectDependencyGraphTest extends
TestCase {
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");
@@ -46,6 +50,17 @@ public class DefaultProjectDependencyGraphTest extends
TestCase {
private final MavenProject transitiveOnly =
createProject(Arrays.asList(toDependency(depender3)), "depender5");
+ public 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));
+ }
+
public void testGetSortedProjects() throws DuplicateProjectException,
CycleDetectedException {
ProjectDependencyGraph graph = new
DefaultProjectDependencyGraph(Arrays.asList(depender1, aProject));
final List<MavenProject> sortedProjects = graph.getSortedProjects();