This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-io.git
The following commit(s) were added to refs/heads/master by this push: new b95421c7c [IO-872] PathUtils.directoryAndFileContentEquals doesn't work across FileSystems b95421c7c is described below commit b95421c7cbc03bd60a11975f6203e59d15f3786b Author: Gary Gregory <garydgreg...@gmail.com> AuthorDate: Fri Apr 4 09:57:44 2025 -0400 [IO-872] PathUtils.directoryAndFileContentEquals doesn't work across FileSystems Add tests and fix NPE --- .../java/org/apache/commons/io/file/PathUtils.java | 4 +- .../io/file/PathUtilsContentEqualsTest.java | 56 ++++++++++++++++++++- src/test/resources/org/apache/commons/io/empty.zip | Bin 0 -> 8972 bytes 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/apache/commons/io/file/PathUtils.java b/src/main/java/org/apache/commons/io/file/PathUtils.java index a9f6bea2e..c2be28788 100644 --- a/src/main/java/org/apache/commons/io/file/PathUtils.java +++ b/src/main/java/org/apache/commons/io/file/PathUtils.java @@ -1739,8 +1739,8 @@ public static BigInteger sizeOfDirectoryAsBigInteger(final Path directory) throw private static Path stripTrailingSeparator(final Path cdir) { final Path dir = cdir.normalize(); final String separator = dir.getFileSystem().getSeparator(); - final String fileName = dir.getFileName().toString(); - return fileName.endsWith(separator) ? dir.resolveSibling(fileName.substring(0, fileName.length() - 1)) : dir; + final String fileName = Objects.toString(dir.getFileName(), null); + return fileName != null && fileName.endsWith(separator) ? dir.resolveSibling(fileName.substring(0, fileName.length() - 1)) : dir; } /** diff --git a/src/test/java/org/apache/commons/io/file/PathUtilsContentEqualsTest.java b/src/test/java/org/apache/commons/io/file/PathUtilsContentEqualsTest.java index 45be9d739..71c3adb05 100644 --- a/src/test/java/org/apache/commons/io/file/PathUtilsContentEqualsTest.java +++ b/src/test/java/org/apache/commons/io/file/PathUtilsContentEqualsTest.java @@ -28,6 +28,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -106,7 +107,7 @@ public void testDirectoryAndFileContentEquals() throws Exception { * @throws Exception on test failure. */ @Test - public void testDirectoryAndFileContentEqualsDifferentFileSystems() throws Exception { + public void testDirectoryAndFileContentEqualsDifferentFileSystemsFileVsZip() throws Exception { final Path dir1 = Paths.get("src/test/resources/dir-equals-tests"); try (FileSystem fileSystem = FileSystems.newFileSystem(dir1.resolveSibling(dir1.getFileName() + ".zip"), null)) { final Path dir2 = fileSystem.getPath("/dir-equals-tests"); @@ -115,6 +116,59 @@ public void testDirectoryAndFileContentEqualsDifferentFileSystems() throws Excep } } + /** + * Tests IO-872 PathUtils.directoryAndFileContentEquals doesn't work across FileSystems. + * + * @throws Exception on test failure. + */ + @Test + public void testDirectoryAndFileContentEqualsDifferentFileSystemsZipVsZip() throws Exception { + final Path zipPath = Paths.get("src/test/resources/dir-equals-tests.zip"); + final Path zipCopy = temporaryFolder.toPath().resolve("copy.zip"); + Files.copy(zipPath, zipCopy, StandardCopyOption.REPLACE_EXISTING); + try (FileSystem fileSystem1 = FileSystems.newFileSystem(zipPath, null); + FileSystem fileSystem2 = FileSystems.newFileSystem(zipCopy, null)) { + final Path dir1 = fileSystem1.getPath("/dir-equals-tests"); + final Path dir2 = fileSystem2.getPath("/dir-equals-tests"); + // WindowsPath, UnixPath, and ZipPath equals() methods always return false if the argument is not of the same instance as itself. + assertTrue(PathUtils.directoryAndFileContentEquals(dir1, dir2)); + } + } + + /** + * Tests IO-872 PathUtils.directoryAndFileContentEquals doesn't work across FileSystems. + * + * @throws Exception on test failure. + */ + @Test + public void testDirectoryAndFileContentEqualsDifferentFileSystemsZipVsZipEmpty() throws Exception { + final Path zipPath = Paths.get("src/test/resources/dir-equals-tests.zip"); + final Path emptyZip = Paths.get("src/test/resources/org/apache/commons/io/empty.zip"); + Files.copy(zipPath, emptyZip, StandardCopyOption.REPLACE_EXISTING); + try (FileSystem fileSystem1 = FileSystems.newFileSystem(zipPath, null); + FileSystem fileSystem2 = FileSystems.newFileSystem(emptyZip, null)) { + final Path dir1 = fileSystem1.getPath("/dir-equals-tests"); + final Path dir2 = fileSystem2.getPath("/"); + // WindowsPath, UnixPath, and ZipPath equals() methods always return false if the argument is not of the same instance as itself. + assertFalse(PathUtils.directoryAndFileContentEquals(dir1, dir2)); + } + try (FileSystem fileSystem1 = FileSystems.newFileSystem(zipPath, null); + FileSystem fileSystem2 = FileSystems.newFileSystem(emptyZip, null)) { + final Path dir1 = fileSystem1.getPath("/dir-equals-tests"); + final Path dir2 = fileSystem2.getRootDirectories().iterator().next(); + // WindowsPath, UnixPath, and ZipPath equals() methods always return false if the argument is not of the same instance as itself. + assertFalse(PathUtils.directoryAndFileContentEquals(dir1, dir2)); + } + final Path zipCopy = temporaryFolder.toPath().resolve("copy.zip"); + Files.copy(emptyZip, zipCopy, StandardCopyOption.REPLACE_EXISTING); + try (FileSystem fileSystem1 = FileSystems.newFileSystem(emptyZip, null); + FileSystem fileSystem2 = FileSystems.newFileSystem(zipCopy, null)) { + final Path dir1 = fileSystem1.getPath(""); + final Path dir2 = fileSystem2.getPath(""); + // WindowsPath, UnixPath, and ZipPath equals() methods always return false if the argument is not of the same instance as itself. + assertTrue(PathUtils.directoryAndFileContentEquals(dir1, dir2)); + } + } @Test public void testDirectoryContentEquals() throws Exception { diff --git a/src/test/resources/org/apache/commons/io/empty.zip b/src/test/resources/org/apache/commons/io/empty.zip new file mode 100644 index 000000000..7eb7ce09c Binary files /dev/null and b/src/test/resources/org/apache/commons/io/empty.zip differ