diff --git a/base/src/main/kotlin/de/staropensource/engine/base/utility/FileAccess.kt b/base/src/main/kotlin/de/staropensource/engine/base/utility/FileAccess.kt index c4bd928e5..c6c7c8698 100644 --- a/base/src/main/kotlin/de/staropensource/engine/base/utility/FileAccess.kt +++ b/base/src/main/kotlin/de/staropensource/engine/base/utility/FileAccess.kt @@ -202,13 +202,16 @@ class FileAccess { // Delete all files recursively // Only applies to directories - it.sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete) + Files.walkFileTree(path, DeleteDirectoryVisitor()) // Delete file or directory if (Files.exists(path)) - if (!path.toFile().delete()) - logger.sarn("Unable to delete file or directory '${unformatFromPath(path)}' scheduled for deletion manually") + try { + Files.delete(path) + } catch (_: NoSuchFileException) { + } } + } catch (_: NoSuchFileException) { } catch (exception: Exception) { logger.sarn("Unable to delete file or directory '${unformatFromPath(path)}' scheduled for deletion.\n${StackTraceUtils.stacktraceRecursive(exception)}") } @@ -617,7 +620,6 @@ class FileAccess { * @throws IOAccessException on IO error * @see verifyIsLink * @see verifyIsSymbolicLink - * @see verifyIsHardLink * @since v1-alpha10 */ @Throws(IOAccessException::class) @@ -715,7 +717,7 @@ class FileAccess { logger.diag("Deleting '${unformatFromPath(path)}'") if (!isSymbolicLink() && file.isDirectory) - Files.walkFileTree(path, DeleteDirectoryVisitor(path)) + Files.walkFileTree(path, DeleteDirectoryVisitor()) Files.delete(path) } catch (_: NoSuchFileException) { @@ -1475,16 +1477,15 @@ class FileAccess { * {@link FileVisitor} instance for * delete directories recursively. * - * @param directory directory to delete * @since v1-alpha9 */ - private class DeleteDirectoryVisitor(directory: Path) : FileVisitor { + private class DeleteDirectoryVisitor : FileVisitor { override fun preVisitDirectory(path: Path, attributes: BasicFileAttributes): FileVisitResult { return FileVisitResult.CONTINUE } override fun visitFile(path: Path, attributes: BasicFileAttributes): FileVisitResult { - path.toFile().delete() + Files.delete(path) return FileVisitResult.CONTINUE } diff --git a/base/src/test/kotlin/de/staropensource/engine/base/utility/FileAccessTest.kt b/base/src/test/kotlin/de/staropensource/engine/base/utility/FileAccessTest.kt index 5ba858a12..ef1940a87 100644 --- a/base/src/test/kotlin/de/staropensource/engine/base/utility/FileAccessTest.kt +++ b/base/src/test/kotlin/de/staropensource/engine/base/utility/FileAccessTest.kt @@ -23,6 +23,7 @@ import de.staropensource.engine.base.Engine import de.staropensource.engine.base.TestBase import de.staropensource.engine.base.utility.FileAccess.Type import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.CsvSource @@ -90,6 +91,7 @@ class FileAccessTest : TestBase() { "/./did/somebody\\/say\\yoga" , "/did/somebody/say/yoga" "test.txt", "+/test.txt"""" ) + @DisplayName("toString") fun toStringTest(supplyValue: String, compareValue: String) { assertEquals( transformToStringPath(compareValue), @@ -215,6 +217,7 @@ class FileAccessTest : TestBase() { } @Test + @DisplayName("exists (void)") fun existsVoid() { assertFalse( FileAccess @@ -227,6 +230,7 @@ class FileAccessTest : TestBase() { } @Test + @DisplayName("exists (file)") fun existsFile() { assertTrue( FileAccess @@ -240,6 +244,7 @@ class FileAccessTest : TestBase() { } @Test + @DisplayName("exists (directory)") fun existsDirectory() { assertTrue( FileAccess @@ -257,7 +262,8 @@ class FileAccessTest : TestBase() { true, false ]) - fun existsSymlinkReal(noFollowSymbolicLink: Boolean) { + @DisplayName("exists (symbolic link, real)") + fun existsSymbolicLinkReal(noFollowSymbolicLink: Boolean) { assertTrue( FileAccess .temporaryCacheDirectory!! @@ -266,7 +272,7 @@ class FileAccessTest : TestBase() { .verifyNotExists() .createLink( FileAccess.temporaryCacheDirectory!! - .traverse("existsSymlinkReal.target.txt") + .traverse("existsSymbolicLinkReal.target.txt") .createFile() .verifyIsFile(), false @@ -280,12 +286,13 @@ class FileAccessTest : TestBase() { true, false ]) - fun existsSymlinkFake(noFollowSymbolicLink: Boolean) { + @DisplayName("exists (symbolic link, fake)") + fun existsSymbolicLinkFake(noFollowSymbolicLink: Boolean) { assertEquals( noFollowSymbolicLink, FileAccess .temporaryCacheDirectory!! - .traverse("existsSymlinkFake.link.txt") + .traverse("existsSymbolicLinkFake.link.txt") .delete() .verifyNotExists() .createLink( @@ -305,6 +312,7 @@ class FileAccessTest : TestBase() { true, false ]) + @DisplayName("exists (hard link, real)") fun existsHardlinkReal(noFollowSymbolicLink: Boolean) { assertTrue( FileAccess @@ -328,6 +336,7 @@ class FileAccessTest : TestBase() { true, false ]) + @DisplayName("exists (hard link, fake)") fun existsHardlinkFake(noFollowSymbolicLink: Boolean) { val target: FileAccess = FileAccess .temporaryCacheDirectory!! @@ -351,6 +360,7 @@ class FileAccessTest : TestBase() { } @Test + @DisplayName("getType (void)") fun getTypeVoid() { assertEquals( Type.VOID, @@ -364,6 +374,7 @@ class FileAccessTest : TestBase() { } @Test + @DisplayName("getType (file)") fun getTypeFile() { assertEquals( Type.FILE, @@ -379,6 +390,7 @@ class FileAccessTest : TestBase() { } @Test + @DisplayName("getType (directory)") fun getTypeDirectory() { assertEquals( Type.DIRECTORY, @@ -394,6 +406,7 @@ class FileAccessTest : TestBase() { } @Test + @DisplayName("isSymbolicLink (real)") fun isSymbolicLinkReal() { assertTrue( FileAccess @@ -413,6 +426,7 @@ class FileAccessTest : TestBase() { } @Test + @DisplayName("isSymbolicLink (fake)") fun isSymbolicLinkFake() { assertTrue( FileAccess @@ -440,6 +454,7 @@ class FileAccessTest : TestBase() { "very\\\cool\\/directory/structure", "+%very/cool/directory/structure" "some.spot", "+%some.spot"""" ) + @DisplayName("getLinkDestination (real)") fun getLinkDestinationReal(supplyValue: String, compareValue: String) { assertEquals( transformToStringPath(compareValue), @@ -469,6 +484,7 @@ class FileAccessTest : TestBase() { "getLinkDestinationSymlinkFake.d/very\\\cool\\/directory/structure", "+%getLinkDestinationSymlinkFake.d/very/cool/directory/structure" "getLinkDestinationSymlinkFake.d/some.spot", "+%getLinkDestinationSymlinkFake.d/some.spot"""" ) + @DisplayName("getLinkDestination (fake)") fun getLinkDestinationFake(supplyValue: String, compareValue: String) { assertEquals( transformToStringPath(compareValue), @@ -559,6 +575,7 @@ class FileAccessTest : TestBase() { // already covered by the exists* link tests @Test + @DisplayName("move (file)") fun moveFile() { val target: FileAccess = FileAccess .temporaryCacheDirectory!! @@ -577,6 +594,7 @@ class FileAccessTest : TestBase() { } @Test + @DisplayName("move (directory)") fun moveDirectory() { val target: FileAccess = FileAccess .temporaryCacheDirectory!! @@ -611,6 +629,7 @@ class FileAccessTest : TestBase() { } @Test + @DisplayName("copy (file)") fun copyFile() { val target: FileAccess = FileAccess .temporaryCacheDirectory!! @@ -629,6 +648,7 @@ class FileAccessTest : TestBase() { } @Test + @DisplayName("copy (directory)") fun copyDirectory() { val target: FileAccess = FileAccess .temporaryCacheDirectory!! @@ -670,6 +690,7 @@ class FileAccessTest : TestBase() { } @Test + @DisplayName("delete (file)") fun deleteFile() { val file: FileAccess = FileAccess .temporaryCacheDirectory!! @@ -684,6 +705,7 @@ class FileAccessTest : TestBase() { } @Test + @DisplayName("delete (directory)") fun deleteDirectory() { val file: FileAccess = FileAccess .temporaryCacheDirectory!! @@ -714,6 +736,7 @@ class FileAccessTest : TestBase() { } @Test + @DisplayName("deleteOnShutdown (file)") fun deleteOnShutdownFile() { val file: FileAccess = FileAccess .temporaryCacheDirectory!! @@ -730,6 +753,7 @@ class FileAccessTest : TestBase() { } @Test + @DisplayName("deleteOnShutdown (directory)") fun deleteOnShutdownDirectory() { val file: FileAccess = FileAccess .temporaryCacheDirectory!! @@ -762,6 +786,7 @@ class FileAccessTest : TestBase() { } @Test + @DisplayName("readBytes & writeBytes") fun readWriteBytes() { val bytes: ByteArray = byteArrayOf( 0x62, 0x75, 0x73, 0x68, @@ -786,6 +811,7 @@ class FileAccessTest : TestBase() { } @Test + @DisplayName("readLines & writeLines") fun readWriteLines() { val lines: List = listOf( "This is an example file", @@ -810,6 +836,7 @@ class FileAccessTest : TestBase() { } @Test + @DisplayName("readString & writeString") fun readWriteString() { val string: String = """ This is an example file