This is an automated email from the ASF dual-hosted git repository. michaelo pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/maven-resolver.git
The following commit(s) were added to refs/heads/master by this push: new 69aeda6 [MRESOLVER-240] Using breadth-first approach to resolve Maven dependencies 69aeda6 is described below commit 69aeda6c7976e5ff39ed7d0f888e4895a50a7f75 Author: Cai <we...@ebay.com> AuthorDate: Mon Jan 31 18:17:30 2022 -0800 [MRESOLVER-240] Using breadth-first approach to resolve Maven dependencies Co-authored-by: ibabiankou <ivan.babian...@gmail.com> This closes #144 --- .../impl/collect/DefaultDependencyCollector.java | 190 ++++++++++----------- .../impl/collect/DefaultDependencyCycle.java | 55 +++++- .../impl/collect/DependencyProcessingContext.java | 77 +++++++++ .../aether/internal/impl/collect/NodeStack.java | 127 -------------- .../impl/collect/DefaultDependencyCycleTest.java | 10 +- 5 files changed, 228 insertions(+), 231 deletions(-) diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollector.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollector.java index a46499d..a773367 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollector.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollector.java @@ -19,6 +19,7 @@ package org.eclipse.aether.internal.impl.collect; * under the License. */ +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -27,7 +28,10 @@ import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Queue; + import static java.util.Objects.requireNonNull; +import static org.eclipse.aether.internal.impl.collect.DefaultDependencyCycle.find; import javax.inject.Inject; import javax.inject.Named; @@ -244,22 +248,34 @@ public class DefaultDependencyCollector { DataPool pool = new DataPool( session ); - NodeStack nodes = new NodeStack(); - nodes.push( node ); - DefaultDependencyCollectionContext context = new DefaultDependencyCollectionContext( session, request.getRootArtifact(), root, managedDependencies ); DefaultVersionFilterContext versionContext = new DefaultVersionFilterContext( session ); - Args args = new Args( session, trace, pool, nodes, context, versionContext, request ); + Args args = new Args( session, trace, pool, context, versionContext, request ); Results results = new Results( result, session ); - process( args, results, dependencies, repositories, - depSelector != null ? depSelector.deriveChildSelector( context ) : null, - depManager != null ? depManager.deriveChildManager( context ) : null, - depTraverser != null ? depTraverser.deriveChildTraverser( context ) : null, - verFilter != null ? verFilter.deriveChildFilter( context ) : null ); + DependencySelector rootDepSelector = + depSelector != null ? depSelector.deriveChildSelector( context ) : null; + DependencyManager rootDepManager = depManager != null ? depManager.deriveChildManager( context ) : null; + DependencyTraverser rootDepTraverser = + depTraverser != null ? depTraverser.deriveChildTraverser( context ) : null; + VersionFilter rootVerFilter = verFilter != null ? verFilter.deriveChildFilter( context ) : null; + + for ( Dependency dependency : dependencies ) + { + args.dependencyProcessingQueue.add( + new DependencyProcessingContext( rootDepSelector, rootDepManager, rootDepTraverser, + rootVerFilter, repositories, managedDependencies, Collections.singletonList( node ), + dependency ) ); + } + + while ( !args.dependencyProcessingQueue.isEmpty() ) + { + processDependency( args, results, args.dependencyProcessingQueue.remove(), Collections.emptyList(), + false ); + } errorPath = results.errorPath; } @@ -344,61 +360,39 @@ public class DefaultDependencyCollector } @SuppressWarnings( "checkstyle:parameternumber" ) - private void process( final Args args, Results results, List<Dependency> dependencies, - List<RemoteRepository> repositories, DependencySelector depSelector, - DependencyManager depManager, DependencyTraverser depTraverser, VersionFilter verFilter ) - { - for ( Dependency dependency : dependencies ) - { - processDependency( args, results, repositories, depSelector, depManager, depTraverser, verFilter, - dependency ); - } - } - - @SuppressWarnings( "checkstyle:parameternumber" ) - private void processDependency( Args args, Results results, List<RemoteRepository> repositories, - DependencySelector depSelector, DependencyManager depManager, - DependencyTraverser depTraverser, VersionFilter verFilter, Dependency dependency ) - { - - List<Artifact> relocations = Collections.emptyList(); - processDependency( args, results, repositories, depSelector, depManager, depTraverser, verFilter, dependency, - relocations, false ); - } - - @SuppressWarnings( "checkstyle:parameternumber" ) - private void processDependency( Args args, Results results, List<RemoteRepository> repositories, - DependencySelector depSelector, DependencyManager depManager, - DependencyTraverser depTraverser, VersionFilter verFilter, Dependency dependency, + private void processDependency( Args args, Results results, DependencyProcessingContext context, List<Artifact> relocations, boolean disableVersionManagement ) { - if ( depSelector != null && !depSelector.selectDependency( dependency ) ) + if ( context.depSelector != null && !context.depSelector.selectDependency( context.dependency ) ) { return; } PremanagedDependency preManaged = - PremanagedDependency.create( depManager, dependency, disableVersionManagement, args.premanagedState ); - dependency = preManaged.managedDependency; + PremanagedDependency.create( context.depManager, context.dependency, disableVersionManagement, + args.premanagedState ); + Dependency dependency = preManaged.managedDependency; boolean noDescriptor = isLackingDescriptor( dependency.getArtifact() ); - boolean traverse = !noDescriptor && ( depTraverser == null || depTraverser.traverseDependency( dependency ) ); + boolean traverse = + !noDescriptor && ( context.depTraverser == null || context.depTraverser.traverseDependency( + dependency ) ); List<? extends Version> versions; VersionRangeResult rangeResult; try { - VersionRangeRequest rangeRequest = createVersionRangeRequest( args, repositories, dependency ); + VersionRangeRequest rangeRequest = createVersionRangeRequest( args, context.repositories, dependency ); rangeResult = cachedResolveRangeResult( rangeRequest, args.pool, args.session ); - versions = filterVersions( dependency, rangeResult, verFilter, args.versionContext ); + versions = filterVersions( dependency, rangeResult, context.verFilter, args.versionContext ); } catch ( VersionRangeResolutionException e ) { - results.addException( dependency, e, args.nodes ); + results.addException( dependency, e, context.parents ); return; } @@ -407,27 +401,30 @@ public class DefaultDependencyCollector Artifact originalArtifact = dependency.getArtifact().setVersion( version.toString() ); Dependency d = dependency.setArtifact( originalArtifact ); - ArtifactDescriptorRequest descriptorRequest = createArtifactDescriptorRequest( args, repositories, d ); + ArtifactDescriptorRequest descriptorRequest = + createArtifactDescriptorRequest( args, context.repositories, d ); final ArtifactDescriptorResult descriptorResult = - getArtifactDescriptorResult( args, results, noDescriptor, d, descriptorRequest ); + noDescriptor + ? new ArtifactDescriptorResult( descriptorRequest ) + : resolveCachedArtifactDescriptor( args.pool, descriptorRequest, args.session, + context.withDependency( d ), results ); + if ( descriptorResult != null ) { d = d.setArtifact( descriptorResult.getArtifact() ); - DependencyNode node = args.nodes.top(); - - int cycleEntry = args.nodes.find( d.getArtifact() ); + int cycleEntry = find( context.parents, d.getArtifact() ); if ( cycleEntry >= 0 ) { - results.addCycle( args.nodes, cycleEntry, d ); - DependencyNode cycleNode = args.nodes.get( cycleEntry ); + results.addCycle( context.parents, cycleEntry, d ); + DependencyNode cycleNode = context.parents.get( cycleEntry ); if ( cycleNode.getDependency() != null ) { DefaultDependencyNode child = - createDependencyNode( relocations, preManaged, rangeResult, version, d, descriptorResult, - cycleNode ); - node.getChildren().add( child ); + createDependencyNode( relocations, preManaged, rangeResult, version, d, + descriptorResult, cycleNode ); + context.getParent().getChildren().add( child ); continue; } } @@ -438,8 +435,8 @@ public class DefaultDependencyCollector originalArtifact.getGroupId().equals( d.getArtifact().getGroupId() ) && originalArtifact.getArtifactId().equals( d.getArtifact().getArtifactId() ); - processDependency( args, results, repositories, depSelector, depManager, depTraverser, verFilter, d, - descriptorResult.getRelocations(), disableVersionManagementSubsequently ); + processDependency( args, results, context.withDependency( d ), descriptorResult.getRelocations(), + disableVersionManagementSubsequently ); return; } else @@ -447,69 +444,72 @@ public class DefaultDependencyCollector d = args.pool.intern( d.setArtifact( args.pool.intern( d.getArtifact() ) ) ); List<RemoteRepository> repos = - getRemoteRepositories( rangeResult.getRepository( version ), repositories ); + getRemoteRepositories( rangeResult.getRepository( version ), context.repositories ); DefaultDependencyNode child = createDependencyNode( relocations, preManaged, rangeResult, version, d, descriptorResult.getAliases(), repos, args.request.getRequestContext() ); - node.getChildren().add( child ); + context.getParent().getChildren().add( child ); boolean recurse = traverse && !descriptorResult.getDependencies().isEmpty(); if ( recurse ) { - doRecurse( args, results, repositories, depSelector, depManager, depTraverser, verFilter, d, - descriptorResult, child ); + doRecurse( args, context.withDependency( d ), descriptorResult, child ); } } } else { - DependencyNode node = args.nodes.top(); List<RemoteRepository> repos = - getRemoteRepositories( rangeResult.getRepository( version ), repositories ); + getRemoteRepositories( rangeResult.getRepository( version ), context.repositories ); DefaultDependencyNode child = createDependencyNode( relocations, preManaged, rangeResult, version, d, null, repos, args.request.getRequestContext() ); - node.getChildren().add( child ); + context.getParent().getChildren().add( child ); } } } @SuppressWarnings( "checkstyle:parameternumber" ) - private void doRecurse( Args args, Results results, List<RemoteRepository> repositories, - DependencySelector depSelector, DependencyManager depManager, - DependencyTraverser depTraverser, VersionFilter verFilter, Dependency d, + private void doRecurse( Args args, DependencyProcessingContext parentContext, ArtifactDescriptorResult descriptorResult, DefaultDependencyNode child ) { DefaultDependencyCollectionContext context = args.collectionContext; - context.set( d, descriptorResult.getManagedDependencies() ); + context.set( parentContext.dependency, descriptorResult.getManagedDependencies() ); - DependencySelector childSelector = depSelector != null ? depSelector.deriveChildSelector( context ) : null; - DependencyManager childManager = depManager != null ? depManager.deriveChildManager( context ) : null; - DependencyTraverser childTraverser = depTraverser != null ? depTraverser.deriveChildTraverser( context ) : null; - VersionFilter childFilter = verFilter != null ? verFilter.deriveChildFilter( context ) : null; + DependencySelector childSelector = + parentContext.depSelector != null ? parentContext.depSelector.deriveChildSelector( context ) : null; + DependencyManager childManager = + parentContext.depManager != null ? parentContext.depManager.deriveChildManager( context ) : null; + DependencyTraverser childTraverser = + parentContext.depTraverser != null ? parentContext.depTraverser.deriveChildTraverser( context ) : null; + VersionFilter childFilter = + parentContext.verFilter != null ? parentContext.verFilter.deriveChildFilter( context ) : null; final List<RemoteRepository> childRepos = - args.ignoreRepos - ? repositories - : remoteRepositoryManager.aggregateRepositories( args.session, repositories, - descriptorResult.getRepositories(), true ); + args.ignoreRepos + ? parentContext.repositories + : remoteRepositoryManager.aggregateRepositories( args.session, parentContext.repositories, + descriptorResult.getRepositories(), true ); Object key = - args.pool.toKey( d.getArtifact(), childRepos, childSelector, childManager, childTraverser, childFilter ); + args.pool.toKey( parentContext.dependency.getArtifact(), childRepos, childSelector, childManager, + childTraverser, childFilter ); List<DependencyNode> children = args.pool.getChildren( key ); if ( children == null ) { args.pool.putChildren( key, child.getChildren() ); - args.nodes.push( child ); - - process( args, results, descriptorResult.getDependencies(), childRepos, childSelector, childManager, - childTraverser, childFilter ); - - args.nodes.pop(); + List<DependencyNode> parents = new ArrayList<>( parentContext.parents ); + parents.add( child ); + for ( Dependency dependency : descriptorResult.getDependencies() ) + { + args.dependencyProcessingQueue.add( + new DependencyProcessingContext( childSelector, childManager, childTraverser, childFilter, + childRepos, descriptorResult.getManagedDependencies(), parents, dependency ) ); + } } else { @@ -517,20 +517,11 @@ public class DefaultDependencyCollector } } - private ArtifactDescriptorResult getArtifactDescriptorResult( Args args, Results results, boolean noDescriptor, - Dependency d, - ArtifactDescriptorRequest descriptorRequest ) - { - return noDescriptor - ? new ArtifactDescriptorResult( descriptorRequest ) - : resolveCachedArtifactDescriptor( args.pool, descriptorRequest, args.session, d, results, args ); - - } - private ArtifactDescriptorResult resolveCachedArtifactDescriptor( DataPool pool, ArtifactDescriptorRequest descriptorRequest, - RepositorySystemSession session, Dependency d, - Results results, Args args ) + RepositorySystemSession session, + DependencyProcessingContext context, + Results results ) { Object key = pool.toKey( descriptorRequest ); ArtifactDescriptorResult descriptorResult = pool.getDescriptor( key, descriptorRequest ); @@ -543,7 +534,7 @@ public class DefaultDependencyCollector } catch ( ArtifactDescriptorException e ) { - results.addException( d, e, args.nodes ); + results.addException( context.dependency, e, context.parents ); pool.putDescriptor( key, e ); return null; } @@ -698,7 +689,7 @@ public class DefaultDependencyCollector final DataPool pool; - final NodeStack nodes; + final Queue<DependencyProcessingContext> dependencyProcessingQueue = new ArrayDeque<>(); final DefaultDependencyCollectionContext collectionContext; @@ -706,7 +697,7 @@ public class DefaultDependencyCollector final CollectRequest request; - Args( RepositorySystemSession session, RequestTrace trace, DataPool pool, NodeStack nodes, + Args( RepositorySystemSession session, RequestTrace trace, DataPool pool, DefaultDependencyCollectionContext collectionContext, DefaultVersionFilterContext versionContext, CollectRequest request ) { @@ -716,7 +707,6 @@ public class DefaultDependencyCollector this.premanagedState = ConfigUtils.getBoolean( session, false, DependencyManagerUtils.CONFIG_PROP_VERBOSE ); this.trace = trace; this.pool = pool; - this.nodes = nodes; this.collectionContext = collectionContext; this.versionContext = versionContext; } @@ -744,7 +734,7 @@ public class DefaultDependencyCollector maxCycles = ConfigUtils.getInteger( session, CONFIG_PROP_MAX_CYCLES_DEFAULT, CONFIG_PROP_MAX_CYCLES ); } - public void addException( Dependency dependency, Exception e, NodeStack nodes ) + public void addException( Dependency dependency, Exception e, List<DependencyNode> nodes ) { if ( maxExceptions < 0 || result.getExceptions().size() < maxExceptions ) { @@ -752,13 +742,13 @@ public class DefaultDependencyCollector if ( errorPath == null ) { StringBuilder buffer = new StringBuilder( 256 ); - for ( int i = 0; i < nodes.size(); i++ ) + for ( DependencyNode node : nodes ) { if ( buffer.length() > 0 ) { buffer.append( " -> " ); } - Dependency dep = nodes.get( i ).getDependency(); + Dependency dep = node.getDependency(); if ( dep != null ) { buffer.append( dep.getArtifact() ); @@ -774,7 +764,7 @@ public class DefaultDependencyCollector } } - public void addCycle( NodeStack nodes, int cycleEntry, Dependency dependency ) + public void addCycle( List<DependencyNode> nodes, int cycleEntry, Dependency dependency ) { if ( maxCycles < 0 || result.getCycles().size() < maxCycles ) { diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCycle.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCycle.java index 42a56c2..dd1565c 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCycle.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCycle.java @@ -23,6 +23,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import org.eclipse.aether.artifact.Artifact; import org.eclipse.aether.graph.Dependency; import org.eclipse.aether.graph.DependencyCycle; import org.eclipse.aether.graph.DependencyNode; @@ -39,7 +40,7 @@ final class DefaultDependencyCycle private final int cycleEntry; - DefaultDependencyCycle( NodeStack nodes, int cycleEntry, Dependency dependency ) + DefaultDependencyCycle( List<DependencyNode> nodes, int cycleEntry, Dependency dependency ) { // skip root node unless it actually has a dependency or is considered the cycle entry (due to its label) int offset = ( cycleEntry > 0 && nodes.get( 0 ).getDependency() == null ) ? 1 : 0; @@ -69,6 +70,58 @@ final class DefaultDependencyCycle return dependencies.subList( cycleEntry, dependencies.size() ); } + /** + * Searches for a node associated with the given artifact. A version of the artifact is not considered during the + * search. + * + * @param nodes a list representing single path in the dependency graph. First element is the root. + * @param artifact to find among the parent nodes. + * @return the index of the node furthest from the root and associated with the given artifact, or {@literal -1} if + * there is no such node. + */ + public static int find( List<DependencyNode> nodes, Artifact artifact ) + { + + for ( int i = nodes.size() - 1; i >= 0; i-- ) + { + DependencyNode node = nodes.get( i ); + + Artifact a = node.getArtifact(); + if ( a == null ) + { + break; + } + + if ( !a.getArtifactId().equals( artifact.getArtifactId() ) ) + { + continue; + } + if ( !a.getGroupId().equals( artifact.getGroupId() ) ) + { + continue; + } + if ( !a.getExtension().equals( artifact.getExtension() ) ) + { + continue; + } + if ( !a.getClassifier().equals( artifact.getClassifier() ) ) + { + continue; + } + /* + * NOTE: While a:1 and a:2 are technically different artifacts, we want to consider the path a:2 -> b:2 -> + * a:1 a cycle in the current context. The artifacts themselves might not form a cycle but their producing + * projects surely do. Furthermore, conflict resolution will always have to consider a:1 a loser (otherwise + * its ancestor a:2 would get pruned and so would a:1) so there is no point in building the sub graph of + * a:1. + */ + + return i; + } + + return -1; + } + @Override public String toString() { diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DependencyProcessingContext.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DependencyProcessingContext.java new file mode 100644 index 0000000..71815d0 --- /dev/null +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DependencyProcessingContext.java @@ -0,0 +1,77 @@ +package org.eclipse.aether.internal.impl.collect; + +/* + * 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 java.util.List; + +import org.eclipse.aether.collection.DependencyManager; +import org.eclipse.aether.collection.DependencySelector; +import org.eclipse.aether.collection.DependencyTraverser; +import org.eclipse.aether.collection.VersionFilter; +import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.graph.DependencyNode; +import org.eclipse.aether.repository.RemoteRepository; + +final class DependencyProcessingContext +{ + final DependencySelector depSelector; + final DependencyManager depManager; + final DependencyTraverser depTraverser; + final VersionFilter verFilter; + final List<RemoteRepository> repositories; + final List<Dependency> managedDependencies; + + /** + * All parents of the dependency in the top > down order. + */ + final List<DependencyNode> parents; + final Dependency dependency; + + @SuppressWarnings( "checkstyle:parameternumber" ) + DependencyProcessingContext( DependencySelector depSelector, + DependencyManager depManager, + DependencyTraverser depTraverser, + VersionFilter verFilter, + List<RemoteRepository> repositories, + List<Dependency> managedDependencies, + List<DependencyNode> parents, + Dependency dependency ) + { + this.depSelector = depSelector; + this.depManager = depManager; + this.depTraverser = depTraverser; + this.verFilter = verFilter; + this.repositories = repositories; + this.dependency = dependency; + this.managedDependencies = managedDependencies; + this.parents = parents; + } + + DependencyProcessingContext withDependency( Dependency dependency ) + { + return new DependencyProcessingContext( depSelector, depManager, depTraverser, verFilter, repositories, + managedDependencies, parents, dependency ); + } + + DependencyNode getParent() + { + return parents.get( parents.size() - 1 ); + } +} diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/NodeStack.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/NodeStack.java deleted file mode 100644 index 668dbc4..0000000 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/NodeStack.java +++ /dev/null @@ -1,127 +0,0 @@ -package org.eclipse.aether.internal.impl.collect; - -/* - * 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 java.util.Arrays; - -import org.eclipse.aether.artifact.Artifact; -import org.eclipse.aether.graph.DependencyNode; - -/** - * @see DefaultDependencyCollector - */ -final class NodeStack -{ - - @SuppressWarnings( {"unchecked", "checkstyle:magicnumber" } ) - // CHECKSTYLE_OFF: MagicNumber - private DependencyNode[] nodes = new DependencyNode[96]; - // CHECKSTYLE_ON: MagicNumber - - private int size; - - public DependencyNode top() - { - if ( size <= 0 ) - { - throw new IllegalStateException( "stack empty" ); - } - return nodes[size - 1]; - } - - public void push( DependencyNode node ) - { - if ( size >= nodes.length ) - { - DependencyNode[] tmp = new DependencyNode[size + 64]; - System.arraycopy( nodes, 0, tmp, 0, nodes.length ); - nodes = tmp; - } - nodes[size++] = node; - } - - public void pop() - { - if ( size <= 0 ) - { - throw new IllegalStateException( "stack empty" ); - } - size--; - } - - public int find( Artifact artifact ) - { - for ( int i = size - 1; i >= 0; i-- ) - { - DependencyNode node = nodes[i]; - - Artifact a = node.getArtifact(); - if ( a == null ) - { - break; - } - - if ( !a.getArtifactId().equals( artifact.getArtifactId() ) ) - { - continue; - } - if ( !a.getGroupId().equals( artifact.getGroupId() ) ) - { - continue; - } - if ( !a.getExtension().equals( artifact.getExtension() ) ) - { - continue; - } - if ( !a.getClassifier().equals( artifact.getClassifier() ) ) - { - continue; - } - /* - * NOTE: While a:1 and a:2 are technically different artifacts, we want to consider the path a:2 -> b:2 -> - * a:1 a cycle in the current context. The artifacts themselves might not form a cycle but their producing - * projects surely do. Furthermore, conflict resolution will always have to consider a:1 a loser (otherwise - * its ancestor a:2 would get pruned and so would a:1) so there is no point in building the sub graph of - * a:1. - */ - - return i; - } - - return -1; - } - - public int size() - { - return size; - } - - public DependencyNode get( int index ) - { - return nodes[index]; - } - - @Override - public String toString() - { - return Arrays.toString( nodes ); - } - -} diff --git a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCycleTest.java b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCycleTest.java index 53cddc2..0a382f8 100644 --- a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCycleTest.java +++ b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCycleTest.java @@ -23,8 +23,12 @@ import org.eclipse.aether.artifact.DefaultArtifact; import org.eclipse.aether.graph.DefaultDependencyNode; import org.eclipse.aether.graph.Dependency; import org.eclipse.aether.graph.DependencyCycle; +import org.eclipse.aether.graph.DependencyNode; import org.junit.Test; +import java.util.ArrayList; +import java.util.List; + import static org.junit.Assert.assertEquals; public class DefaultDependencyCycleTest @@ -35,9 +39,9 @@ public class DefaultDependencyCycleTest @Test public void testToString() { - NodeStack nodeStack = new NodeStack(); - nodeStack.push( new DefaultDependencyNode( FOO_DEPENDENCY ) ); - DependencyCycle cycle = new DefaultDependencyCycle( nodeStack, 1, BAR_DEPENDENCY ); + List<DependencyNode> nodes = new ArrayList<>(); + nodes.add( new DefaultDependencyNode( FOO_DEPENDENCY ) ); + DependencyCycle cycle = new DefaultDependencyCycle( nodes, 1, BAR_DEPENDENCY ); assertEquals( "group-id:foo:jar -> group-id:bar:jar", cycle.toString() ); }