From fb5c02af63742090e96c1bfb11a69afcd4d7e9cf Mon Sep 17 00:00:00 2001 From: Slawomir Jaranowski Date: Thu, 6 Apr 2023 00:43:01 +0200 Subject: [PATCH] [MDEP-853] list-repositories - improvements - use Resolver API instead of m-a-t - add information about mirrored repositories --- src/it/projects/list-repositories/pom.xml | 101 ++++++------ .../projects/list-repositories/verify.groovy | 28 ++++ .../dependency/ListRepositoriesMojo.java | 149 ++++++++++++++++++ .../resolvers/ListRepositoriesMojo.java | 66 -------- src/site/apt/index.apt.vm | 3 +- 5 files changed, 233 insertions(+), 114 deletions(-) create mode 100644 src/it/projects/list-repositories/verify.groovy create mode 100644 src/main/java/org/apache/maven/plugins/dependency/ListRepositoriesMojo.java delete mode 100644 src/main/java/org/apache/maven/plugins/dependency/resolvers/ListRepositoriesMojo.java diff --git a/src/it/projects/list-repositories/pom.xml b/src/it/projects/list-repositories/pom.xml index 5b3be7983..d74bc248d 100644 --- a/src/it/projects/list-repositories/pom.xml +++ b/src/it/projects/list-repositories/pom.xml @@ -1,47 +1,54 @@ - - - - - 4.0.0 - - org.apache.maven.its.dependency - test - 1.0-SNAPSHOT - - Test - - Test dependency:list-repositories - - - - UTF-8 - - - - - org.apache.maven - maven-project - 2.0.6 - - - - + + + + + 4.0.0 + + org.apache.maven.its.dependency + test + 1.0-SNAPSHOT + + Test + + Test dependency:list-repositories + + + + UTF-8 + + + + + fake-remote-repository + http://localhost:2345 + + + + + + org.apache.maven + maven-core + 3.2.5 + + + + \ No newline at end of file diff --git a/src/it/projects/list-repositories/verify.groovy b/src/it/projects/list-repositories/verify.groovy new file mode 100644 index 000000000..be64953d9 --- /dev/null +++ b/src/it/projects/list-repositories/verify.groovy @@ -0,0 +1,28 @@ +/* + * 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. + */ + +File file = new File( basedir, "build.log" ); +assert file.exists(); + +String buildLog = file.getText( "UTF-8" ); +assert buildLog.contains( 'Project remote repositories used by this build:'); +assert buildLog.contains( '* fake-remote-repository (http://localhost:2345, default, releases+snapshots)'); +assert buildLog.contains( '* sonatype-nexus-snapshots (https://oss.sonatype.org/content/repositories/snapshots, default, snapshots) mirrored by mrm-maven-plugin'); +assert buildLog.contains( '* central (https://repo.maven.apache.org/maven2, default, releases) mirrored by mrm-maven-plugin'); + diff --git a/src/main/java/org/apache/maven/plugins/dependency/ListRepositoriesMojo.java b/src/main/java/org/apache/maven/plugins/dependency/ListRepositoriesMojo.java new file mode 100644 index 000000000..81d402c13 --- /dev/null +++ b/src/main/java/org/apache/maven/plugins/dependency/ListRepositoriesMojo.java @@ -0,0 +1,149 @@ +/* + * 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. + */ +package org.apache.maven.plugins.dependency; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import org.apache.maven.RepositoryUtils; +import org.apache.maven.model.DependencyManagement; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Mojo; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.artifact.ArtifactTypeRegistry; +import org.eclipse.aether.collection.CollectRequest; +import org.eclipse.aether.collection.CollectResult; +import org.eclipse.aether.collection.DependencyCollectionException; +import org.eclipse.aether.graph.DependencyNode; +import org.eclipse.aether.graph.DependencyVisitor; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.util.graph.visitor.TreeDependencyVisitor; + +/** + * Goal that collect all project dependencies and then lists the repositories used by the build and by the transitive + * dependencies + * + * @author Brian Fox + * @since 2.2 + */ +@Mojo(name = "list-repositories", threadSafe = true) +public class ListRepositoriesMojo extends AbstractDependencyMojo { + + @Component + RepositorySystem repositorySystem; + + /** + * Displays a list of the repositories used by this build. + * + * @throws MojoExecutionException with a message if an error occurs. + */ + @Override + protected void doExecute() throws MojoExecutionException { + + CollectRequest request = new CollectRequest(); + request.setRepositories(getProject().getRemoteProjectRepositories()); + request.setRootArtifact(RepositoryUtils.toArtifact(getProject().getArtifact())); + + ArtifactTypeRegistry artifactTypeRegistry = + session.getRepositorySession().getArtifactTypeRegistry(); + + request.setDependencies(getProject().getDependencies().stream() + .map(d -> RepositoryUtils.toDependency(d, artifactTypeRegistry)) + .collect(Collectors.toList())); + + request.setManagedDependencies(Optional.ofNullable(getProject().getDependencyManagement()) + .map(DependencyManagement::getDependencies) + .orElseGet(Collections::emptyList) + .stream() + .map(d -> RepositoryUtils.toDependency(d, artifactTypeRegistry)) + .collect(Collectors.toList())); + + try { + CollectResult collectResult = repositorySystem.collectDependencies(session.getRepositorySession(), request); + Set repositories = new HashSet<>(); + collectResult.getRoot().accept(new TreeDependencyVisitor(new DependencyVisitor() { + @Override + public boolean visitEnter(DependencyNode node) { + repositories.addAll(node.getRepositories()); + return true; + } + + @Override + public boolean visitLeave(DependencyNode node) { + return true; + } + })); + + StringBuilder message = new StringBuilder(); + + Map> repoGroupByMirrors = repositories.stream() + .collect(Collectors.groupingBy( + repo -> repo.getMirroredRepositories().isEmpty())); + + prepareRemoteRepositoriesList(message, repoGroupByMirrors.get(Boolean.TRUE)); + prepareRemoteMirrorRepositoriesList(message, repoGroupByMirrors.get(Boolean.FALSE)); + + getLog().info(message); + + } catch (DependencyCollectionException e) { + throw new MojoExecutionException(e.getMessage(), e); + } + } + + private void prepareRemoteMirrorRepositoriesList( + StringBuilder message, Collection remoteProjectRepositories) { + + Map mirrorMap = new HashMap<>(); + remoteProjectRepositories.forEach(repo -> { + repo.getMirroredRepositories().forEach(mrepo -> mirrorMap.put(mrepo, repo)); + }); + + mirrorMap.forEach((repo, mirror) -> message.append(" * ") + .append(repo) + .append(" mirrored by ") + .append(mirror) + .append(System.lineSeparator())); + } + + private void prepareRemoteRepositoriesList( + StringBuilder message, Collection remoteProjectRepositories) { + + message.append("Project remote repositories used by this build:").append(System.lineSeparator()); + + remoteProjectRepositories.forEach( + repo -> message.append(" * ").append(repo).append(System.lineSeparator())); + } + + private Map getMirroredRepo(Set repositories) { + Map mirrorMap = new HashMap<>(); + + repositories.stream() + .filter(repo -> !repo.getMirroredRepositories().isEmpty()) + .forEach(repo -> repo.getMirroredRepositories().forEach(mrepo -> mirrorMap.put(mrepo, repo))); + + return mirrorMap; + } +} diff --git a/src/main/java/org/apache/maven/plugins/dependency/resolvers/ListRepositoriesMojo.java b/src/main/java/org/apache/maven/plugins/dependency/resolvers/ListRepositoriesMojo.java deleted file mode 100644 index 59a785ce3..000000000 --- a/src/main/java/org/apache/maven/plugins/dependency/resolvers/ListRepositoriesMojo.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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. - */ -package org.apache.maven.plugins.dependency.resolvers; - -import org.apache.maven.artifact.repository.ArtifactRepository; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugins.annotations.Component; -import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.plugins.annotations.ResolutionScope; -import org.apache.maven.plugins.dependency.AbstractDependencyMojo; -import org.apache.maven.shared.transfer.dependencies.collect.CollectorResult; -import org.apache.maven.shared.transfer.dependencies.collect.DependencyCollector; -import org.apache.maven.shared.transfer.dependencies.collect.DependencyCollectorException; - -/** - * Goal that resolves all project dependencies and then lists the repositories used by the build and by the transitive - * dependencies - * - * @author Brian Fox - * @since 2.2 - */ -@Mojo(name = "list-repositories", requiresDependencyResolution = ResolutionScope.TEST, threadSafe = true) -public class ListRepositoriesMojo extends AbstractDependencyMojo { - /** - * Dependency collector, needed to resolve dependencies. - */ - @Component(role = DependencyCollector.class) - private DependencyCollector dependencyCollector; - - /** - * Displays a list of the repositories used by this build. - * - * @throws MojoExecutionException with a message if an error occurs. - */ - @Override - protected void doExecute() throws MojoExecutionException { - try { - CollectorResult collectResult = dependencyCollector.collectDependencies( - session.getProjectBuildingRequest(), getProject().getModel()); - - this.getLog().info("Repositories used by this build:"); - - for (ArtifactRepository repo : collectResult.getRemoteRepositories()) { - this.getLog().info(repo.toString()); - } - } catch (DependencyCollectorException e) { - throw new MojoExecutionException("Unable to resolve artifacts", e); - } - } -} diff --git a/src/site/apt/index.apt.vm b/src/site/apt/index.apt.vm index 07e678e26..4cae408d4 100644 --- a/src/site/apt/index.apt.vm +++ b/src/site/apt/index.apt.vm @@ -74,7 +74,8 @@ ${project.name} *{{{./list-classes-mojo.html}dependency:list-classes}} displays the fully package-qualified names of all classes found in a specified artifact. - *{{{./list-repositories-mojo.html}dependency:list-repositories}} displays all project dependencies and then lists the repositories used. + *{{{./list-repositories-mojo.html}dependency:list-repositories}} collect all project dependencies and then lists the repositories + used by the build and by the transitive dependencies. *{{{./properties-mojo.html}dependency:properties}} set a property for each project dependency containing the to the artifact on the file system.