Repository: asciidoctor/asciidoctor-maven-plugin
Pull request #731 (2024-01-05 16:37:27)

(v2.2.x) Return maven-filtering to v3.3.0 from v3.3.1
**What kind of change does this PR introduce?** (check at least one)

- [ ] Bugfix
- [ ] Feature
- [ ] Documentation
- [ ] Refactor
- [ ] Build improvement
- [x] Other (please describe)

Avoid upstream bug.

**What is the goal of this pull request?**

v3.3.1 introduced a change that causes confusing output when using 'project.baseDir' for resources path.
See https://issues.apache.org/jira/browse/MSHARED-1175

The old message when copying resouces is fine.
```
Copying 118 resources
```

But the new, while less informative, omits the source after "from" in some cases.
```
Copying 118 resources from  to target/generated-docs
```

**Are there any alternative ways to implement this?**

No. I don't think we are loosing anything with the revert.

**Are there any implications of this pull request? Anything a user must know?**


**Is it related to an existing issue?**
<!-- If Yes, please add a line of the form: `Fixes #Issue` --> 
- [ ] Yes
- [x] No

*Finally, please add a corresponding entry to CHANGELOG.adoc*



Patch:
diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc
index 2bc3420..c44774d 100644
--- a/CHANGELOG.adoc
+++ b/CHANGELOG.adoc
@@ -16,6 +16,7 @@ For a detailed view of what has changed, refer to the {uri-repo}/commits/main[co
 Bug Fixes::
 
   * Remove Java 'requires open access' module warning in modern Java versions with JRuby v9.4.5.0 (#553)
+  * Check for both destinationDir and toDir when to avoid invalid "Duplicated destination found" messages, and improve warning message (#728)
 
 Build / Infrastructure::
 
diff --git a/pom.xml b/pom.xml
index 493a168..2e31259 100644
--- a/pom.xml
+++ b/pom.xml
@@ -80,7 +80,7 @@
         <maven.jacoco.plugin.version>0.8.11</maven.jacoco.plugin.version>
         <maven.plugin.plugin.version>3.9.0</maven.plugin.plugin.version>
         <maven.project.version>3.8.5</maven.project.version>
-        <maven.filtering.version>3.3.1</maven.filtering.version>
+        <maven.filtering.version>3.3.0</maven.filtering.version>
         <plexus.utils.version>3.5.1</plexus.utils.version>
         <plexus.component.metadata.version>2.1.1</plexus.component.metadata.version>
         <netty.version>4.1.104.Final</netty.version>
@@ -352,7 +352,7 @@
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-surefire-plugin</artifactId>
-                    <version>3.2.3</version>
+                    <version>3.2.5</version>
                 </plugin>
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
diff --git a/src/main/java/org/asciidoctor/maven/AsciidoctorMojo.java b/src/main/java/org/asciidoctor/maven/AsciidoctorMojo.java
index 95782c7..1703715 100644
--- a/src/main/java/org/asciidoctor/maven/AsciidoctorMojo.java
+++ b/src/main/java/org/asciidoctor/maven/AsciidoctorMojo.java
@@ -1,5 +1,6 @@
 package org.asciidoctor.maven;
 
+import org.apache.commons.io.FilenameUtils;
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.model.Resource;
 import org.apache.maven.plugin.AbstractMojo;
@@ -243,9 +244,16 @@ public class AsciidoctorMojo extends AbstractMojo {
 
         final Set<File> uniquePaths = new HashSet<>();
         for (final File source : sourceFiles) {
-            final File destinationPath = setDestinationPaths(source, optionsBuilder, sourceDir, this);
-            if (!uniquePaths.add(destinationPath))
-                getLog().warn("Duplicated destination found: overwriting file: " + destinationPath.getAbsolutePath());
+            final Destination destination = setDestinationPaths(source, optionsBuilder, sourceDir, this);
+            final File destinationPath = destination.path;
+            if (!uniquePaths.add(destinationPath)) {
+                String destinationFile = destinationPath.getAbsolutePath();
+                if (!destination.isOutput) {
+                    String baseName = FilenameUtils.getBaseName(destinationPath.getName());
+                    destinationFile = destinationPath.getParentFile().getAbsolutePath() + File.separator + baseName + ".*";
+                }
+                getLog().warn("Duplicated destination found: overwriting file: " + destinationFile);
+            }
 
             convertFile(asciidoctor, optionsBuilder.asMap(), source);
 
@@ -357,8 +365,8 @@ public class AsciidoctorMojo extends AbstractMojo {
      * @return the final destination file path.
      * @throws MojoExecutionException If output is not valid
      */
-    public File setDestinationPaths(final File sourceFile, final OptionsBuilder optionsBuilder, final File sourceDirectory,
-                                    final AsciidoctorMojo configuration) throws MojoExecutionException {
+    public Destination setDestinationPaths(final File sourceFile, final OptionsBuilder optionsBuilder, final File sourceDirectory,
+                                           final AsciidoctorMojo configuration) throws MojoExecutionException {
         try {
             if (configuration.getBaseDir() != null) {
                 optionsBuilder.baseDir(configuration.getBaseDir());
@@ -379,19 +387,37 @@ public class AsciidoctorMojo extends AbstractMojo {
                 optionsBuilder.toDir(outputDir).destinationDir(outputDir);
             }
             final File outputFile = configuration.getOutputFile();
-            final String destinationDir = (String) optionsBuilder.asMap().get(Options.DESTINATION_DIR);
+            final String destinationDir = getDestinationDir(optionsBuilder);
             if (outputFile != null) {
-                // allow overriding the output file name
                 optionsBuilder.toFile(outputFile);
-                return outputFile.isAbsolute() ? outputFile : new File(destinationDir, outputFile.getPath());
+                return outputFile.isAbsolute()
+                        ? new Destination(outputFile, true)
+                        : new Destination(new File(destinationDir, outputFile.getPath()), true);
             } else {
-                return new File(destinationDir, sourceFile.getName());
+                return new Destination(new File(destinationDir, sourceFile.getName()), false);
             }
         } catch (IOException e) {
             throw new MojoExecutionException("Unable to locate output directory", e);
         }
     }
 
+    class Destination {
+        final File path;
+        // Whether path is the actual output file or an approximation
+        final boolean isOutput;
+
+        Destination(File destination, boolean isSource) {
+            this.path = destination;
+            this.isOutput = isSource;
+        }
+    }
+
+    private static String getDestinationDir(OptionsBuilder optionsBuilder) {
+        final Map<String, Object> options = optionsBuilder.asMap();
+        return (String) Optional.ofNullable(options.get(Options.DESTINATION_DIR))
+                .orElse(options.get(Options.TO_DIR));
+    }
+
     protected Asciidoctor getAsciidoctorInstance(String gemPath) throws MojoExecutionException {
         Asciidoctor asciidoctor = null;
         if (gemPath == null) {


Test patch:
diff --git a/src/test/java/org/asciidoctor/maven/AsciidoctorMojoTest.java b/src/test/java/org/asciidoctor/maven/AsciidoctorMojoTest.java
index d6342af..c2dab28 100644
--- a/src/test/java/org/asciidoctor/maven/AsciidoctorMojoTest.java
+++ b/src/test/java/org/asciidoctor/maven/AsciidoctorMojoTest.java
@@ -5,12 +5,18 @@ import org.apache.commons.io.FileUtils;
 import org.apache.maven.model.Resource;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
+import org.asciidoctor.Options;
+import org.asciidoctor.OptionsBuilder;
+import org.asciidoctor.maven.AsciidoctorMojo.Destination;
 import org.asciidoctor.maven.extensions.ExtensionConfiguration;
 import org.asciidoctor.maven.io.AsciidoctorFileScanner;
 import org.asciidoctor.maven.io.ConsoleHolder;
 import org.asciidoctor.maven.test.processors.RequireCheckerTreeprocessor;
 import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.NullSource;
+import org.junit.jupiter.params.provider.ValueSource;
 
 import java.io.*;
 import java.nio.file.Files;
@@ -1069,4 +1075,23 @@ public class AsciidoctorMojoTest {
         consoleHolder.release();
     }
 
+    @ParameterizedTest
+    @NullSource
+    @ValueSource(strings = {"output.html"})
+    public void should_return_absolute_path_when_calculating_destination(String outputFile) throws MojoExecutionException {
+        // given
+        final AsciidoctorMojo mojo = mockAsciidoctorMojo();
+        mojo.setOutputDirectory(newOutputTestDirectory("overlapping-outputFile"));
+        if (outputFile != null) mojo.setOutputFile(outputFile);
+        final File source = new File("source.adoc");
+        final OptionsBuilder builder = Options.builder();
+        final File sourceDir = new File(".");
+
+        // when
+        Destination file = mojo.setDestinationPaths(source, builder, sourceDir, mojo);
+
+        // then
+        Assertions.assertThat(file.path).isAbsolute();
+        Assertions.assertThat(file.isOutput).isEqualTo(outputFile != null);
+    }
 }