You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by gn...@apache.org on 2026/09/24 20:48:54 UTC

(maven-filtering) 03/09: fix: normalize Windows drive paths in FilteringUtils

This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch maven-filtering-3.x
in repository https://gitbox.apache.org/repos/asf/maven-filtering.git

commit 5245ba3831433e0272d76d19d345569e70f9405a
Author: Efe <go...@gmail.com>
AuthorDate: Thu Sep 24 19:38:37 2026 +0300

    fix: normalize Windows drive paths in FilteringUtils
    
    - Replace backslash-prefixed drive paths (e.g. \\C:\\path) with
      forward-slash form (C:/path) before relative path computation
    - Tighten Windows drive letter regex to require separator after colon
    - Use forward slashes in getRelativeFilePath for cross-platform consistency
    - Add Unix and Windows path test coverage
    
    (cherry picked from commit 4876d9e06b140ea88acb82a94ce38980d05c5d3e)
---
 .../maven/shared/filtering/FilteringUtils.java     | 24 ++++++++++++----------
 .../maven/shared/filtering/FilteringUtilsTest.java | 12 +++++++++++
 2 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/src/main/java/org/apache/maven/shared/filtering/FilteringUtils.java b/src/main/java/org/apache/maven/shared/filtering/FilteringUtils.java
index 196b570..e2ed2c3 100644
--- a/src/main/java/org/apache/maven/shared/filtering/FilteringUtils.java
+++ b/src/main/java/org/apache/maven/shared/filtering/FilteringUtils.java
@@ -180,9 +180,9 @@ public final class FilteringUtils {
      * PathTool.getRelativeFilePath( "/usr/local/", "/usr/local/java/bin/java.sh" ) = "java/bin/java.sh"
      * PathTool.getRelativeFilePath( "/usr/local/java/bin/java.sh", "/usr/local/" ) = "../../.."
      * PathTool.getRelativeFilePath( "/usr/local/", "/bin" )                        = "../../bin"
-     * PathTool.getRelativeFilePath( "/bin", "/usr/local/" )                        = "../usr/local"
+     * PathTool.getRelativeFilePath( "/bin", "/usr/local/" )                        = "../usr/local/"
      * </pre>
-     * Note: On Windows based system, the <code>/</code> character should be replaced by <code>\</code> character.
+     * Note: The path separator is always {@code /}, regardless of the operating system.
      *
      * @param oldPath old path
      * @param newPath new path
@@ -193,15 +193,17 @@ public final class FilteringUtils {
             return "";
         }
 
-        // normalise the path delimiters
-        String fromPath = new File(oldPath).getPath();
-        String toPath = new File(newPath).getPath();
+        // normalise the path delimiters to forward slashes for cross-platform consistency
+        String fromPath = new File(oldPath).getPath().replace('\\', '/');
+        String toPath = new File(newPath).getPath().replace('\\', '/');
 
-        // strip any leading slashes if its a windows path
-        if (toPath.matches("^\\[a-zA-Z]:")) {
+        // strip any leading slashes if its a windows path (require separator after colon to avoid
+        // false positives on unusual Unix paths like /a:/something); backslashes are already
+        // normalised to forward slashes above, so only '/' needs to be matched here
+        if (toPath.matches("^/[a-zA-Z]:/.*")) {
             toPath = toPath.substring(1);
         }
-        if (fromPath.matches("^\\[a-zA-Z]:")) {
+        if (fromPath.matches("^/[a-zA-Z]:/.*")) {
             fromPath = fromPath.substring(1);
         }
 
@@ -229,10 +231,10 @@ public final class FilteringUtils {
             return null;
         }
 
-        String resultPath = buildRelativePath(toPath, fromPath, File.separatorChar);
+        String resultPath = buildRelativePath(toPath, fromPath, '/');
 
-        if (newPath.endsWith(File.separator) && !resultPath.endsWith(File.separator)) {
-            return resultPath + File.separator;
+        if ((newPath.endsWith("/") || newPath.endsWith(File.separator)) && !resultPath.endsWith("/")) {
+            return resultPath + "/";
         }
 
         return resultPath;
diff --git a/src/test/java/org/apache/maven/shared/filtering/FilteringUtilsTest.java b/src/test/java/org/apache/maven/shared/filtering/FilteringUtilsTest.java
index 5392b3d..e0ee62c 100644
--- a/src/test/java/org/apache/maven/shared/filtering/FilteringUtilsTest.java
+++ b/src/test/java/org/apache/maven/shared/filtering/FilteringUtilsTest.java
@@ -164,5 +164,17 @@ class FilteringUtilsTest {
 
         FilteringUtils.copyFile(temp, out, "UTF-8", new FilterWrapper[0]);
         assertFalse(out.canWrite());
+
+    @Test
+    void relativeFilePathStripsLeadingSeparatorFromWindowsDrivePath() {
+        assertEquals("file.txt", FilteringUtils.getRelativeFilePath("C:/base", "/C:/base/file.txt"));
+        assertEquals("../other/file.txt", FilteringUtils.getRelativeFilePath("/C:/base/dir", "C:/base/other/file.txt"));
+    }
+
+    @Test
+    void relativeFilePathUnixStylePaths() {
+        assertEquals("java/bin", FilteringUtils.getRelativeFilePath("/usr/local", "/usr/local/java/bin"));
+        assertEquals("../../bin", FilteringUtils.getRelativeFilePath("/usr/local/", "/bin"));
+        assertEquals("../usr/local/", FilteringUtils.getRelativeFilePath("/bin", "/usr/local/"));
     }
 }