You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by kw...@apache.org on 2022/06/08 17:42:39 UTC
[sling-maven-enforcer-rules] branch master updated: Only collect but not resolve dependencies
This is an automated email from the ASF dual-hosted git repository.
kwin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-maven-enforcer-rules.git
The following commit(s) were added to refs/heads/master by this push:
new 377804a Only collect but not resolve dependencies
377804a is described below
commit 377804aeed0fbd34a2e005237d464be27f7b4ea7
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Wed Jun 8 19:41:41 2022 +0200
Only collect but not resolve dependencies
---
...uireProvidedDependenciesInRuntimeClasspath.java | 120 +++++++++++----------
1 file changed, 62 insertions(+), 58 deletions(-)
diff --git a/src/main/java/org/apache/sling/maven/enforcer/RequireProvidedDependenciesInRuntimeClasspath.java b/src/main/java/org/apache/sling/maven/enforcer/RequireProvidedDependenciesInRuntimeClasspath.java
index c268052..2d89f8d 100644
--- a/src/main/java/org/apache/sling/maven/enforcer/RequireProvidedDependenciesInRuntimeClasspath.java
+++ b/src/main/java/org/apache/sling/maven/enforcer/RequireProvidedDependenciesInRuntimeClasspath.java
@@ -21,12 +21,12 @@ package org.apache.sling.maven.enforcer;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
import java.util.Objects;
import java.util.stream.Collectors;
@@ -48,7 +48,9 @@ import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.collection.CollectRequest;
+import org.eclipse.aether.collection.CollectResult;
import org.eclipse.aether.collection.DependencyCollectionContext;
+import org.eclipse.aether.collection.DependencyCollectionException;
import org.eclipse.aether.collection.DependencySelector;
import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.graph.DependencyFilter;
@@ -56,16 +58,11 @@ import org.eclipse.aether.graph.DependencyNode;
import org.eclipse.aether.graph.DependencyVisitor;
import org.eclipse.aether.graph.Exclusion;
import org.eclipse.aether.repository.RemoteRepository;
-import org.eclipse.aether.resolution.ArtifactResult;
-import org.eclipse.aether.resolution.DependencyRequest;
-import org.eclipse.aether.resolution.DependencyResolutionException;
-import org.eclipse.aether.resolution.DependencyResult;
import org.eclipse.aether.util.graph.selector.AndDependencySelector;
import org.eclipse.aether.util.graph.selector.ExclusionDependencySelector;
import org.eclipse.aether.util.graph.selector.OptionalDependencySelector;
import org.eclipse.aether.util.graph.selector.ScopeDependencySelector;
import org.eclipse.aether.util.graph.selector.StaticDependencySelector;
-import org.eclipse.aether.util.graph.visitor.PathRecordingDependencyVisitor;
import org.eclipse.aether.util.graph.visitor.TreeDependencyVisitor;
/** Checks that the runtime classpath (e.g. used by Maven Plugins via the
@@ -149,20 +146,13 @@ public class RequireProvidedDependenciesInRuntimeClasspath
Dependency rootDependency = RepositoryUtils.toDependency(project.getArtifact(), null);
try {
- Map<org.eclipse.aether.artifact.Artifact, List<List<DependencyNode>>> artifactMap = collectTransitiveDependencies(
+ DependencyNode rootDependencyNode = collectTransitiveDependencies(
rootDependency, repoSystem, newRepoSession, remoteRepositories, log);
- if (log.isDebugEnabled()) {
- log.debug("Collected " + artifactMap.size()+ " transitive dependencies: ");
- for (Entry<org.eclipse.aether.artifact.Artifact, List<List<DependencyNode>>> artifactResult : artifactMap.entrySet()) {
- log.debug(artifactResult.getKey().toString()
- + " (" + dumpPaths(artifactResult.getValue()) + ")");
- }
- }
- int numViolations = checkForMissingArtifacts(artifactMap, runtimeArtifacts, log);
+ int numViolations = checkForMissingArtifacts(rootDependencyNode, runtimeArtifacts, log);
if (numViolations > 0) {
throw new EnforcerRuleException("Found " + numViolations + " missing runtime dependencies. Look at the errors emitted above for the details.");
}
- } catch (DependencyResolutionException e) {
+ } catch (DependencyCollectionException e) {
// draw graph
StringWriter writer = new StringWriter();
DependencyVisitor depVisitor = new TreeDependencyVisitor(
@@ -264,59 +254,79 @@ public class RequireProvidedDependenciesInRuntimeClasspath
}
}
- protected Map<Artifact, List<List<DependencyNode>>> collectTransitiveDependencies(
+ private static final class MissingArtifactsDependencyVisitor implements DependencyVisitor {
+ private final List<Artifact> artifacts;
+ private final Log log;
+ private int numMissingArtifacts;
+ private final Deque<DependencyNode> nodeStack; // all intermediate nodes (without the root node)
+ private boolean isRoot;
+
+ MissingArtifactsDependencyVisitor(List<Artifact> artifacts, Log log) {
+ this.artifacts = artifacts;
+ this.log = log;
+ numMissingArtifacts = 0;
+ nodeStack = new ArrayDeque<>();
+ isRoot = true;
+ }
+
+ @Override
+ public boolean visitEnter(DependencyNode dependencyNode) {
+ if (isRoot) {
+ isRoot = false;
+ } else {
+ if (!isArtifactContainedInList(dependencyNode.getArtifact(), artifacts)) {
+ MessageBuilder msgBuilder = MessageUtils.buffer();
+ log.error(msgBuilder.a("Provided dependency ").strong(dependencyNode.getArtifact()).mojo(" (" + dumpIntermediatePath(nodeStack) + ")").a(" not found as runtime dependency!").toString());
+ numMissingArtifacts++;
+ }
+ nodeStack.addLast(dependencyNode);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean visitLeave(DependencyNode dependencyNode) {
+ if (!nodeStack.isEmpty()) {
+ nodeStack.removeLast();
+ }
+ return true;
+ }
+
+ public int getNumMissingArtifacts() {
+ return numMissingArtifacts;
+ }
+ }
+
+ protected DependencyNode collectTransitiveDependencies(
org.eclipse.aether.graph.Dependency rootDependency,
RepositorySystem repoSystem, RepositorySystemSession repoSession,
List<RemoteRepository> remoteRepositories, Log log)
- throws DependencyResolutionException {
+ throws DependencyCollectionException {
CollectRequest collectRequest = new CollectRequest(rootDependency, remoteRepositories);
- DependencyRequest req = new DependencyRequest(collectRequest, null);
- DependencyResult resolutionResult = repoSystem.resolveDependencies(repoSession, req);
+ CollectResult collectResult = repoSystem.collectDependencies(repoSession, collectRequest);
if (log.isDebugEnabled()) {
// draw full dependency graph
StringWriter writer = new StringWriter();
DependencyVisitor depVisitor = new TreeDependencyVisitor(
new DependencyVisitorPrinter(new PrintWriter(writer)));
- resolutionResult.getRoot().accept(depVisitor);
+ collectResult.getRoot().accept(depVisitor);
log.debug("dependency tree: " + writer.toString());
}
- // generate a map with key = artifact, value = all paths to it
- return resolutionResult.getArtifactResults().stream()
- .filter(a -> !areArtifactsEqualDisregardingVersion(a.getArtifact(), rootDependency.getArtifact())) // remove rootDependency itself
- .collect(Collectors.toMap(ArtifactResult::getArtifact, a -> getPathsForDependency(resolutionResult.getRoot(), a.getArtifact())));
+ return collectResult.getRoot();
}
- protected int checkForMissingArtifacts(Map<Artifact, List<List<DependencyNode>>> artifactMap, List<Artifact> runtimeArtifacts,
+ protected int checkForMissingArtifacts(DependencyNode rootDependencyNode, List<Artifact> runtimeArtifacts,
Log log) {
- int numViolations = 0;
- for (Entry<Artifact, List<List<DependencyNode>>> artifactResult : artifactMap.entrySet()) {
- if (!isArtifactContainedInList(artifactResult.getKey(), runtimeArtifacts)) {
- MessageBuilder msgBuilder = MessageUtils.buffer();
- log.error(msgBuilder.a("Provided dependency ").strong(artifactResult.getKey()).mojo(" (" + dumpPaths(artifactResult.getValue()) + ")").a(" not found as runtime dependency!").toString());
- numViolations++;
- }
- }
- return numViolations;
+ MissingArtifactsDependencyVisitor depVisitor = new MissingArtifactsDependencyVisitor(runtimeArtifacts, log);
+ rootDependencyNode.accept(depVisitor);
+ return depVisitor.getNumMissingArtifacts();
}
- private static String dumpPaths(List<List<DependencyNode>> paths) {
- String via = paths.stream()
- .map(RequireProvidedDependenciesInRuntimeClasspath::dumpPath)
- .collect(Collectors.joining(" and "));
- if (via.isEmpty()) {
+ private static String dumpIntermediatePath(Collection<DependencyNode> path) {
+ if (path.isEmpty()) {
return "direct";
- } else {
- return "via " + via;
}
- }
-
- private static String dumpPath(List<DependencyNode> path) {
- if (path.size() <= 2) {
- return "";
- }
- return path.stream()
- .skip(1) // first entry is the project itself
- .limit(path.size() - 2l) // last entry is the dependency (which is logged separately)
+ return "via " + path.stream()
.map(n -> n.getArtifact().toString())
.collect(Collectors.joining(" -> "));
}
@@ -344,12 +354,6 @@ public class RequireProvidedDependenciesInRuntimeClasspath
&& artifact1.getExtension().equals(artifact2.getExtension()));
}
- private static List<List<DependencyNode>> getPathsForDependency(DependencyNode root, Artifact artifact) {
- PathRecordingDependencyVisitor visitor = new PathRecordingDependencyVisitor(new SingleArtifactFilter(artifact));
- root.accept(visitor);
- return visitor.getPaths();
- }
-
private static final class SingleArtifactFilter implements DependencyFilter {
private final org.eclipse.aether.artifact.Artifact artifact;