slawekjaranowski commented on code in PR #198: URL: https://github.com/apache/maven-enforcer/pull/198#discussion_r1056796605
########## enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/DependencyConvergence.java: ########## @@ -51,58 +46,41 @@ public class DependencyConvergence implements EnforcerRule { private List<String> excludes; + private DependencyVersionMap dependencyVersionMap; + public void setUniqueVersions(boolean uniqueVersions) { this.uniqueVersions = uniqueVersions; } - // CHECKSTYLE_OFF: LineLength - /** - * Uses the {@link EnforcerRuleHelper} to populate the values of the - * {@link DependencyTreeBuilder#buildDependencyTree(MavenProject, ArtifactRepository, ArtifactFactory, ArtifactMetadataSource, ArtifactFilter, ArtifactCollector)} - * factory method. <br/> - * This method simply exists to hide all the ugly lookup that the {@link EnforcerRuleHelper} has to do. - * - * @param helper - * @return a Dependency Node which is the root of the project's dependency tree - * @throws EnforcerRuleException - */ - // CHECKSTYLE_ON: LineLength - private DependencyNode getNode(EnforcerRuleHelper helper) throws EnforcerRuleException { - try { - MavenProject project = (MavenProject) helper.evaluate("${project}"); - MavenSession session = (MavenSession) helper.evaluate("${session}"); - DependencyCollectorBuilder dependencyCollectorBuilder = - helper.getComponent(DependencyCollectorBuilder.class); - ArtifactRepository repository = (ArtifactRepository) helper.evaluate("${localRepository}"); - - ProjectBuildingRequest buildingRequest = - new DefaultProjectBuildingRequest(session.getProjectBuildingRequest()); - buildingRequest.setProject(project); - buildingRequest.setLocalRepository(repository); - ArtifactFilter filter = (Artifact a) -> - ("compile".equalsIgnoreCase(a.getScope()) || "runtime".equalsIgnoreCase(a.getScope())) - && !a.isOptional(); - - return dependencyCollectorBuilder.collectDependencyGraph(buildingRequest, filter); - } catch (ExpressionEvaluationException | ComponentLookupException e) { - throw new EnforcerRuleException("Unable to lookup a component " + e.getLocalizedMessage(), e); - } catch (DependencyCollectorBuilderException e) { - throw new EnforcerRuleException("Could not build dependency tree " + e.getLocalizedMessage(), e); - } - } - @Override public void execute(EnforcerRuleHelper helper) throws EnforcerRuleException { if (log == null) { log = helper.getLog(); } try { - DependencyNode node = getNode(helper); - DependencyVersionMap visitor = new DependencyVersionMap(log); - visitor.setUniqueVersions(uniqueVersions); - node.accept(visitor); - List<CharSequence> errorMsgs = new ArrayList<>(); - errorMsgs.addAll(getConvergenceErrorMsgs(visitor.getConflictedVersionNumbers(includes, excludes))); + DependencyNode node = ArtifactUtils.resolveTransitiveDependencies( + helper, + // TODO: use a modified version of ExclusionDependencySelector to process excludes and includes + new DependencySelector() { + @Override + public boolean selectDependency(Dependency dependency) { + // regular OptionalDependencySelector only discriminates optional dependencies at level 2+ + return !dependency.isOptional() + // regular ScopeDependencySelector is case-sensitive + && !dependency.getScope().equalsIgnoreCase(Artifact.SCOPE_TEST); + } + + @Override + public DependencySelector deriveChildSelector(DependencyCollectionContext context) { + return this; + } + }, + new ExclusionDependencySelector()); Review Comment: Why we need here special selectors? provided scope is missing for exclusion - see MENFORCER-407 https://github.com/apache/maven/blob/master/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemUtils.java ########## enforcer-rules/src/main/java/org/apache/maven/plugins/enforcer/utils/ArtifactUtils.java: ########## @@ -18,70 +18,188 @@ */ package org.apache.maven.plugins.enforcer.utils; +import static java.util.Optional.ofNullable; + +import java.util.Collection; import java.util.HashSet; -import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; +import org.apache.maven.RepositoryUtils; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; import org.apache.maven.enforcer.rule.api.EnforcerRuleException; +import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.model.DependencyManagement; import org.apache.maven.plugins.enforcer.utils.ArtifactMatcher.Pattern; -import org.apache.maven.shared.dependency.graph.DependencyNode; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; +import org.codehaus.plexus.component.repository.exception.ComponentLookupException; +import org.eclipse.aether.DefaultRepositorySystemSession; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.artifact.ArtifactTypeRegistry; +import org.eclipse.aether.collection.CollectRequest; +import org.eclipse.aether.collection.DependencyCollectionException; +import org.eclipse.aether.collection.DependencySelector; +import org.eclipse.aether.graph.DependencyNode; +import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; +import org.eclipse.aether.util.graph.selector.AndDependencySelector; +import org.eclipse.aether.util.graph.transformer.ConflictResolver; +import org.eclipse.aether.util.graph.transformer.JavaScopeDeriver; +import org.eclipse.aether.util.graph.transformer.JavaScopeSelector; +import org.eclipse.aether.util.graph.transformer.NearestVersionSelector; +import org.eclipse.aether.util.graph.transformer.SimpleOptionalitySelector; /** * * @author Robert Scholte * @since 3.0.0 */ public final class ArtifactUtils { - private ArtifactUtils() {} - public static Set<Artifact> getAllDescendants(DependencyNode node) { - Set<Artifact> children = null; - if (node.getChildren() != null) { - children = new HashSet<>(); - for (DependencyNode depNode : node.getChildren()) { - children.add(depNode.getArtifact()); - Set<Artifact> subNodes = getAllDescendants(depNode); - if (subNodes != null) { - children.addAll(subNodes); - } + /** + * Converts {@link DependencyNode} to {@link Artifact}; in comparison + * to {@link RepositoryUtils#toArtifact(org.eclipse.aether.artifact.Artifact)}, this method + * assigns {@link Artifact#getScope()} and {@link Artifact#isOptional()} based on + * the dependency information from the node. + * + * @param node {@link DependencyNode} to convert to {@link Artifact} + * @return target artifact + */ + public static Artifact toArtifact(DependencyNode node) { + Artifact artifact = RepositoryUtils.toArtifact(node.getArtifact()); + ofNullable(node.getDependency()).ifPresent(dependency -> { + ofNullable(dependency.getScope()).ifPresent(artifact::setScope); + artifact.setOptional(dependency.isOptional()); + }); + return artifact; + } + + /** + * Retrieves the {@link DependencyNode} instance containing the result of the transitive dependency + * for the current {@link MavenProject}. + * + * @param helper (may not be null) an instance of the {@link EnforcerRuleHelper} class + * @param selectors zero or more {@link DependencySelector} instances + * @return a Dependency Node which is the root of the project's dependency tree + * @throws EnforcerRuleException thrown if the lookup fails + */ + public static DependencyNode resolveTransitiveDependencies( + EnforcerRuleHelper helper, DependencySelector... selectors) throws EnforcerRuleException { + try { + RepositorySystem repositorySystem = helper.getComponent(RepositorySystem.class); + MavenSession session = (MavenSession) helper.evaluate("${session}"); + MavenProject project = session.getCurrentProject(); + ArtifactTypeRegistry artifactTypeRegistry = + session.getRepositorySession().getArtifactTypeRegistry(); + + DefaultRepositorySystemSession repositorySystemSession = + new DefaultRepositorySystemSession(session.getRepositorySession()); + repositorySystemSession.setDependencyGraphTransformer(new ConflictResolver( + new NearestVersionSelector(), + new JavaScopeSelector(), + new SimpleOptionalitySelector(), + new JavaScopeDeriver())); Review Comment: This is default settings provided by Maven - why we need to change? https://github.com/apache/maven/blob/master/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemUtils.java -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: issues-unsubscr...@maven.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org