[MNG-8041] Move PathScope into the dependency collection request (#1807)

JIRA issue: [MNG-8041](https://issues.apache.org/jira/browse/MNG-8041)
IT PR: https://github.com/apache/maven-integration-testing/pull/390
This commit is contained in:
Guillaume Nodet 2024-10-16 16:15:37 +02:00 committed by GitHub
parent ee29050d0f
commit 0d04bb9a21
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 96 additions and 57 deletions

View File

@ -612,25 +612,27 @@ public interface Session {
* Shortcut for {@code getService(DependencyResolver.class).collect(...)} * Shortcut for {@code getService(DependencyResolver.class).collect(...)}
* *
* @param artifact artifact for which to get the dependencies, including transitive ones * @param artifact artifact for which to get the dependencies, including transitive ones
* @param scope the {link PathScope} to collect dependencies, must not be {@code null}
* @return root node of the dependency graph for the given artifact * @return root node of the dependency graph for the given artifact
* *
* @see org.apache.maven.api.services.DependencyResolver#collect(Session, Artifact) * @see org.apache.maven.api.services.DependencyResolver#collect(Session, Artifact, PathScope)
* @throws org.apache.maven.api.services.DependencyResolverException if the dependency collection failed * @throws org.apache.maven.api.services.DependencyResolverException if the dependency collection failed
*/ */
@Nonnull @Nonnull
Node collectDependencies(@Nonnull Artifact artifact); Node collectDependencies(@Nonnull Artifact artifact, @Nonnull PathScope scope);
/** /**
* Shortcut for {@code getService(DependencyResolver.class).collect(...)} * Shortcut for {@code getService(DependencyResolver.class).collect(...)}
* *
* @param project project for which to get the dependencies, including transitive ones * @param project project for which to get the dependencies, including transitive ones
* @param scope the {link PathScope} to collect dependencies, must not be {@code null}
* @return root node of the dependency graph for the given project * @return root node of the dependency graph for the given project
* *
* @see org.apache.maven.api.services.DependencyResolver#collect(Session, Project) * @see org.apache.maven.api.services.DependencyResolver#collect(Session, Project, PathScope)
* @throws org.apache.maven.api.services.DependencyResolverException if the dependency collection failed * @throws org.apache.maven.api.services.DependencyResolverException if the dependency collection failed
*/ */
@Nonnull @Nonnull
Node collectDependencies(@Nonnull Project project); Node collectDependencies(@Nonnull Project project, @Nonnull PathScope scope);
/** /**
* Collects the transitive dependencies of some artifacts and builds a dependency graph. Note that this operation is * Collects the transitive dependencies of some artifacts and builds a dependency graph. Note that this operation is
@ -640,13 +642,14 @@ public interface Session {
* Shortcut for {@code getService(DependencyResolver.class).resolve(...)} * Shortcut for {@code getService(DependencyResolver.class).resolve(...)}
* *
* @param dependency dependency for which to get transitive dependencies * @param dependency dependency for which to get transitive dependencies
* @param scope the {link PathScope} to collect dependencies, must not be {@code null}
* @return root node of the dependency graph for the given artifact * @return root node of the dependency graph for the given artifact
* *
* @see org.apache.maven.api.services.DependencyResolver#collect(Session, DependencyCoordinates) * @see org.apache.maven.api.services.DependencyResolver#collect(Session, DependencyCoordinates, PathScope)
* @throws org.apache.maven.api.services.DependencyResolverException if the dependency collection failed * @throws org.apache.maven.api.services.DependencyResolverException if the dependency collection failed
*/ */
@Nonnull @Nonnull
Node collectDependencies(@Nonnull DependencyCoordinates dependency); Node collectDependencies(@Nonnull DependencyCoordinates dependency, @Nonnull PathScope scope);
/** /**
* Shortcut for {@code getService(DependencyResolver.class).flatten(...)}. * Shortcut for {@code getService(DependencyResolver.class).flatten(...)}.

View File

@ -29,6 +29,7 @@ import org.apache.maven.api.Service;
import org.apache.maven.api.Session; import org.apache.maven.api.Session;
import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Experimental;
import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.annotations.Nullable;
/** /**
* Collects, flattens and resolves dependencies. * Collects, flattens and resolves dependencies.
@ -37,56 +38,63 @@ import org.apache.maven.api.annotations.Nonnull;
public interface DependencyResolver extends Service { public interface DependencyResolver extends Service {
/** /**
* Collects the transitive dependencies of some artifacts and builds a dependency graph. Note that this operation is * Collects the transitive dependencies of some artifacts and builds a dependency graph for the given path scope.
* only concerned about determining the coordinates of the transitive dependencies and does not actually resolve the * Note that this operation is only concerned about determining the coordinates of the transitive dependencies and
* artifact files. * does not actually resolve the artifact files.
* *
* @param session the {@link Session}, must not be {@code null} * @param session the {@link Session}, must not be {@code null}
* @param root the Maven Dependency, must not be {@code null} * @param root the Maven Dependency, must not be {@code null}
* @param scope the {link PathScope} to collect dependencies, must not be {@code null}
* @return the collection result, never {@code null} * @return the collection result, never {@code null}
* @throws DependencyResolverException if the dependency tree could not be built * @throws DependencyResolverException if the dependency tree could not be built
* @throws IllegalArgumentException if an argument is null or invalid * @throws IllegalArgumentException if an argument is null or invalid
* @see #collect(DependencyResolverRequest) * @see #collect(DependencyResolverRequest)
*/ */
@Nonnull @Nonnull
default DependencyResolverResult collect(@Nonnull Session session, @Nonnull DependencyCoordinates root) { default DependencyResolverResult collect(
return collect(DependencyResolverRequest.build(session, DependencyResolverRequest.RequestType.COLLECT, root)); @Nonnull Session session, @Nonnull DependencyCoordinates root, @Nonnull PathScope scope) {
return collect(
DependencyResolverRequest.build(session, DependencyResolverRequest.RequestType.COLLECT, root, scope));
} }
/** /**
* Collects the transitive dependencies of some artifacts and builds a dependency graph. Note that this operation is * Collects the transitive dependencies of some artifacts and builds a dependency graph for the given path scope.
* only concerned about determining the coordinates of the transitive dependencies and does not actually resolve the * Note that this operation is only concerned about determining the coordinates of the transitive dependencies and
* artifact files. * does not actually resolve the artifact files.
* *
* @param session the {@link Session}, must not be {@code null} * @param session the {@link Session}, must not be {@code null}
* @param project the {@link Project}, must not be {@code null} * @param project the {@link Project}, must not be {@code null}
* @param scope the {link PathScope} to collect dependencies, must not be {@code null}
* @return the collection result, never {@code null} * @return the collection result, never {@code null}
* @throws DependencyResolverException if the dependency tree could not be built * @throws DependencyResolverException if the dependency tree could not be built
* @throws IllegalArgumentException if an argument is null or invalid * @throws IllegalArgumentException if an argument is null or invalid
* @see #collect(DependencyResolverRequest) * @see #collect(DependencyResolverRequest)
*/ */
@Nonnull @Nonnull
default DependencyResolverResult collect(@Nonnull Session session, @Nonnull Project project) { default DependencyResolverResult collect(
return collect( @Nonnull Session session, @Nonnull Project project, @Nonnull PathScope scope) {
DependencyResolverRequest.build(session, DependencyResolverRequest.RequestType.COLLECT, project)); return collect(DependencyResolverRequest.build(
session, DependencyResolverRequest.RequestType.COLLECT, project, scope));
} }
/** /**
* Collects the transitive dependencies of some artifacts and builds a dependency graph. Note that this operation is * Collects the transitive dependencies of some artifacts and builds a dependency graph for the given path scope.
* only concerned about determining the coordinates of the transitive dependencies and does not actually resolve the * Note that this operation is only concerned about determining the coordinates of the transitive dependencies and
* artifact files. * does not actually resolve the artifact files.
* *
* @param session the {@link Session}, must not be {@code null} * @param session the {@link Session}, must not be {@code null}
* @param artifact the {@link Artifact}, must not be {@code null} * @param artifact the {@link Artifact}, must not be {@code null}
* @param scope the {link PathScope} to collect dependencies, must not be {@code null}
* @return the collection result, never {@code null} * @return the collection result, never {@code null}
* @throws DependencyResolverException if the dependency tree could not be built * @throws DependencyResolverException if the dependency tree could not be built
* @throws IllegalArgumentException if an argument is null or invalid * @throws IllegalArgumentException if an argument is null or invalid
* @see #collect(DependencyResolverRequest) * @see #collect(DependencyResolverRequest)
*/ */
@Nonnull @Nonnull
default DependencyResolverResult collect(@Nonnull Session session, @Nonnull Artifact artifact) { default DependencyResolverResult collect(
return collect( @Nonnull Session session, @Nonnull Artifact artifact, @Nonnull PathScope scope) {
DependencyResolverRequest.build(session, DependencyResolverRequest.RequestType.COLLECT, artifact)); return collect(DependencyResolverRequest.build(
session, DependencyResolverRequest.RequestType.COLLECT, artifact, scope));
} }
/** /**
@ -99,9 +107,9 @@ public interface DependencyResolver extends Service {
* @throws DependencyResolverException if the dependency tree could not be built * @throws DependencyResolverException if the dependency tree could not be built
* @throws IllegalArgumentException if an argument is null or invalid * @throws IllegalArgumentException if an argument is null or invalid
* *
* @see DependencyResolver#collect(Session, Project) * @see DependencyResolver#collect(Session, Project, PathScope)
* @see DependencyResolver#collect(Session, DependencyCoordinates) * @see DependencyResolver#collect(Session, DependencyCoordinates, PathScope)
* @see DependencyResolver#collect(Session, Artifact) * @see DependencyResolver#collect(Session, Artifact, PathScope)
*/ */
@Nonnull @Nonnull
default DependencyResolverResult collect(@Nonnull DependencyResolverRequest request) { default DependencyResolverResult collect(@Nonnull DependencyResolverRequest request) {
@ -113,20 +121,17 @@ public interface DependencyResolver extends Service {
/** /**
* Flattens a list of nodes. * Flattens a list of nodes.
* Note that the {@code PathScope} argument should usually be null as the dependency tree has been
* filtered during collection for the appropriate scope.
* *
* @param session * @param session the {@link Session}, must not be {@code null}
* @param node * @param node the {@link Node} to flatten, must not be {@code null}
* @param scope * @param scope an optional {@link PathScope} to filter out dependencies
* @return * @return the flattened list of node
* @throws DependencyResolverException * @throws DependencyResolverException
*/ */
List<Node> flatten(Session session, Node node, PathScope scope) throws DependencyResolverException; List<Node> flatten(@Nonnull Session session, @Nonnull Node node, @Nullable PathScope scope)
throws DependencyResolverException;
@Nonnull
default DependencyResolverResult flatten(@Nonnull Session session, @Nonnull Project project) {
return flatten(
DependencyResolverRequest.build(session, DependencyResolverRequest.RequestType.FLATTEN, project));
}
@Nonnull @Nonnull
default DependencyResolverResult flatten( default DependencyResolverResult flatten(

View File

@ -81,7 +81,7 @@ public interface DependencyResolverRequest {
boolean getVerbose(); boolean getVerbose();
@Nullable @Nonnull
PathScope getPathScope(); PathScope getPathScope();
/** /**
@ -105,11 +105,17 @@ public interface DependencyResolverRequest {
@Nonnull @Nonnull
static DependencyResolverRequest build(Session session, RequestType requestType, Artifact rootArtifact) { static DependencyResolverRequest build(Session session, RequestType requestType, Artifact rootArtifact) {
return build(session, requestType, rootArtifact, PathScope.MAIN_RUNTIME);
}
@Nonnull
static DependencyResolverRequest build(
Session session, RequestType requestType, Artifact rootArtifact, PathScope scope) {
return new DependencyResolverRequestBuilder() return new DependencyResolverRequestBuilder()
.session(session) .session(session)
.requestType(requestType) .requestType(requestType)
.rootArtifact(rootArtifact) .rootArtifact(rootArtifact)
.pathScope(PathScope.MAIN_RUNTIME) .pathScope(scope)
.build(); .build();
} }
@ -395,7 +401,7 @@ public interface DependencyResolverRequest {
this.managedDependencies = this.managedDependencies =
unmodifiable(nonNull(managedDependencies, "managedDependencies cannot be null")); unmodifiable(nonNull(managedDependencies, "managedDependencies cannot be null"));
this.verbose = verbose; this.verbose = verbose;
this.pathScope = pathScope; this.pathScope = nonNull(pathScope, "pathScope cannot be null");
this.pathTypeFilter = (pathTypeFilter != null) ? pathTypeFilter : (t) -> true; this.pathTypeFilter = (pathTypeFilter != null) ? pathTypeFilter : (t) -> true;
this.repositories = repositories; this.repositories = repositories;
if (verbose && requestType != RequestType.COLLECT) { if (verbose && requestType != RequestType.COLLECT) {

View File

@ -720,37 +720,42 @@ public abstract class AbstractSession implements InternalSession {
* Shortcut for <code>getService(DependencyResolver.class).collect(...)</code> * Shortcut for <code>getService(DependencyResolver.class).collect(...)</code>
* *
* @throws DependencyResolverException if the dependency collection failed * @throws DependencyResolverException if the dependency collection failed
* @see DependencyResolver#collect(Session, Artifact) * @see DependencyResolver#collect(Session, Artifact, PathScope)
*/ */
@Nonnull @Nonnull
@Override @Override
public Node collectDependencies(@Nonnull Artifact artifact) { public Node collectDependencies(@Nonnull Artifact artifact, @Nonnull PathScope scope) {
return getService(DependencyResolver.class).collect(this, artifact).getRoot(); return getService(DependencyResolver.class)
.collect(this, artifact, scope)
.getRoot();
} }
/** /**
* Shortcut for <code>getService(DependencyResolver.class).collect(...)</code> * Shortcut for <code>getService(DependencyResolver.class).collect(...)</code>
* *
* @throws DependencyResolverException if the dependency collection failed * @throws DependencyResolverException if the dependency collection failed
* @see DependencyResolver#collect(Session, Project) * @see DependencyResolver#collect(Session, Project, PathScope)
*/ */
@Nonnull @Nonnull
@Override @Override
public Node collectDependencies(@Nonnull Project project) { public Node collectDependencies(@Nonnull Project project, @Nonnull PathScope scope) {
return getService(DependencyResolver.class).collect(this, project).getRoot(); return getService(DependencyResolver.class)
.collect(this, project, scope)
.getRoot();
} }
/** /**
* Shortcut for <code>getService(DependencyResolver.class).collect(...)</code> * Shortcut for <code>getService(DependencyResolver.class).collect(...)</code>
* *
* @throws DependencyResolverException if the dependency collection failed * @throws DependencyResolverException if the dependency collection failed
* @see DependencyResolver#collect(Session, DependencyCoordinates) * @see DependencyResolver#collect(Session, DependencyCoordinates, PathScope)
*/ */
@Nonnull @Nonnull
@Override @Override
public Node collectDependencies(@Nonnull DependencyCoordinates dependency) { public Node collectDependencies(@Nonnull DependencyCoordinates dependency, @Nonnull PathScope scope) {
Node root = Node root = getService(DependencyResolver.class)
getService(DependencyResolver.class).collect(this, dependency).getRoot(); .collect(this, dependency, scope)
.getRoot();
return root.getChildren().iterator().next(); return root.getChildren().iterator().next();
} }

View File

@ -39,6 +39,7 @@ import org.apache.maven.api.Project;
import org.apache.maven.api.RemoteRepository; import org.apache.maven.api.RemoteRepository;
import org.apache.maven.api.Session; import org.apache.maven.api.Session;
import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.annotations.Nullable;
import org.apache.maven.api.di.Named; import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Singleton; import org.apache.maven.api.di.Singleton;
import org.apache.maven.api.services.ArtifactResolver; import org.apache.maven.api.services.ArtifactResolver;
@ -56,6 +57,7 @@ import org.eclipse.aether.collection.CollectResult;
import org.eclipse.aether.collection.DependencyCollectionException; import org.eclipse.aether.collection.DependencyCollectionException;
import org.eclipse.aether.graph.DependencyFilter; import org.eclipse.aether.graph.DependencyFilter;
import org.eclipse.aether.graph.DependencyNode; import org.eclipse.aether.graph.DependencyNode;
import org.eclipse.aether.scope.ResolutionScope;
import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
import org.eclipse.aether.util.graph.transformer.ConflictResolver; import org.eclipse.aether.util.graph.transformer.ConflictResolver;
@ -96,12 +98,20 @@ public class DefaultDependencyResolver implements DependencyResolver {
remoteRepositories = remoteRepositories =
request.getRepositories() != null ? request.getRepositories() : session.getRemoteRepositories(); request.getRepositories() != null ? request.getRepositories() : session.getRemoteRepositories();
} }
ResolutionScope resolutionScope = null;
if (request.getPathScope() != null) {
resolutionScope = session.getSession()
.getScopeManager()
.getResolutionScope(request.getPathScope().id())
.orElseThrow();
}
CollectRequest collectRequest = new CollectRequest() CollectRequest collectRequest = new CollectRequest()
.setRootArtifact(rootArtifact != null ? session.toArtifact(rootArtifact) : null) .setRootArtifact(rootArtifact != null ? session.toArtifact(rootArtifact) : null)
.setRoot(root != null ? session.toDependency(root, false) : null) .setRoot(root != null ? session.toDependency(root, false) : null)
.setDependencies(session.toDependencies(dependencies, false)) .setDependencies(session.toDependencies(dependencies, false))
.setManagedDependencies(session.toDependencies(managedDependencies, true)) .setManagedDependencies(session.toDependencies(managedDependencies, true))
.setRepositories(session.toRepositories(remoteRepositories)); .setRepositories(session.toRepositories(remoteRepositories));
collectRequest.setResolutionScope(resolutionScope);
RepositorySystemSession systemSession = session.getSession(); RepositorySystemSession systemSession = session.getSession();
if (request.getVerbose()) { if (request.getVerbose()) {
@ -120,8 +130,10 @@ public class DefaultDependencyResolver implements DependencyResolver {
} }
} }
@Nonnull
@Override @Override
public List<Node> flatten(Session s, Node node, PathScope scope) throws DependencyResolverException { public List<Node> flatten(@Nonnull Session s, @Nonnull Node node, @Nullable PathScope scope)
throws DependencyResolverException {
InternalSession session = InternalSession.from(s); InternalSession session = InternalSession.from(s);
DependencyNode root = cast(AbstractNode.class, node, "node").getDependencyNode(); DependencyNode root = cast(AbstractNode.class, node, "node").getDependencyNode();
List<DependencyNode> dependencies = session.getRepositorySystem() List<DependencyNode> dependencies = session.getRepositorySystem()
@ -131,6 +143,9 @@ public class DefaultDependencyResolver implements DependencyResolver {
} }
private static DependencyFilter getScopeDependencyFilter(PathScope scope) { private static DependencyFilter getScopeDependencyFilter(PathScope scope) {
if (scope == null) {
return null;
}
Set<String> scopes = Set<String> scopes =
scope.dependencyScopes().stream().map(DependencyScope::id).collect(Collectors.toSet()); scope.dependencyScopes().stream().map(DependencyScope::id).collect(Collectors.toSet());
return (n, p) -> { return (n, p) -> {

View File

@ -61,10 +61,12 @@ import org.apache.maven.di.impl.DIException;
import org.apache.maven.internal.impl.AbstractSession; import org.apache.maven.internal.impl.AbstractSession;
import org.apache.maven.internal.impl.InternalSession; import org.apache.maven.internal.impl.InternalSession;
import org.apache.maven.internal.impl.di.SessionScope; import org.apache.maven.internal.impl.di.SessionScope;
import org.apache.maven.internal.impl.resolver.scopes.Maven4ScopeManagerConfiguration;
import org.eclipse.aether.DefaultRepositorySystemSession; import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystem; import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession; import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.impl.RemoteRepositoryManager; import org.eclipse.aether.impl.RemoteRepositoryManager;
import org.eclipse.aether.internal.impl.scope.ScopeManagerImpl;
import org.eclipse.aether.repository.LocalRepository; import org.eclipse.aether.repository.LocalRepository;
import org.eclipse.aether.repository.LocalRepositoryManager; import org.eclipse.aether.repository.LocalRepositoryManager;
@ -328,6 +330,7 @@ public class ApiRunner {
: properties.containsKey("env.MAVEN_HOME") ? Paths.get(properties.get("env.MAVEN_HOME")) : null; : properties.containsKey("env.MAVEN_HOME") ? Paths.get(properties.get("env.MAVEN_HOME")) : null;
DefaultRepositorySystemSession rsession = new DefaultRepositorySystemSession(h -> false); DefaultRepositorySystemSession rsession = new DefaultRepositorySystemSession(h -> false);
rsession.setScopeManager(new ScopeManagerImpl(Maven4ScopeManagerConfiguration.INSTANCE));
rsession.setSystemProperties(properties); rsession.setSystemProperties(properties);
rsession.setConfigProperties(properties); rsession.setConfigProperties(properties);

View File

@ -24,6 +24,7 @@ import java.nio.file.Paths;
import org.apache.maven.api.ArtifactCoordinates; import org.apache.maven.api.ArtifactCoordinates;
import org.apache.maven.api.DownloadedArtifact; import org.apache.maven.api.DownloadedArtifact;
import org.apache.maven.api.Node; import org.apache.maven.api.Node;
import org.apache.maven.api.PathScope;
import org.apache.maven.api.Session; import org.apache.maven.api.Session;
import org.apache.maven.api.services.ModelBuilder; import org.apache.maven.api.services.ModelBuilder;
import org.apache.maven.api.services.ModelBuilderRequest; import org.apache.maven.api.services.ModelBuilderRequest;
@ -58,8 +59,8 @@ class TestApiStandalone {
assertNotNull(res.getPath()); assertNotNull(res.getPath());
assertTrue(Files.exists(res.getPath())); assertTrue(Files.exists(res.getPath()));
Node node = session.collectDependencies(session.createDependencyCoordinates(coords)); Node node = session.collectDependencies(session.createDependencyCoordinates(coords), PathScope.MAIN_RUNTIME);
assertNotNull(node); assertNotNull(node);
assertEquals(8, node.getChildren().size()); assertEquals(6, node.getChildren().size());
} }
} }

View File

@ -642,8 +642,9 @@ public class DefaultMavenPluginManager implements MavenPluginManager {
} }
} else { } else {
// collection // collection
DependencyResolverResult res = DependencyResolverResult res = sessionV4
sessionV4.getService(DependencyResolver.class).collect(sessionV4, project); .getService(DependencyResolver.class)
.collect(sessionV4, project, PathScope.MAIN_RUNTIME);
if (field.getType() == DependencyResolverResult.class) { if (field.getType() == DependencyResolverResult.class) {
result = res; result = res;
} else if (field.getType() == Node.class) { } else if (field.getType() == Node.class) {

View File

@ -176,7 +176,7 @@ class TestApi {
void testCollectArtifactDependencies() { void testCollectArtifactDependencies() {
Artifact artifact = Artifact artifact =
session.createArtifact("org.codehaus.plexus", "plexus-container-default", "1.0-alpha-32", "jar"); session.createArtifact("org.codehaus.plexus", "plexus-container-default", "1.0-alpha-32", "jar");
Node root = session.collectDependencies(artifact); Node root = session.collectDependencies(artifact, PathScope.MAIN_RUNTIME);
assertNotNull(root); assertNotNull(root);
} }
@ -236,7 +236,7 @@ class TestApi {
assertNotNull(project); assertNotNull(project);
Artifact artifact = session.createArtifact("org.apache.maven.core.test", "test-extension", "1", "jar"); Artifact artifact = session.createArtifact("org.apache.maven.core.test", "test-extension", "1", "jar");
Node root = session.collectDependencies(artifact); Node root = session.collectDependencies(artifact, PathScope.MAIN_RUNTIME);
assertNotNull(root); assertNotNull(root);
DependencyResolverResult result = DependencyResolverResult result =