24
24
import java .util .List ;
25
25
import java .util .Map ;
26
26
import java .util .Objects ;
27
+ import java .util .stream .Collectors ;
27
28
28
29
import org .apache .maven .execution .ProjectDependencyGraph ;
29
30
import org .apache .maven .project .MavenProject ;
35
36
*/
36
37
class FilteredProjectDependencyGraph implements ProjectDependencyGraph {
37
38
38
- private ProjectDependencyGraph projectDependencyGraph ;
39
+ private final ProjectDependencyGraph projectDependencyGraph ;
39
40
40
- private Map <MavenProject , ?> whiteList ;
41
+ private final Map <MavenProject , ?> whiteList ;
41
42
42
- private List <MavenProject > sortedProjects ;
43
+ private final List <MavenProject > sortedProjects ;
43
44
44
45
/**
45
46
* Creates a new project dependency graph from the specified graph.
@@ -51,46 +52,58 @@ class FilteredProjectDependencyGraph implements ProjectDependencyGraph {
51
52
ProjectDependencyGraph projectDependencyGraph , Collection <? extends MavenProject > whiteList ) {
52
53
this .projectDependencyGraph =
53
54
Objects .requireNonNull (projectDependencyGraph , "projectDependencyGraph cannot be null" );
54
-
55
- this .whiteList = new IdentityHashMap <MavenProject , Object >();
56
-
55
+ this .whiteList = new IdentityHashMap <>();
57
56
for (MavenProject project : whiteList ) {
58
57
this .whiteList .put (project , null );
59
58
}
59
+ this .sortedProjects = projectDependencyGraph .getSortedProjects ().stream ()
60
+ .filter (this .whiteList ::containsKey )
61
+ .collect (Collectors .toList ());
60
62
}
61
63
62
64
/**
63
65
* @since 3.5.0
64
66
*/
67
+ @ Override
65
68
public List <MavenProject > getAllProjects () {
66
69
return this .projectDependencyGraph .getAllProjects ();
67
70
}
68
71
72
+ @ Override
69
73
public List <MavenProject > getSortedProjects () {
70
- if (sortedProjects == null ) {
71
- sortedProjects = applyFilter (projectDependencyGraph .getSortedProjects ());
72
- }
73
-
74
74
return new ArrayList <>(sortedProjects );
75
75
}
76
76
77
+ @ Override
77
78
public List <MavenProject > getDownstreamProjects (MavenProject project , boolean transitive ) {
78
- return applyFilter (projectDependencyGraph .getDownstreamProjects (project , transitive ));
79
+ return applyFilter (projectDependencyGraph .getDownstreamProjects (project , transitive ), transitive , false );
79
80
}
80
81
82
+ @ Override
81
83
public List <MavenProject > getUpstreamProjects (MavenProject project , boolean transitive ) {
82
- return applyFilter (projectDependencyGraph .getUpstreamProjects (project , transitive ));
84
+ return applyFilter (projectDependencyGraph .getUpstreamProjects (project , transitive ), transitive , true );
83
85
}
84
86
85
- private List <MavenProject > applyFilter (Collection <? extends MavenProject > projects ) {
87
+ /**
88
+ * Filter out whitelisted projects with a big twist:
89
+ * Assume we have all projects {@code a, b, c} while active are {@code a, c} and relation among all projects
90
+ * is {@code a -> b -> c}. This method handles well the case for transitive list. But, for non-transitive we need
91
+ * to "pull in" transitive dependencies of eliminated projects, as for case above, the properly filtered list would
92
+ * be {@code a -> c}.
93
+ * <p>
94
+ * Original code would falsely report {@code a} project as "without dependencies", basically would lose link due
95
+ * filtering. This causes build ordering issues in concurrent builders.
96
+ */
97
+ private List <MavenProject > applyFilter (
98
+ Collection <? extends MavenProject > projects , boolean transitive , boolean upstream ) {
86
99
List <MavenProject > filtered = new ArrayList <>(projects .size ());
87
-
88
100
for (MavenProject project : projects ) {
89
101
if (whiteList .containsKey (project )) {
90
102
filtered .add (project );
103
+ } else if (!transitive ) {
104
+ filtered .addAll (upstream ? getUpstreamProjects (project , false ) : getDownstreamProjects (project , false ));
91
105
}
92
106
}
93
-
94
107
return filtered ;
95
108
}
96
109
0 commit comments