diff --git a/maven-core/pom.xml b/maven-core/pom.xml index f46fdeb1d998..b0d2ff2662dd 100644 --- a/maven-core/pom.xml +++ b/maven-core/pom.xml @@ -185,6 +185,12 @@ under the License. plexus-testing test + + org.apache.maven.resolver + maven-resolver-test-util + ${resolverVersion} + test + diff --git a/maven-core/src/main/java/org/apache/maven/RepositoryUtils.java b/maven-core/src/main/java/org/apache/maven/RepositoryUtils.java index bafed36ee7b4..1d3729fe457a 100644 --- a/maven-core/src/main/java/org/apache/maven/RepositoryUtils.java +++ b/maven-core/src/main/java/org/apache/maven/RepositoryUtils.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.TreeMap; import org.apache.maven.artifact.handler.ArtifactHandler; import org.apache.maven.artifact.handler.DefaultArtifactHandler; @@ -112,6 +113,25 @@ public static org.apache.maven.artifact.Artifact toArtifact( Artifact artifact ) public static void toArtifacts( Collection artifacts, Collection nodes, List trail, DependencyFilter filter ) + { + Map> artifactsByDepth = new TreeMap<>(); + + List firstLevelArtifacts = new ArrayList<>( nodes.size() ); + // we know there are at least direct dependencies + artifactsByDepth.put( 1, firstLevelArtifacts ); + + toArtifacts( artifactsByDepth, 1, nodes, trail, filter ); + + // list of artifacts ordered by depth level + for ( List artifactsInDepth : artifactsByDepth.values() ) + { + artifacts.addAll( artifactsInDepth ); + } + } + + private static void toArtifacts( Map> artifactsByDepth, + int currentDepth, Collection nodes, List trail, + DependencyFilter filter ) { for ( DependencyNode node : nodes ) { @@ -124,10 +144,18 @@ public static void toArtifacts( Collection a if ( filter == null || filter.accept( node, Collections.emptyList() ) ) { artifact.setDependencyTrail( nodeTrail ); - artifacts.add( artifact ); + + // add artifact in the list of the current depth + List artifactsCurrentDepth = artifactsByDepth.get( currentDepth ); + if ( artifactsCurrentDepth == null ) + { + artifactsCurrentDepth = new ArrayList<>(); + artifactsByDepth.put( currentDepth, artifactsCurrentDepth ); + } + artifactsCurrentDepth.add( artifact ); } - toArtifacts( artifacts, node.getChildren(), nodeTrail, filter ); + toArtifacts( artifactsByDepth, currentDepth + 1, node.getChildren(), nodeTrail, filter ); } } diff --git a/maven-core/src/test/java/org/apache/maven/RepositoryUtilsTest.java b/maven-core/src/test/java/org/apache/maven/RepositoryUtilsTest.java new file mode 100644 index 000000000000..5f2cd1c81b74 --- /dev/null +++ b/maven-core/src/test/java/org/apache/maven/RepositoryUtilsTest.java @@ -0,0 +1,114 @@ +package org.apache.maven; + +/* + * 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. + */ +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.aether.graph.DependencyFilter; +import org.eclipse.aether.graph.DependencyNode; +import org.eclipse.aether.internal.test.util.DependencyGraphParser; +import org.junit.jupiter.api.Test; + +/** + * Test RepositoryUtils + * + * @author Gabriel Belingueres + */ +public class RepositoryUtilsTest +{ + + @Test + public void testToArtifactsCollectionOrderedByNodeDepth() + { + Collection artifacts = new ArrayList<>(); + + DependencyNode root = createDependencyTree(); + + List trail = new ArrayList<>(); + DependencyFilter filter = null; + + RepositoryUtils.toArtifacts( artifacts, root.getChildren(), trail, filter ); + + String expected = + "[gid:zlevel1:jar:1:, gid:ylevel1:jar:1:, gid:xlevel1:jar:1:, gid:alevel2:jar:1:, gid:blevel2:jar:1:, gid:clevel2:jar:1:, gid:alevel3:jar:1:]"; + assertEquals( expected, artifacts.toString() ); + } + + @Test + public void testToArtifactsCollectionOrderedByNodeDepthWithFilter() + { + Collection artifacts = new ArrayList<>(); + + DependencyNode root = createDependencyTree(); + + List trail = new ArrayList<>(); + DependencyFilter filter = new DependencyFilter() + { + @Override + public boolean accept( DependencyNode node, List parents ) + { + // accept node if artifactId does NOT contain "level2" + return !node.getArtifact().getArtifactId().contains( "level2" ); + } + }; + + RepositoryUtils.toArtifacts( artifacts, root.getChildren(), trail, filter ); + + String expected = + "[gid:zlevel1:jar:1:, gid:ylevel1:jar:1:, gid:xlevel1:jar:1:, gid:alevel3:jar:1:]"; + assertEquals( expected, artifacts.toString() ); + } + + /** + * Create a dependency tree. + * + * @return the root node or the tree. + */ + private DependencyNode createDependencyTree() + { + String LS = System.lineSeparator(); + DependencyGraphParser parser = new DependencyGraphParser(); + String dependencyGraph = + "gid:root:1" + LS + + "+- gid:zlevel1:1" + LS + + "| \\- gid:alevel2:1" + LS + + "\\- gid:ylevel1:1" + LS + + "| \\- gid:blevel2:1" + LS + + "| \\- gid:alevel3:1" + LS + + "\\- gid:xlevel1:1" + LS + + " \\- gid:clevel2:1" + LS; + + try + { + return parser.parseLiteral( dependencyGraph ); + } + catch ( IOException e ) + { + fail( "Failed the parsing of the dependency node graph" ); + } + return null; + } + +}