From 4b8147c1dbec12ba1857118ee8f9383272de0f72 Mon Sep 17 00:00:00 2001 From: Luke Bemish Date: Wed, 28 May 2025 14:33:39 -0500 Subject: [PATCH 1/2] Fix `UnionFileSystemProvider#newDirectoryStream` to obey contract of `FileSystemProvider#newDirectoryStream` Fixes #78 --- .../jarhandling/impl/JarContentsImpl.java | 2 +- .../cpw/mods/niofs/union/UnionFileSystem.java | 3 ++- .../cpw/mods/niofs/union/TestUnionFS.java | 20 +++++++++---------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/main/java/cpw/mods/jarhandling/impl/JarContentsImpl.java b/src/main/java/cpw/mods/jarhandling/impl/JarContentsImpl.java index d198444..cdbd82b 100644 --- a/src/main/java/cpw/mods/jarhandling/impl/JarContentsImpl.java +++ b/src/main/java/cpw/mods/jarhandling/impl/JarContentsImpl.java @@ -168,7 +168,7 @@ public Set getPackagesExcluding(String... excludedRootPackages) { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { if (file.getFileName().toString().endsWith(".class") && attrs.isRegularFile()) { - var pkg = file.getParent().toString().replace('/', '.'); + var pkg = JarContentsImpl.this.filesystem.getRoot().relativize(file.getParent()).toString().replace('/', '.'); if (!pkg.isEmpty()) { packages.add(pkg); } diff --git a/src/main/java/cpw/mods/niofs/union/UnionFileSystem.java b/src/main/java/cpw/mods/niofs/union/UnionFileSystem.java index 4db42d7..8c2771b 100644 --- a/src/main/java/cpw/mods/niofs/union/UnionFileSystem.java +++ b/src/main/java/cpw/mods/niofs/union/UnionFileSystem.java @@ -409,7 +409,8 @@ public DirectoryStream newDirStream(final UnionPath path, final DirectoryS closeables.add(ds); final var currentPaths = StreamSupport.stream(ds.spliterator(), false) .filter(p -> testFilter(p, bp, null)) - .map(other -> fastPath(isSimple ? other : bp.relativize(other))); + .map(other -> fastPath(isSimple ? other : bp.relativize(other))) + .map(other -> path.resolve(path.relativize(other))); stream = Stream.concat(stream, currentPaths); } final Stream realStream = stream.distinct(); diff --git a/src/test/java/cpw/mods/niofs/union/TestUnionFS.java b/src/test/java/cpw/mods/niofs/union/TestUnionFS.java index 37d3cdd..a1b02b9 100644 --- a/src/test/java/cpw/mods/niofs/union/TestUnionFS.java +++ b/src/test/java/cpw/mods/niofs/union/TestUnionFS.java @@ -137,13 +137,13 @@ void testPathFiltering() { final var dir2 = Paths.get("src", "test", "resources", "dir2").toAbsolutePath().normalize(); var fsp = (UnionFileSystemProvider)FileSystemProvider.installedProviders().stream().filter(fs-> fs.getScheme().equals("union")).findFirst().orElseThrow(); var ufs = fsp.newFileSystem((path, base)->!path.startsWith("masktest2.txt"), dir1, dir2); - var t1 = ufs.getPath("masktest.txt"); - var t3 = ufs.getPath("masktest3.txt"); - var t2 = ufs.getPath("masktest2.txt"); + var t1 = ufs.getPath("/masktest.txt"); + var t3 = ufs.getPath("/masktest3.txt"); + var t2 = ufs.getPath("/masktest2.txt"); assertTrue(Files.exists(t1)); assertTrue(Files.exists(t3)); assertTrue(Files.notExists(t2)); - var sd1 = ufs.getPath("subdir1"); + var sd1 = ufs.getPath("/subdir1"); var sdt1 = sd1.resolve("masktestsd1.txt"); var walk = Set.of(ufs.getRoot(), t1, t3, sd1, sdt1); assertDoesNotThrow(()-> { @@ -160,9 +160,9 @@ void testFilteredDuplicate() { var fsp = (UnionFileSystemProvider)FileSystemProvider.installedProviders().stream().filter(fs-> fs.getScheme().equals("union")).findFirst().orElseThrow(); var all = fsp.newFileSystem((a,b) -> true, dir1); var all_expected = Set.of( - all.getPath("masktest.txt"), - all.getPath("masktest2.txt"), - all.getPath("subdir1/masktestsd1.txt") + all.getPath("/masktest.txt"), + all.getPath("/masktest2.txt"), + all.getPath("/subdir1/masktestsd1.txt") ); assertDoesNotThrow(() -> { try (var walk = Files.walk(all.getRoot())) { @@ -173,7 +173,7 @@ void testFilteredDuplicate() { var some = assertDoesNotThrow(() -> fsp.newFileSystem((a,b) -> a.endsWith("/") || a.equals("masktest.txt"), dir1)); var some_expected = Set.of( - some.getPath("masktest.txt") + some.getPath("/masktest.txt") ); assertDoesNotThrow(() -> { try (var walk = Files.walk(some.getRoot())) { @@ -189,7 +189,7 @@ void testNested() { var fsp = (UnionFileSystemProvider)FileSystemProvider.installedProviders().stream().filter(fs-> fs.getScheme().equals("union")).findFirst().orElseThrow(); var inner = fsp.newFileSystem((a,b) -> a.endsWith("/") || a.equals("masktest.txt"), dir1); var outer = fsp.newFileSystem((a, b) -> true, inner.getRoot()); - var path = outer.getPath("masktest.txt"); + var path = outer.getPath("/masktest.txt"); var expected = Set.of(path); assertDoesNotThrow(() -> { try (var walk = Files.walk(outer.getRoot())) { @@ -263,7 +263,7 @@ public void testDirectoryVisitorJar() throws Exception { final List foundFiles = new ArrayList<>(); assertAll( StreamSupport.stream(dirStream.spliterator(), false) - .peek(path -> foundFiles.add(path.toString())) + .peek(path -> foundFiles.add(root.relativize(path).toString())) .map(p-> ()-> { if (!Files.exists(p)) { throw new NoSuchFileException(p.toString()); From c65abe5d765bbba5c342c4e6f20afce7fda45058 Mon Sep 17 00:00:00 2001 From: Luke Bemish Date: Thu, 29 May 2025 14:17:19 -0500 Subject: [PATCH 2/2] Avoid relying on bad behaviour of UnionPath --- src/main/java/cpw/mods/niofs/union/UnionFileSystem.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/cpw/mods/niofs/union/UnionFileSystem.java b/src/main/java/cpw/mods/niofs/union/UnionFileSystem.java index 8c2771b..cf58adc 100644 --- a/src/main/java/cpw/mods/niofs/union/UnionFileSystem.java +++ b/src/main/java/cpw/mods/niofs/union/UnionFileSystem.java @@ -404,13 +404,11 @@ public DirectoryStream newDirStream(final UnionPath path, final DirectoryS if (!fastPathExists(dir)) { continue; } - final var isSimple = embeddedFileSystems.containsKey(bp); final var ds = Files.newDirectoryStream(dir, filter); closeables.add(ds); final var currentPaths = StreamSupport.stream(ds.spliterator(), false) .filter(p -> testFilter(p, bp, null)) - .map(other -> fastPath(isSimple ? other : bp.relativize(other))) - .map(other -> path.resolve(path.relativize(other))); + .map(other -> path.resolve(fastPath(dir.relativize(other)))); stream = Stream.concat(stream, currentPaths); } final Stream realStream = stream.distinct();