This is an automated email from the ASF dual-hosted git repository. elharo pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/maven-dependency-plugin.git
The following commit(s) were added to refs/heads/master by this push: new 6fa66043 [MDEP-776] Warn when multiple dependencies have the same file name (#463) 6fa66043 is described below commit 6fa66043341b83a4e2ae49366c7edc2279c5a044 Author: Elliotte Rusty Harold <elh...@users.noreply.github.com> AuthorDate: Fri Dec 6 13:34:42 2024 +0000 [MDEP-776] Warn when multiple dependencies have the same file name (#463) * Warn when overwriting file --- .../invoker.properties | 18 +++++ .../copy-dependencies-with-conflict/pom.xml | 77 ++++++++++++++++++++++ .../copy-dependencies-with-conflict/verify.groovy | 31 +++++++++ .../dependency/fromConfiguration/ArtifactItem.java | 12 ++-- .../dependency/fromConfiguration/CopyMojo.java | 11 ++-- .../fromDependencies/CopyDependenciesMojo.java | 48 +++++++++----- .../maven/plugins/dependency/utils/CopyUtil.java | 6 +- 7 files changed, 174 insertions(+), 29 deletions(-) diff --git a/src/it/projects/copy-dependencies-with-conflict/invoker.properties b/src/it/projects/copy-dependencies-with-conflict/invoker.properties new file mode 100644 index 00000000..f50e476f --- /dev/null +++ b/src/it/projects/copy-dependencies-with-conflict/invoker.properties @@ -0,0 +1,18 @@ +# 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. + +invoker.goals = clean process-sources diff --git a/src/it/projects/copy-dependencies-with-conflict/pom.xml b/src/it/projects/copy-dependencies-with-conflict/pom.xml new file mode 100644 index 00000000..b7c6cf62 --- /dev/null +++ b/src/it/projects/copy-dependencies-with-conflict/pom.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ 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. + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>org.apache.maven.its.dependency</groupId> + <artifactId>test</artifactId> + <version>1.0-SNAPSHOT</version> + + <name>Test with conflicts</name> + <description> + Test dependency:copy-dependencies with conflicting artifact IDs + </description> + + + <dependencies> + <!-- need two deps that have same version and artifact ID but different group ID --> + <dependency> + <groupId>org.jdom</groupId> + <artifactId>jdom</artifactId> + <version>1.1.3</version> + </dependency> + <dependency> + <groupId>org.lucee</groupId> + <artifactId>jdom</artifactId> + <version>1.1.3</version> + </dependency> + </dependencies> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <build> + + <defaultGoal>package</defaultGoal> + + <plugins> + <plugin> + <artifactId>maven-dependency-plugin</artifactId> + <version>@project.version@</version> + <executions> + <execution> + <id>test-2</id> + <goals> + <goal>copy-dependencies</goal> + </goals> + <configuration> + <copyPom>true</copyPom> + <outputDirectory>${project.build.directory}/it/copy-dep-test-2</outputDirectory> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> diff --git a/src/it/projects/copy-dependencies-with-conflict/verify.groovy b/src/it/projects/copy-dependencies-with-conflict/verify.groovy new file mode 100644 index 00000000..b66deb08 --- /dev/null +++ b/src/it/projects/copy-dependencies-with-conflict/verify.groovy @@ -0,0 +1,31 @@ +/* + * 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( '[WARNING] Overwriting ' ) +assert buildLog.contains( '[DEBUG] Copying artifact \'org.jdom:jdom:jar:1.1.3\'' ) +assert buildLog.contains( '[DEBUG] Copying artifact \'org.jdom:jdom:pom:1.1.3\'' ) +assert buildLog.contains( '[DEBUG] Copying artifact \'org.jdom:jdom:jar:1.1.3\'' ) +assert buildLog.contains( '[DEBUG] Copying artifact \'org.lucee:jdom:jar:1.1.3\'' ) +assert buildLog.contains( '[WARNING] Multiple files with the name jdom-1.1.3.jar in the dependency tree.' ) + +return true diff --git a/src/main/java/org/apache/maven/plugins/dependency/fromConfiguration/ArtifactItem.java b/src/main/java/org/apache/maven/plugins/dependency/fromConfiguration/ArtifactItem.java index ff9e5b39..b98b4567 100644 --- a/src/main/java/org/apache/maven/plugins/dependency/fromConfiguration/ArtifactItem.java +++ b/src/main/java/org/apache/maven/plugins/dependency/fromConfiguration/ArtifactItem.java @@ -36,8 +36,7 @@ import org.codehaus.plexus.components.io.filemappers.FileMapper; */ public class ArtifactItem implements DependableCoordinate { /** - * Group Id of Artifact - * + * Group ID of Artifact */ @Parameter(required = true) private String groupId; @@ -56,7 +55,6 @@ public class ArtifactItem implements DependableCoordinate { /** * Type of Artifact (War,Jar,etc) - * */ @Parameter(required = true) private String type = "jar"; @@ -90,9 +88,6 @@ public class ArtifactItem implements DependableCoordinate { @Parameter private String encoding; - /** - * - */ private boolean needsProcessing; /** @@ -147,6 +142,7 @@ public class ArtifactItem implements DependableCoordinate { /** * @return Returns the artifactId. */ + @Override public String getArtifactId() { return artifactId; } @@ -161,6 +157,7 @@ public class ArtifactItem implements DependableCoordinate { /** * @return Returns the groupId. */ + @Override public String getGroupId() { return groupId; } @@ -175,6 +172,7 @@ public class ArtifactItem implements DependableCoordinate { /** * @return Returns the type. */ + @Override public String getType() { return type; } @@ -189,6 +187,7 @@ public class ArtifactItem implements DependableCoordinate { /** * @return Returns the version. */ + @Override public String getVersion() { return version; } @@ -210,6 +209,7 @@ public class ArtifactItem implements DependableCoordinate { /** * @return Classifier. */ + @Override public String getClassifier() { return classifier; } diff --git a/src/main/java/org/apache/maven/plugins/dependency/fromConfiguration/CopyMojo.java b/src/main/java/org/apache/maven/plugins/dependency/fromConfiguration/CopyMojo.java index a9b9ba88..e9ad6d73 100644 --- a/src/main/java/org/apache/maven/plugins/dependency/fromConfiguration/CopyMojo.java +++ b/src/main/java/org/apache/maven/plugins/dependency/fromConfiguration/CopyMojo.java @@ -101,11 +101,12 @@ public class CopyMojo extends AbstractFromConfigurationMojo { List<ArtifactItem> theArtifactItems = getProcessedArtifactItems( new ProcessArtifactItemsRequest(stripVersion, prependGroupId, useBaseVersion, stripClassifier)); + for (ArtifactItem artifactItem : theArtifactItems) { if (artifactItem.isNeedsProcessing()) { copyArtifact(artifactItem); } else { - this.getLog().info(artifactItem + " already exists in " + artifactItem.getOutputDirectory()); + getLog().info(artifactItem + " already exists in " + artifactItem.getOutputDirectory()); } } } @@ -113,13 +114,15 @@ public class CopyMojo extends AbstractFromConfigurationMojo { /** * Resolves the artifact from the repository and copies it to the specified location. * - * @param artifactItem containing the information about the Artifact to copy. - * @throws MojoExecutionException with a message if an error occurs. + * @param artifactItem containing the information about the artifact to copy + * @throws MojoExecutionException with a message if an error occurs * @see CopyUtil#copyArtifactFile(Artifact, File) */ protected void copyArtifact(ArtifactItem artifactItem) throws MojoExecutionException { File destFile = new File(artifactItem.getOutputDirectory(), artifactItem.getDestFileName()); - + if (destFile.exists()) { + getLog().warn("Overwriting " + destFile); + } try { copyUtil.copyArtifactFile(artifactItem.getArtifact(), destFile); } catch (IOException e) { diff --git a/src/main/java/org/apache/maven/plugins/dependency/fromDependencies/CopyDependenciesMojo.java b/src/main/java/org/apache/maven/plugins/dependency/fromDependencies/CopyDependenciesMojo.java index 01e15040..f8b18023 100644 --- a/src/main/java/org/apache/maven/plugins/dependency/fromDependencies/CopyDependenciesMojo.java +++ b/src/main/java/org/apache/maven/plugins/dependency/fromDependencies/CopyDependenciesMojo.java @@ -23,6 +23,8 @@ import javax.inject.Inject; import java.io.File; import java.io.IOException; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.Set; import org.apache.maven.RepositoryUtils; @@ -44,7 +46,10 @@ import org.eclipse.aether.resolution.ArtifactResolutionException; import org.eclipse.aether.util.artifact.SubArtifact; /** - * Goal that copies the project dependencies from the repository to a defined location. + * Goal that copies the files for a project's dependencies from the repository to a directory. + * The default location to copy to is target/dependencies. + * Since all files are copied to the same directory by default, a dependency that + * has the same file name as another dependency will be overwritten. * * @author <a href="mailto:bri...@apache.org">Brian Fox</a> * @since 1.0 @@ -95,7 +100,7 @@ public class CopyDependenciesMojo extends AbstractFromDependenciesMojo { /** * Main entry into mojo. Gets the list of dependencies and iterates through calling copyArtifact. * - * @throws MojoExecutionException with a message if an error occurs. + * @throws MojoExecutionException with a message if an error occurs * @see #getDependencySets(boolean, boolean) * @see #copyArtifact(Artifact, boolean, boolean, boolean, boolean) */ @@ -105,6 +110,21 @@ public class CopyDependenciesMojo extends AbstractFromDependenciesMojo { Set<Artifact> artifacts = dss.getResolvedDependencies(); if (!useRepositoryLayout) { + Map<String, Integer> copies = new HashMap<>(); + for (Artifact artifactItem : artifacts) { + String destFileName = DependencyUtil.getFormattedFileName( + artifactItem, stripVersion, prependGroupId, useBaseVersion, stripClassifier); + int numCopies = copies.getOrDefault(destFileName, 0); + copies.put(destFileName, numCopies + 1); + } + for (Map.Entry<String, Integer> entry : copies.entrySet()) { + if (entry.getValue() > 1) { + getLog().warn("Multiple files with the name " + entry.getKey() + " in the dependency tree."); + getLog().warn( + "Not all JARs will be available. Consider using prependGroupId, useSubDirectoryPerArtifact, or useRepositoryLayout."); + } + } + for (Artifact artifact : artifacts) { copyArtifact( artifact, isStripVersion(), this.prependGroupId, this.useBaseVersion, this.stripClassifier); @@ -123,19 +143,13 @@ public class CopyDependenciesMojo extends AbstractFromDependenciesMojo { if (isCopyPom() && !useRepositoryLayout) { copyPoms(getOutputDirectory(), artifacts, this.stripVersion); - copyPoms(getOutputDirectory(), skippedArtifacts, this.stripVersion, this.stripClassifier); // Artifacts - // that already - // exist may - // not yet have - // poms + copyPoms(getOutputDirectory(), skippedArtifacts, this.stripVersion, this.stripClassifier); + // Artifacts that already exist may not yet have poms } } /** - * install the artifact and the corresponding pom if copyPoms=true - * - * @param artifact - * @param buildingRequest + * Install the artifact and the corresponding pom if copyPoms=true. */ private void installArtifact(Artifact artifact, ProjectBuildingRequest buildingRequest) { try { @@ -193,7 +207,7 @@ public class CopyDependenciesMojo extends AbstractFromDependenciesMojo { * @param artifact representing the object to be copied. * @param removeVersion specifies if the version should be removed from the file name when copying. * @param prependGroupId specifies if the groupId should be prepend to the file while copying. - * @param theUseBaseVersion specifies if the baseVersion of the artifact should be used instead of the version. + * @param useBaseVersion specifies if the baseVersion of the artifact should be used instead of the version. * @param removeClassifier specifies if the classifier should be removed from the file name when copying. * @throws MojoExecutionException with a message if an error occurs. * @see CopyUtil#copyArtifactFile(Artifact, File) @@ -203,12 +217,12 @@ public class CopyDependenciesMojo extends AbstractFromDependenciesMojo { Artifact artifact, boolean removeVersion, boolean prependGroupId, - boolean theUseBaseVersion, + boolean useBaseVersion, boolean removeClassifier) throws MojoExecutionException { String destFileName = DependencyUtil.getFormattedFileName( - artifact, removeVersion, prependGroupId, theUseBaseVersion, removeClassifier); + artifact, removeVersion, prependGroupId, useBaseVersion, removeClassifier); File destDir = DependencyUtil.getFormattedOutputDirectory( useSubDirectoryPerScope, @@ -220,7 +234,9 @@ public class CopyDependenciesMojo extends AbstractFromDependenciesMojo { outputDirectory, artifact); File destFile = new File(destDir, destFileName); - + if (destFile.exists()) { + getLog().warn("Overwriting " + destFile); + } try { copyUtil.copyArtifactFile(artifact, destFile); } catch (IOException e) { @@ -323,7 +339,7 @@ public class CopyDependenciesMojo extends AbstractFromDependenciesMojo { } /** - * @param copyPom - true if the pom of each artifact must be copied + * @param copyPom true if the pom of each artifact must be copied */ public void setCopyPom(boolean copyPom) { this.copyPom = copyPom; diff --git a/src/main/java/org/apache/maven/plugins/dependency/utils/CopyUtil.java b/src/main/java/org/apache/maven/plugins/dependency/utils/CopyUtil.java index b175fb70..f83bb15c 100644 --- a/src/main/java/org/apache/maven/plugins/dependency/utils/CopyUtil.java +++ b/src/main/java/org/apache/maven/plugins/dependency/utils/CopyUtil.java @@ -51,9 +51,9 @@ public class CopyUtil { } /** - * Copies the artifact (file). + * Copies the artifact (file) * - * @param sourceArtifact represents the artifact (file) to copy + * @param sourceArtifact the artifact (file) to copy * @param destination file name of destination file * @throws IOException if copy has failed * @throws MojoExecutionException if artifact file is a directory (which has not been packaged yet) @@ -68,7 +68,7 @@ public class CopyUtil { + "' has not been packaged yet (is a directory). When used on reactor artifact, " + "copy should be executed after packaging: see MDEP-187."); } - logger.debug("Copying artifact '{}' ({}) to {}", sourceArtifact, sourceArtifact.getFile(), destination); + logger.debug("Copying artifact '{}' ({}) to {}", sourceArtifact.getId(), sourceArtifact.getFile(), destination); FileUtils.copyFile(source, destination); buildContext.refresh(destination); }