From f953475fb6028401ebc82f11c7834baec56fd58e Mon Sep 17 00:00:00 2001 From: Vaclav Haisman Date: Sun, 2 Aug 2026 12:07:33 +0200 Subject: [PATCH] [MDEP-870] Overwrite copied artifact POMs When dependency:copy-dependencies copies an artifact, also overwrite its associated POM so version-stripped output cannot mix versions. Preserve copy-only-if-missing behavior for artifacts skipped by the overwrite policy. Fixes #1370 --- .../CopyDependenciesMojo.java | 12 ++- .../TestCopyDependenciesMojo.java | 81 +++++++++++++++++++ 2 files changed, 90 insertions(+), 3 deletions(-) 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 43a385035..6b820480f 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 @@ -170,9 +170,9 @@ protected void doExecute() throws MojoExecutionException { } if (isCopyPom() && !useRepositoryLayout) { - copyPoms(getOutputDirectory(), artifacts, this.stripVersion); - copyPoms(getOutputDirectory(), skippedArtifacts, this.stripVersion, this.stripClassifier); + copyPoms(getOutputDirectory(), artifacts, this.stripVersion, this.stripClassifier, true); // Artifacts that already exist may not yet have poms + copyPoms(getOutputDirectory(), skippedArtifacts, this.stripVersion, this.stripClassifier, false); } } @@ -341,6 +341,12 @@ public void copyPoms(File destDir, Set artifacts, boolean removeVersio */ public void copyPoms(File destDir, Set artifacts, boolean removeVersion, boolean removeClassifier) throws MojoExecutionException { + copyPoms(destDir, artifacts, removeVersion, removeClassifier, false); + } + + private void copyPoms( + File destDir, Set artifacts, boolean removeVersion, boolean removeClassifier, boolean overwrite) + throws MojoExecutionException { for (Artifact artifact : artifacts) { Artifact pomArtifact = getResolvedPomArtifact(artifact); @@ -353,7 +359,7 @@ public void copyPoms(File destDir, Set artifacts, boolean removeVersio destDir, DependencyUtil.getFormattedFileName( pomArtifact, removeVersion, prependGroupId, useBaseVersion, removeClassifier)); - if (!pomDestFile.exists()) { + if (overwrite || !pomDestFile.exists()) { try { copyUtil.copyArtifactFile(pomArtifact, pomDestFile); } catch (IOException e) { diff --git a/src/test/java/org/apache/maven/plugins/dependency/fromDependencies/TestCopyDependenciesMojo.java b/src/test/java/org/apache/maven/plugins/dependency/fromDependencies/TestCopyDependenciesMojo.java index 5527f0d31..83715c63c 100644 --- a/src/test/java/org/apache/maven/plugins/dependency/fromDependencies/TestCopyDependenciesMojo.java +++ b/src/test/java/org/apache/maven/plugins/dependency/fromDependencies/TestCopyDependenciesMojo.java @@ -22,6 +22,8 @@ import java.io.File; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.HashSet; import java.util.Set; @@ -47,6 +49,9 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; @MojoTest(realRepositorySession = true) class TestCopyDependenciesMojo { @@ -775,6 +780,82 @@ void testCopyPom(CopyDependenciesMojo mojo) throws Exception { } } + @Test + @InjectMojo(goal = "copy-dependencies") + void testCopyPomOverwritesExistingPomWhenArtifactIsCopied(CopyDependenciesMojo mojo) throws Exception { + Artifact artifact = stubFactory.createArtifact("org.example", "artifact", "2.0", Artifact.SCOPE_COMPILE); + Artifact pomArtifact = + stubFactory.createArtifact("org.example", "artifact", "2.0", Artifact.SCOPE_COMPILE, "pom", null); + writeFile(artifact.getFile(), "new jar"); + writeFile(pomArtifact.getFile(), "new pom"); + + Set artifacts = new HashSet<>(); + artifacts.add(artifact); + mojo.getProject().setArtifacts(artifacts); + + CopyDependenciesMojo mojoSpy = spy(mojo); + doReturn(pomArtifact).when(mojoSpy).getResolvedPomArtifact(any(Artifact.class)); + mojoSpy.setCopyPom(true); + mojoSpy.setStripVersion(true); + mojoSpy.overWriteReleases = true; + mojoSpy.overWriteIfNewer = false; + + File jarDestination = new File(mojoSpy.outputDirectory, "artifact.jar"); + File pomDestination = new File(mojoSpy.outputDirectory, "artifact.pom"); + writeFile(jarDestination, "old jar"); + writeFile(pomDestination, "old pom"); + + mojoSpy.execute(); + + assertEquals("new jar", readFile(jarDestination)); + assertEquals("new pom", readFile(pomDestination)); + } + + @Test + @InjectMojo(goal = "copy-dependencies") + void testCopyPomForSkippedArtifactOnlyWhenMissing(CopyDependenciesMojo mojo) throws Exception { + Artifact artifact = stubFactory.createArtifact("org.example", "artifact", "2.0", Artifact.SCOPE_COMPILE); + Artifact pomArtifact = + stubFactory.createArtifact("org.example", "artifact", "2.0", Artifact.SCOPE_COMPILE, "pom", null); + writeFile(artifact.getFile(), "new jar"); + writeFile(pomArtifact.getFile(), "new pom"); + + Set artifacts = new HashSet<>(); + artifacts.add(artifact); + mojo.getProject().setArtifacts(artifacts); + + CopyDependenciesMojo mojoSpy = spy(mojo); + doReturn(pomArtifact).when(mojoSpy).getResolvedPomArtifact(any(Artifact.class)); + mojoSpy.setCopyPom(true); + mojoSpy.setStripVersion(true); + mojoSpy.overWriteReleases = false; + mojoSpy.overWriteIfNewer = false; + + File jarDestination = new File(mojoSpy.outputDirectory, "artifact.jar"); + File pomDestination = new File(mojoSpy.outputDirectory, "artifact.pom"); + writeFile(jarDestination, "old jar"); + + mojoSpy.execute(); + + assertEquals("old jar", readFile(jarDestination)); + assertEquals("new pom", readFile(pomDestination)); + + writeFile(pomDestination, "existing pom"); + mojoSpy.execute(); + + assertEquals("old jar", readFile(jarDestination)); + assertEquals("existing pom", readFile(pomDestination)); + } + + private static void writeFile(File file, String contents) throws IOException { + Files.createDirectories(file.getParentFile().toPath()); + Files.write(file.toPath(), contents.getBytes(StandardCharsets.UTF_8)); + } + + private static String readFile(File file) throws IOException { + return new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8); + } + @Test @InjectMojo(goal = "copy-dependencies") void testPrependGroupId(CopyDependenciesMojo mojo) throws Exception {