This is an automated email from the ASF dual-hosted git repository. kwin pushed a commit to branch support-site-directories-skipping-duplicates in repository https://gitbox.apache.org/repos/asf/maven-doxia-sitetools.git
commit ca90124c96ccc7a0e3d1e989aec2bc0c8c8c7a9b Author: Konrad Windszus <[email protected]> AuthorDate: Wed Feb 12 13:14:09 2025 +0100 [DOXIASITETOOLS-359] Support site directories where duplicates are skipped Usually a duplicate relative file path in multiple site directories lead to a RendererException (because only one can end up in the built site). For some cases it is beneficial to add source directories where duplicates should be just silently skipped (for example to allow overwriting certain files in previous sources). --- .../doxia/siterenderer/DefaultSiteRenderer.java | 15 +++++--- .../doxia/siterenderer/SiteRenderingContext.java | 17 ++++++++ .../siterenderer/DefaultSiteRendererTest.java | 45 +++++++++++++++++++++- 3 files changed, 70 insertions(+), 7 deletions(-) diff --git a/doxia-site-renderer/src/main/java/org/apache/maven/doxia/siterenderer/DefaultSiteRenderer.java b/doxia-site-renderer/src/main/java/org/apache/maven/doxia/siterenderer/DefaultSiteRenderer.java index 465b795..97100c8 100644 --- a/doxia-site-renderer/src/main/java/org/apache/maven/doxia/siterenderer/DefaultSiteRenderer.java +++ b/doxia-site-renderer/src/main/java/org/apache/maven/doxia/siterenderer/DefaultSiteRenderer.java @@ -171,7 +171,8 @@ public class DefaultSiteRenderer implements Renderer { module, excludes, files, - siteDirectory.isEditable()); + siteDirectory.isEditable(), + siteDirectory.isSkipDuplicates()); } } } @@ -198,7 +199,7 @@ public class DefaultSiteRenderer implements Renderer { ParserModule module, String excludes, Map<String, DocumentRenderer> files, - boolean editable) + boolean editable, boolean skipDuplicates) throws IOException, RendererException { if (!moduleBasedir.exists() || ArrayUtils.isEmpty(module.getExtensions())) { return; @@ -231,8 +232,8 @@ public class DefaultSiteRenderer implements Renderer { } String key = docRenderingContext.getOutputName(); - - if (files.containsKey(key)) { + boolean foundDuplicate = files.containsKey(key); + if (foundDuplicate && !skipDuplicates) { DocumentRenderer docRenderer = files.get(key); DocumentRenderingContext originalDocRenderingContext = docRenderer.getRenderingContext(); @@ -247,7 +248,7 @@ public class DefaultSiteRenderer implements Renderer { // Handle key without case differences // ----------------------------------------------------------------------- String originalKey = caseInsensitiveFiles.put(key.toLowerCase(Locale.ROOT), key); - if (originalKey != null) { + if (originalKey != null && !skipDuplicates) { DocumentRenderingContext originalDocRenderingContext = files.get(originalKey).getRenderingContext(); @@ -265,7 +266,9 @@ public class DefaultSiteRenderer implements Renderer { } } - files.put(key, new DoxiaDocumentRenderer(docRenderingContext)); + if (!foundDuplicate) { + files.put(key, new DoxiaDocumentRenderer(docRenderingContext)); + } } } } diff --git a/doxia-site-renderer/src/main/java/org/apache/maven/doxia/siterenderer/SiteRenderingContext.java b/doxia-site-renderer/src/main/java/org/apache/maven/doxia/siterenderer/SiteRenderingContext.java index 03c2d28..152c9e5 100644 --- a/doxia-site-renderer/src/main/java/org/apache/maven/doxia/siterenderer/SiteRenderingContext.java +++ b/doxia-site-renderer/src/main/java/org/apache/maven/doxia/siterenderer/SiteRenderingContext.java @@ -43,10 +43,23 @@ public class SiteRenderingContext { public static class SiteDirectory { private File path; private boolean editable; + private boolean skipDuplicates; public SiteDirectory(File path, boolean editable) { + this(path, editable, false); + } + + /** + * + * @param path + * @param editable + * @param skipDuplicates flag indicating if duplicates in this directory should be skipped ({@code true}) or lead to an exception ({@code false}) + * @since 2.1 + */ + public SiteDirectory(File path, boolean editable, boolean skipDuplicates) { this.path = path; this.editable = editable; + this.skipDuplicates = skipDuplicates; } public File getPath() { @@ -56,6 +69,10 @@ public class SiteRenderingContext { public boolean isEditable() { return editable; } + + public boolean isSkipDuplicates() { + return skipDuplicates; + } } private String inputEncoding = ReaderFactory.FILE_ENCODING; diff --git a/doxia-site-renderer/src/test/java/org/apache/maven/doxia/siterenderer/DefaultSiteRendererTest.java b/doxia-site-renderer/src/test/java/org/apache/maven/doxia/siterenderer/DefaultSiteRendererTest.java index 8a2c04e..4ae29be 100644 --- a/doxia-site-renderer/src/test/java/org/apache/maven/doxia/siterenderer/DefaultSiteRendererTest.java +++ b/doxia-site-renderer/src/test/java/org/apache/maven/doxia/siterenderer/DefaultSiteRendererTest.java @@ -31,9 +31,11 @@ import java.io.StringWriter; import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; import java.util.jar.JarOutputStream; import java.util.zip.ZipEntry; @@ -67,9 +69,15 @@ import static org.codehaus.plexus.testing.PlexusExtension.getTestFile; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; -import static org.mockito.Mockito.*; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; /** * @author <a href="mailto:[email protected]">Vincent Siveton</a> @@ -319,6 +327,41 @@ public class DefaultSiteRendererTest { assertFalse(r.matchVersion("1.7", "1.8")); } + @Test + public void testLocateDocumentFiles() throws IOException, RendererException { + SiteRenderingContext context = new SiteRenderingContext(); + File sourceDirectory = getTestFile("src/test/resources/site-validate"); + context.setRootDirectory(sourceDirectory); + context.addSiteDirectory(new SiteDirectory(sourceDirectory, true)); + Set<String> outputFiles = siteRenderer.locateDocumentFiles(context).keySet(); + Set<String> expectedOutputFiles = new HashSet<>(); + expectedOutputFiles.add("entityTest.html"); + assertEquals(expectedOutputFiles, outputFiles); + } + + @Test + public void testLocateDocumentFilesWithNameClashes() throws IOException, RendererException { + SiteRenderingContext context = new SiteRenderingContext(); + File sourceDirectory = getTestFile("src/test/resources/site-validate"); + context.setRootDirectory(sourceDirectory); + context.addSiteDirectory(new SiteDirectory(sourceDirectory, true)); + context.addSiteDirectory(new SiteDirectory(sourceDirectory, true)); + assertThrows(RendererException.class, () -> siteRenderer.locateDocumentFiles(context)); + } + + @Test + public void testLocateDocumentFilesWithNameClashesInSkippingDuplicatesDirectory() throws IOException, RendererException { + SiteRenderingContext context = new SiteRenderingContext(); + File sourceDirectory = getTestFile("src/test/resources/site-validate"); + context.setRootDirectory(sourceDirectory); + context.addSiteDirectory(new SiteDirectory(sourceDirectory, true)); + context.addSiteDirectory(new SiteDirectory(sourceDirectory, true, true)); + Set<String> outputFiles = siteRenderer.locateDocumentFiles(context).keySet(); + Set<String> expectedOutputFiles = new HashSet<>(); + expectedOutputFiles.add("entityTest.html"); + assertEquals(expectedOutputFiles, outputFiles); + } + private SiteRenderingContext getSiteRenderingContext(SiteModel siteModel, String siteDir, boolean validate) throws RendererException, IOException { File skinFile = minimalSkinJar;
