From 8102159b4f38851a00c11d73c25a2925ef498bfe Mon Sep 17 00:00:00 2001 From: Konrad Windszus Date: Thu, 29 Oct 2026 13:24:42 +0100 Subject: [PATCH 1/2] RAT-585: Respect filesystem case sensitivity in path root matching Add corresponding tests --- .../org/apache/rat/document/DocumentName.java | 5 +++-- .../apache/rat/document/DocumentNameTest.java | 12 ++++++++++++ .../java/org/apache/rat/document/FSInfoTest.java | 16 ++++++++++++++++ src/changes/changes.xml | 3 +++ 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/apache-rat-core/src/main/java/org/apache/rat/document/DocumentName.java b/apache-rat-core/src/main/java/org/apache/rat/document/DocumentName.java index c6cc55f22..463b7da6f 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/document/DocumentName.java +++ b/apache-rat-core/src/main/java/org/apache/rat/document/DocumentName.java @@ -513,12 +513,13 @@ public boolean isCaseSensitive() { /** * Retrieves the root extracted from the name. + * Matching respects the case sensitivity of this file system. * @param name the name to extract the root from * @return an optional containing the root or empty. */ public Optional rootFor(final String name) { for (String sysRoot : data.roots) { - if (name.startsWith(sysRoot)) { + if (name.regionMatches(!isCaseSensitive(), 0, sysRoot, 0, sysRoot.length())) { return Optional.of(sysRoot); } } @@ -773,7 +774,7 @@ public Builder setName(final String name) { Pair splitRoot(final String name) { String workingName = name; String workingRoot = fsInfo.rootFor(name).orElse(""); - if (!workingRoot.isEmpty() && workingName.startsWith(workingRoot)) { + if (!workingRoot.isEmpty()) { workingName = workingName.substring(workingRoot.length()); } return ImmutablePair.of(workingRoot, workingName); diff --git a/apache-rat-core/src/test/java/org/apache/rat/document/DocumentNameTest.java b/apache-rat-core/src/test/java/org/apache/rat/document/DocumentNameTest.java index 7b1ef2489..74a67cb15 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/document/DocumentNameTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/document/DocumentNameTest.java @@ -40,6 +40,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.FieldSource; import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -50,6 +51,17 @@ public class DocumentNameTest { private static final FSInfo[] TEST_SUITE = FSInfoTest.TEST_SUITE; + @ParameterizedTest + @ValueSource(booleans = {true, false}) + void splitRootRespectsCaseSensitivity(boolean caseSensitive) { + FSInfo info = new FSInfo("test", "\\", caseSensitive, List.of("F:\\")); + String path = "f:\\workspace\\target\\rat.txt"; + var result = DocumentName.builder(info).splitRoot(path); + + assertThat(result.getLeft()).isEqualTo(caseSensitive ? "" : "F:\\"); + assertThat(result.getRight()).isEqualTo(caseSensitive ? path : "workspace\\target\\rat.txt"); + } + /** * Create a list of mocked files from the specified directory. * @param directory the native directory to read. diff --git a/apache-rat-core/src/test/java/org/apache/rat/document/FSInfoTest.java b/apache-rat-core/src/test/java/org/apache/rat/document/FSInfoTest.java index e2513822e..089a2dda0 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/document/FSInfoTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/document/FSInfoTest.java @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.TreeMap; import org.junit.jupiter.api.Test; @@ -33,6 +34,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.FieldSource; import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -59,6 +61,20 @@ public class FSInfoTest { public static final DocumentName.FSInfo[] TEST_SUITE = {UNIX, WINDOWS, OSX}; + @ParameterizedTest + @ValueSource(booleans = {true, false}) + void rootForRespectsCaseSensitivity(boolean caseSensitive) { + DocumentName.FSInfo info = new DocumentName.FSInfo("test", "\\", caseSensitive, List.of("C:\\", "F:\\")); + + assertThat(info.rootFor("F:\\workspace\\target\\rat.txt")).contains("F:\\"); + assertThat(info.rootFor("f:\\workspace\\target\\rat.txt")) + .isEqualTo(caseSensitive ? Optional.empty() : Optional.of("F:\\")); + assertThat(info.rootFor("c:\\workspace\\target\\rat.txt")) + .isEqualTo(caseSensitive ? Optional.empty() : Optional.of("C:\\")); + assertThat(info.rootFor("G:\\workspace\\target\\rat.txt")).isEmpty(); + assertThat(info.rootFor("target\\rat.txt")).isEmpty(); + } + @ParameterizedTest @FieldSource("TEST_SUITE") void normalizeTest(DocumentName.FSInfo info) { diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 8d6bb7f1d..0b9096e29 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -68,6 +68,9 @@ in order to be properly linked in site reports. --> + + Respect filesystem case sensitivity when matching path roots, preventing lowercase Windows drive letters from being treated as relative report paths. + Fix applying configured exclusion rules to resources added via Ant ResourceCollections, including nested filesets and externally resolved collections such as Gradle fileTree elements. From ac2bc81f7ca4393ac6981e1e9ac436ab2ea416fd Mon Sep 17 00:00:00 2001 From: Konrad Windszus Date: Thu, 29 Oct 2026 13:58:54 +0100 Subject: [PATCH 2/2] Fix changelog --- src/changes/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 0b9096e29..a6f7cbab7 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -68,7 +68,7 @@ in order to be properly linked in site reports. --> - + Respect filesystem case sensitivity when matching path roots, preventing lowercase Windows drive letters from being treated as relative report paths.