From 82862aad269fad2f9e2e46a9439b54fbd318ddce Mon Sep 17 00:00:00 2001 From: noeppi_noeppi Date: Tue, 15 Mar 2022 18:07:25 +0100 Subject: [PATCH 1/5] Make tests work with jar paths --- .../cpw/mods/niofs/union/TestUnionPath.java | 49 ++++++++++++++----- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/src/test/java/cpw/mods/niofs/union/TestUnionPath.java b/src/test/java/cpw/mods/niofs/union/TestUnionPath.java index b1319e1..796f13a 100644 --- a/src/test/java/cpw/mods/niofs/union/TestUnionPath.java +++ b/src/test/java/cpw/mods/niofs/union/TestUnionPath.java @@ -2,20 +2,33 @@ import org.junit.jupiter.api.Test; +import java.io.IOException; +import java.net.URI; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.spi.FileSystemProvider; import java.util.Arrays; +import java.util.Map; import static org.junit.jupiter.api.Assertions.*; public class TestUnionPath { + @Test - void testUnionPath() { + void testUnionPath() throws IOException { + var jarFs = FileSystems.newFileSystem(URI.create("jar:" + Paths.get("src", "test", "resources", "dir1.zip").toUri()), Map.of()); + // First test that our tests succed on jar paths: + assertAll("Tests failed for jar file system, this should not happen, tests need to be adjusted", () -> runPathTests(jarFs)); + var fsp = (UnionFileSystemProvider) FileSystemProvider.installedProviders().stream().filter(fs-> fs.getScheme().equals("union")).findFirst().orElseThrow(); // Actual base directory is not relevant as we don't access the file system in these tests var fs = fsp.newFileSystem((path, base) -> true, Paths.get("src").toAbsolutePath().normalize()); - + runPathTests(fs); + } + + private static void runPathTests(FileSystem fs) { var relUp = fs.getPath(".."); var rel0 = fs.getPath(""); var rel1 = fs.getPath("one"); @@ -120,7 +133,7 @@ void testUnionPath() { assertEquals(rel1, rel1223.getParent().getParent().getParent()); assertEquals(rel1, rel12up3.getParent().getParent().getParent()); assertEquals(rel1, rel13.getParent()); - assertEquals(rel0, rel13.getParent().getParent()); + assertNull(rel13.getParent().getParent()); assertEquals(rel1, rel13slash.getParent()); assertEquals(rel1, rel1slash3.getParent()); assertEquals(abs3, abs32.getParent()); @@ -134,7 +147,7 @@ void testUnionPath() { // getNameCount, getName, getFileName, subpath testNameParts(fs, relUp, ".."); - testNameParts(fs, rel0); + testNameParts(fs, rel0, ""); testNameParts(fs, rel1, "one"); testNameParts(fs, rel2, "two"); testNameParts(fs, rel3, "three"); @@ -174,8 +187,8 @@ void testUnionPath() { assertEquals(abs13, abs13.normalize()); assertEquals(abs123, abs1223.normalize()); assertEquals(abs13, abs12up3.normalize()); - assertEquals(absUpUp1, absUpUp1.normalize()); - assertEquals(absUpUp123, absUpUp123.normalize()); + assertEquals(abs1, absUpUp1.normalize()); + assertEquals(abs123, absUpUp123.normalize()); // resolve assertEquals(abs32, rel0.resolve(abs32)); @@ -191,22 +204,32 @@ void testUnionPath() { // relativize is tested in TestUnionFS } - private static void testNameParts(UnionFileSystem fs, Path path, String... names) { + private static void testNameParts(FileSystem fs, Path path, String... names) { // getNameCount - assertEquals(names.length, path.getNameCount()); + if (names.length == 0) { + if (path.isAbsolute()) { + assertEquals(0, path.getNameCount()); + } else { + assertEquals(1, path.getNameCount()); + assertEquals(fs.getPath(""), path.getName(0)); + } + } else { + assertEquals(names.length, path.getNameCount()); + } + int nameCount = path.getNameCount(); // getName assertThrows(IllegalArgumentException.class, () -> path.getName(-1)); - assertThrows(IllegalArgumentException.class, () -> path.getName(names.length)); + assertThrows(IllegalArgumentException.class, () -> path.getName(nameCount)); for (int i = 0; i < names.length; i++) { assertEquals(fs.getPath(names[i]), path.getName(i)); } // getFileName - if (names.length > 0) { - assertEquals(fs.getPath(names[names.length - 1]), path.getFileName()); + if (names.length == 0 || (names.length == 1 && names[0].isEmpty())) { + assertNull(path.getFileName()); } else { - assertEquals(fs.getPath(""), path.getFileName()); + assertEquals(fs.getPath(names[names.length - 1]), path.getFileName()); } // subpath, startsWith, endsWith @@ -223,7 +246,7 @@ private static void testNameParts(UnionFileSystem fs, Path path, String... names String absStr = path.isAbsolute() ? "/" : ""; String oppositeAbsStr = path.isAbsolute() ? "" : "/"; assertTrue(path.startsWith(fs.getPath(absStr, fromStart))); - assertTrue(path.endsWith(fs.getPath(absStr, fromEnd))); + assertTrue(path.endsWith(fs.getPath("", fromEnd))); assertFalse(path.startsWith(fs.getPath(oppositeAbsStr, fromStart))); if (path.isAbsolute()) { // Absolute paths can end on non-absolute paths From 3494f50104d4dd3322a682a1ad6cba96fd521146 Mon Sep 17 00:00:00 2001 From: noeppi_noeppi Date: Tue, 15 Mar 2022 18:46:12 +0100 Subject: [PATCH 2/5] Move tests for relativize to TestUnionPath and fix path and fs so they behave as jar paths do --- .../cpw/mods/niofs/union/UnionFileSystem.java | 4 +- .../java/cpw/mods/niofs/union/UnionPath.java | 46 ++++++++-------- .../cpw/mods/niofs/union/TestUnionFS.java | 52 ------------------- .../cpw/mods/niofs/union/TestUnionPath.java | 26 +++++++++- 4 files changed, 50 insertions(+), 78 deletions(-) diff --git a/src/main/java/cpw/mods/niofs/union/UnionFileSystem.java b/src/main/java/cpw/mods/niofs/union/UnionFileSystem.java index 2156421..c8738b8 100644 --- a/src/main/java/cpw/mods/niofs/union/UnionFileSystem.java +++ b/src/main/java/cpw/mods/niofs/union/UnionFileSystem.java @@ -240,7 +240,7 @@ public DirectoryStream newDirStream(final UnionPath path, final DirectoryS try (final var ds = Files.newDirectoryStream(dir, filter)) { StreamSupport.stream(ds.spliterator(), false) .filter(p->testFilter(p, bp)) - .map(other -> (isSimple ? other : bp.relativize(other)).toString()) + .map(other -> (isSimple ? other : bp.toAbsolutePath().relativize(other.toAbsolutePath())).toString()) .map(this::getPath) .forEachOrdered(allpaths::add); } @@ -269,7 +269,7 @@ private boolean testFilter(final Path path, final Path basePath) { var sPath = path.toString(); if (path.getFileSystem() == basePath.getFileSystem()) // Directories, zips will be different file systems. - sPath = basePath.relativize(path).toString().replace('\\', '/'); + sPath = basePath.toAbsolutePath().relativize(path.toAbsolutePath()).toString().replace('\\', '/'); if (Files.isDirectory(path)) sPath += '/'; if (sPath.length() > 1 && sPath.startsWith("/")) diff --git a/src/main/java/cpw/mods/niofs/union/UnionPath.java b/src/main/java/cpw/mods/niofs/union/UnionPath.java index d39eee0..e713b92 100644 --- a/src/main/java/cpw/mods/niofs/union/UnionPath.java +++ b/src/main/java/cpw/mods/niofs/union/UnionPath.java @@ -13,6 +13,7 @@ public class UnionPath implements Path { private final UnionFileSystem fileSystem; private final boolean absolute; + private final boolean empty; private final String[] pathParts; // Store the normalized path after it has been created first @@ -22,11 +23,13 @@ public class UnionPath implements Path { this.fileSystem = fileSystem; if (pathParts.length == 0) { this.absolute = false; - this.pathParts = new String[0]; + this.pathParts = new String[]{ "" }; + this.empty = true; } else { final var longstring = Arrays.stream(pathParts).filter(part -> !part.isEmpty()).collect(Collectors.joining(this.getFileSystem().getSeparator())); this.absolute = longstring.startsWith(this.getFileSystem().getSeparator()); - this.pathParts = getPathParts(longstring); + this.pathParts = getPathParts(this.absolute, longstring); + this.empty = !this.absolute && this.pathParts.length == 1 && this.pathParts[0].isEmpty(); } this.normalized = null; } @@ -40,13 +43,14 @@ private UnionPath(final UnionFileSystem fileSystem, boolean absolute, boolean is this.fileSystem = fileSystem; this.absolute = absolute; this.pathParts = pathParts; + this.empty = !this.absolute && this.pathParts.length == 1 && this.pathParts[0].isEmpty(); if (isNormalized) this.normalized = this; else this.normalized = null; } - private String[] getPathParts(final String longstring) { + private String[] getPathParts(final boolean isAbsolute, final String longstring) { var sep = "(?:" + Pattern.quote(this.getFileSystem().getSeparator()) + ")"; String pathname = longstring .replace("\\", this.getFileSystem().getSeparator()) @@ -55,7 +59,7 @@ private String[] getPathParts(final String longstring) { // Remove duplicate separators .replaceAll(sep + "+(?=" + sep + ")", ""); if (pathname.isEmpty()) - return new String[0]; + return isAbsolute ? new String[0] : new String[]{ "" }; else return pathname.split(this.getFileSystem().getSeparator()); } @@ -72,28 +76,25 @@ public boolean isAbsolute() { @Override public Path getRoot() { - // Found nothing in the docs that say a non-absolute path can't have a root - // although this is uncommon. However, other stuff relies on it so leave it - //if (!this.absolute) - // return null; + if (!this.absolute) + return null; return this.fileSystem.getRoot(); } @Override public Path getFileName() { - if (this.pathParts.length > 0) { + if (this.empty) { + return null; + } else if (this.pathParts.length > 0) { return new UnionPath(this.getFileSystem(), false, this.pathParts[this.pathParts.length - 1]); } else { - // normally would be null for the empty absolute path and empty string for the empty relative - // path. But again, very much stuff relies on it and there's no current directory for union - // paths, so it does not really matter. - return new UnionPath(this.fileSystem, false); + return this.absolute ? null : new UnionPath(this.fileSystem, false); } } @Override public Path getParent() { - if (this.pathParts.length > 0) { + if (this.pathParts.length > 1 || (this.absolute && this.pathParts.length == 1)) { return new UnionPath(this.fileSystem, this.absolute, Arrays.copyOf(this.pathParts,this.pathParts.length - 1)); } else { return null; @@ -171,10 +172,10 @@ public Path normalize() { case ".": break; case "..": - if (normpath.isEmpty() || normpath.getLast().equals("..")) { - // .. on an empty path is allowed, so keep it + if (!this.absolute && (normpath.isEmpty() || normpath.getLast().equals(".."))) { + // .. on an empty path is allowed as long as it is not absolute, so keep it normpath.addLast(pathPart); - } else { + } else if (!normpath.isEmpty()) { normpath.removeLast(); } break; @@ -190,9 +191,12 @@ public Path normalize() { @Override public Path resolve(final Path other) { if (other instanceof UnionPath path) { - if (path.isAbsolute()) { + if (path.isAbsolute() || this.empty) { return path; } + if (path.empty) { + return this; + } String[] mergedParts = new String[this.pathParts.length + path.pathParts.length]; System.arraycopy(this.pathParts, 0, mergedParts, 0, this.pathParts.length); System.arraycopy(path.pathParts, 0, mergedParts, this.pathParts.length, path.pathParts.length); @@ -206,11 +210,7 @@ public Path relativize(final Path other) { if (other.getFileSystem()!=this.getFileSystem()) throw new IllegalArgumentException("Wrong filesystem"); if (other instanceof UnionPath p) { if (this.absolute != p.absolute) { - // Should not be allowed but union fs relies on it - // also there is no such concept of a current directory for union paths - // meaning absolute and relative paths should have the same effect, - // so we just allow this. - //throw new IllegalArgumentException("Different types of path"); + throw new IllegalArgumentException("Different types of path"); } var length = Math.min(this.pathParts.length, p.pathParts.length); int i = 0; diff --git a/src/test/java/cpw/mods/niofs/union/TestUnionFS.java b/src/test/java/cpw/mods/niofs/union/TestUnionFS.java index 50f3116..f7c307b 100644 --- a/src/test/java/cpw/mods/niofs/union/TestUnionFS.java +++ b/src/test/java/cpw/mods/niofs/union/TestUnionFS.java @@ -41,58 +41,6 @@ void testUnionFileSystem() throws IOException { p.subpath(1, 2); } - @Test - void testRelativize() { - final var dir1 = Paths.get("src", "test", "resources", "dir1").toAbsolutePath().normalize(); - 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) -> true, dir1, dir2); - var p1 = ufs.getPath("path1"); - var p123 = ufs.getPath("path1/path2/path3"); - var p11 = ufs.getPath("path1/path1"); - var p12 = ufs.getPath("path1/path2"); - var p13 = ufs.getPath("path1/path3"); - var p23 = ufs.getPath("path2/path3"); - var p13plus = ufs.getPath("path1/path3"); - assertAll( - ()->assertEquals("path2/path3", p1.relativize(p123).toString()), - ()->assertEquals("../..", p123.relativize(p1).toString()), - ()->assertEquals("path1", p1.relativize(p11).toString()), - ()->assertEquals("path2", p1.relativize(p12).toString()), - ()->assertEquals("path3", p1.relativize(p13).toString()), - ()->assertEquals("../../path1/path1", p23.relativize(p11).toString()), - ()->assertEquals("../../path1", p123.relativize(p11).toString()), - ()->assertEquals(0, p13.relativize(p13plus).getNameCount()) - ); - } - - @Test - void testRelativizeAbsolute() { - final var dir1 = Paths.get("src", "test", "resources", "dir1").toAbsolutePath().normalize(); - 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) -> true, dir1, dir2); - var p1 = ufs.getPath("/path1"); - var p123 = ufs.getPath("/path1/path2/path3"); - var p11 = ufs.getPath("/path1/path1"); - var p12 = ufs.getPath("/path1/path2"); - var p13 = ufs.getPath("/path1/path3"); - var p23 = ufs.getPath("/path2/path3"); - var p13plus = ufs.getPath("/path1/path3"); - assertAll( - ()->assertEquals("path2/path3", p1.relativize(p123).toString()), - ()->assertEquals("../..", p123.relativize(p1).toString()), - ()->assertEquals("path1", p1.relativize(p11).toString()), - ()->assertEquals("path2", p1.relativize(p12).toString()), - ()->assertEquals("path3", p1.relativize(p13).toString()), - ()->assertEquals("../../path1/path1", p23.relativize(p11).toString()), - ()->assertEquals("../../path1", p123.relativize(p11).toString()), - ()->assertEquals(0, p13.relativize(p13plus).getNameCount()) - ); - } - @Test void testPathFiltering() { final var dir1 = Paths.get("src", "test", "resources", "dir1").toAbsolutePath().normalize(); diff --git a/src/test/java/cpw/mods/niofs/union/TestUnionPath.java b/src/test/java/cpw/mods/niofs/union/TestUnionPath.java index 796f13a..c644e21 100644 --- a/src/test/java/cpw/mods/niofs/union/TestUnionPath.java +++ b/src/test/java/cpw/mods/niofs/union/TestUnionPath.java @@ -200,8 +200,32 @@ private static void runPathTests(FileSystem fs) { assertEquals(abs123, abs0.resolve(rel123)); assertEquals(abs123, abs1.resolve(rel2).resolve(rel3)); assertEquals(abs32, abs3.resolve(rel0).resolve(rel2)); + + assertThrows(IllegalArgumentException.class, () -> rel1.relativize(abs123)); + assertThrows(IllegalArgumentException.class, () -> abs1.relativize(rel123)); + + assertEquals(fs.getPath("two/three"), rel1.relativize(rel123)); + assertEquals(fs.getPath("../.."), rel123.relativize(rel1)); + assertEquals(rel1, rel1.relativize(fs.getPath("one/one"))); + assertEquals(rel3, rel1.relativize(rel13)); + assertEquals(fs.getPath("../../one/one"), rel32.relativize(fs.getPath("one/one"))); + assertEquals(fs.getPath("../../one"), rel123.relativize(fs.getPath("one/one"))); - // relativize is tested in TestUnionFS + assertEquals(fs.getPath("two/three"), abs1.relativize(abs123)); + assertEquals(fs.getPath("../.."), abs123.relativize(abs1)); + assertEquals(rel1, abs1.relativize(fs.getPath("/one/one"))); + assertEquals(rel3, abs1.relativize(abs13)); + assertEquals(fs.getPath("../../one/one"), abs32.relativize(fs.getPath("/one/one"))); + assertEquals(fs.getPath("../../one"), abs123.relativize(fs.getPath("/one/one"))); + + // getRoot + assertNull(rel0.getRoot()); + assertNull(rel123.getRoot()); + assertNull(relUpUp1.getRoot()); + + assertEquals(abs0, abs0.getRoot()); + assertEquals(abs0, abs123.getRoot()); + assertEquals(abs0, absUpUp1.getRoot()); } private static void testNameParts(FileSystem fs, Path path, String... names) { From e89c092123d978d21a4f8bf6ac2cf5aa5682b3df Mon Sep 17 00:00:00 2001 From: noeppi_noeppi Date: Tue, 15 Mar 2022 19:27:09 +0100 Subject: [PATCH 3/5] Some jar fixes --- src/main/java/cpw/mods/jarhandling/impl/Jar.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/cpw/mods/jarhandling/impl/Jar.java b/src/main/java/cpw/mods/jarhandling/impl/Jar.java index c27f22f..9640883 100644 --- a/src/main/java/cpw/mods/jarhandling/impl/Jar.java +++ b/src/main/java/cpw/mods/jarhandling/impl/Jar.java @@ -114,7 +114,7 @@ public Jar(final Supplier defaultManifest, final Function!p1.isAbsolute()) .filter(path1 -> !Files.isDirectory(path1)) @@ -206,9 +206,9 @@ public String name() { @Override public Set getPackages() { if (this.packages == null) { - try (var walk = Files.walk(this.filesystem.getRoot())) { + try (var walk = Files.walk(this.filesystem.getPath(""))) { this.packages = walk - .filter(path->path.getNameCount()>0) + .filter(path->path.getNameCount()>1) .filter(path->!path.getName(0).toString().equals("META-INF")) .filter(path->path.getFileName().toString().endsWith(".class")) .filter(Files::isRegularFile) From 4d8cf80e0c37553c72a907025e9e851b96429c91 Mon Sep 17 00:00:00 2001 From: noeppi_noeppi Date: Fri, 8 Jul 2022 21:08:16 +0200 Subject: [PATCH 4/5] Fix UnionPath --- .../cpw/mods/niofs/union/UnionFileSystem.java | 4 +- .../java/cpw/mods/niofs/union/UnionPath.java | 69 +++++++++++-------- 2 files changed, 41 insertions(+), 32 deletions(-) diff --git a/src/main/java/cpw/mods/niofs/union/UnionFileSystem.java b/src/main/java/cpw/mods/niofs/union/UnionFileSystem.java index c6ab100..48da78a 100644 --- a/src/main/java/cpw/mods/niofs/union/UnionFileSystem.java +++ b/src/main/java/cpw/mods/niofs/union/UnionFileSystem.java @@ -336,7 +336,7 @@ public DirectoryStream newDirStream(final UnionPath path, final DirectoryS try (final var ds = Files.newDirectoryStream(dir, filter)) { StreamSupport.stream(ds.spliterator(), false) .filter(p->testFilter(p, bp)) - .map(other -> StreamSupport.stream(Spliterators.spliteratorUnknownSize((isSimple ? other : bp.relativize(other)).iterator(), Spliterator.ORDERED), false) + .map(other -> StreamSupport.stream(Spliterators.spliteratorUnknownSize((isSimple ? other : bp.toAbsolutePath().relativize(other.toAbsolutePath())).iterator(), Spliterator.ORDERED), false) .map(Path::getFileName).map(Path::toString).toArray(String[]::new)) .map(this::fastPath) .forEachOrdered(allpaths::add); @@ -366,7 +366,7 @@ private boolean testFilter(final Path path, final Path basePath) { var sPath = path.toString(); if (path.getFileSystem() == basePath.getFileSystem()) // Directories, zips will be different file systems. - sPath = basePath.relativize(path).toString().replace('\\', '/'); + sPath = basePath.toAbsolutePath().relativize(path.toAbsolutePath()).toString().replace('\\', '/'); if (Files.isDirectory(path)) sPath += '/'; if (sPath.length() > 1 && sPath.startsWith("/")) diff --git a/src/main/java/cpw/mods/niofs/union/UnionPath.java b/src/main/java/cpw/mods/niofs/union/UnionPath.java index a4212cc..39a6b78 100644 --- a/src/main/java/cpw/mods/niofs/union/UnionPath.java +++ b/src/main/java/cpw/mods/niofs/union/UnionPath.java @@ -14,13 +14,13 @@ import java.util.Deque; import java.util.List; import java.util.Objects; -import java.util.StringJoiner; import java.util.function.IntBinaryOperator; import java.util.stream.IntStream; public class UnionPath implements Path { private final UnionFileSystem fileSystem; private final boolean absolute; + private final boolean empty; private final String[] pathParts; // Store the normalized path after it has been created first @@ -30,7 +30,8 @@ public class UnionPath implements Path { this.fileSystem = fileSystem; if (pathParts.length == 0) { this.absolute = false; - this.pathParts = new String[0]; + this.pathParts = new String[]{ "" }; + this.empty = true; } else { StringBuilder joiner = new StringBuilder(); for (int i = 0; i < pathParts.length; i++) { @@ -42,7 +43,8 @@ public class UnionPath implements Path { } final var longstring = joiner.toString(); this.absolute = longstring.startsWith(UnionFileSystem.SEP_STRING); - this.pathParts = getPathParts(longstring); + this.pathParts = getPathParts(this.absolute, longstring); + this.empty = !this.absolute && this.pathParts.length == 1 && this.pathParts[0].isEmpty(); } this.normalized = null; } @@ -54,15 +56,22 @@ public class UnionPath implements Path { private UnionPath(final UnionFileSystem fileSystem, boolean absolute, boolean isNormalized, final String... pathParts) { this.fileSystem = fileSystem; - this.absolute = absolute; - this.pathParts = pathParts; - if (isNormalized) - this.normalized = this; - else - this.normalized = null; + if (!absolute && (pathParts.length == 0 || (pathParts.length == 1 && pathParts[0].isEmpty()))) { + this.absolute = false; + this.pathParts = new String[]{ "" }; + this.empty = true; + } else { + this.absolute = absolute; + this.empty = false; + this.pathParts = pathParts; + if (isNormalized) + this.normalized = this; + else + this.normalized = null; + } } - private String[] getPathParts(final String longstring) { + private String[] getPathParts(final boolean isAbsolute, final String longstring) { var clean = longstring.replace('\\', '/'); int startIndex = 0; List parts = new ArrayList<>(); @@ -78,7 +87,11 @@ private String[] getPathParts(final String longstring) { } startIndex = (index + 1); } - return parts.toArray(String[]::new); + if (parts.isEmpty() && !isAbsolute) { + return new String[]{ "" }; + } else { + return parts.toArray(String[]::new); + } } @Override @@ -93,28 +106,25 @@ public boolean isAbsolute() { @Override public Path getRoot() { - // Found nothing in the docs that say a non-absolute path can't have a root - // although this is uncommon. However, other stuff relies on it so leave it - //if (!this.absolute) - // return null; + if (!this.absolute) + return null; return this.fileSystem.getRoot(); } @Override public Path getFileName() { - if (this.pathParts.length > 0) { + if (this.empty) { + return null; + } else if (this.pathParts.length > 0) { return new UnionPath(this.getFileSystem(), false, this.pathParts[this.pathParts.length - 1]); } else { - // normally would be null for the empty absolute path and empty string for the empty relative - // path. But again, very much stuff relies on it and there's no current directory for union - // paths, so it does not really matter. - return new UnionPath(this.fileSystem, false); + return this.absolute ? null : new UnionPath(this.fileSystem, false); } } @Override public Path getParent() { - if (this.pathParts.length > 0) { + if (this.pathParts.length > 1 || (this.absolute && this.pathParts.length == 1)) { return new UnionPath(this.fileSystem, this.absolute, Arrays.copyOf(this.pathParts,this.pathParts.length - 1)); } else { return null; @@ -192,10 +202,10 @@ public Path normalize() { case ".": break; case "..": - if (normpath.isEmpty() || normpath.getLast().equals("..")) { - // .. on an empty path is allowed, so keep it + if (!this.absolute && (normpath.isEmpty() || normpath.getLast().equals(".."))) { + // .. on an empty path is allowed as long as it is not absolute, so keep it normpath.addLast(pathPart); - } else { + } else if (!normpath.isEmpty()) { normpath.removeLast(); } break; @@ -211,9 +221,12 @@ public Path normalize() { @Override public Path resolve(final Path other) { if (other instanceof UnionPath path) { - if (path.isAbsolute()) { + if (path.isAbsolute() || this.empty) { return path; } + if (path.empty) { + return this; + } String[] mergedParts = new String[this.pathParts.length + path.pathParts.length]; System.arraycopy(this.pathParts, 0, mergedParts, 0, this.pathParts.length); System.arraycopy(path.pathParts, 0, mergedParts, this.pathParts.length, path.pathParts.length); @@ -227,11 +240,7 @@ public Path relativize(final Path other) { if (other.getFileSystem()!=this.getFileSystem()) throw new IllegalArgumentException("Wrong filesystem"); if (other instanceof UnionPath p) { if (this.absolute != p.absolute) { - // Should not be allowed but union fs relies on it - // also there is no such concept of a current directory for union paths - // meaning absolute and relative paths should have the same effect, - // so we just allow this. - //throw new IllegalArgumentException("Different types of path"); + throw new IllegalArgumentException("Different types of path"); } var length = Math.min(this.pathParts.length, p.pathParts.length); int i = 0; From 2dedd83f59b88a4f5cbbd211a39b7858dab93955 Mon Sep 17 00:00:00 2001 From: noeppi_noeppi Date: Sat, 20 Jan 2024 22:18:09 +0100 Subject: [PATCH 5/5] Reapply the changes that were lost dropped the merge commit to JarContentsImpl.java --- src/main/java/cpw/mods/jarhandling/impl/JarContentsImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/cpw/mods/jarhandling/impl/JarContentsImpl.java b/src/main/java/cpw/mods/jarhandling/impl/JarContentsImpl.java index a39807b..067382e 100644 --- a/src/main/java/cpw/mods/jarhandling/impl/JarContentsImpl.java +++ b/src/main/java/cpw/mods/jarhandling/impl/JarContentsImpl.java @@ -114,7 +114,7 @@ private Map readMultiReleaseInfo() { return Map.of(); } - var vers = filesystem.getRoot().resolve("META-INF/versions"); + var vers = filesystem.getPath("").resolve("META-INF/versions"); try (var walk = Files.walk(vers)) { Map pathToJavaVersion = new HashMap<>(); walk @@ -161,7 +161,7 @@ public Set getPackagesExcluding(String... excludedRootPackages) { Set packages = new HashSet<>(); try { - Files.walkFileTree(this.filesystem.getRoot(), new SimpleFileVisitor<>() { + Files.walkFileTree(this.filesystem.getPath(""), new SimpleFileVisitor<>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { if (file.getFileName().toString().endsWith(".class") && attrs.isRegularFile()) {