From 5750324be2e15f1c0e1a4ebfdbcd18cf9b20b269 Mon Sep 17 00:00:00 2001 From: Benoit Quenaudon Date: Mon, 19 Jun 2023 14:20:02 +0200 Subject: [PATCH] Support symlink for NioFSWrappingFS --- .../kotlin/okio/AbstractFileSystemTest.kt | 24 ++++++++++++++-- .../okio/NioFileSystemWrappingFileSystem.kt | 28 +++++++++++++++++-- .../kotlin/okio/JvmSystemFileSystemTest.kt | 11 ++++++++ 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/okio-testing-support/src/commonMain/kotlin/okio/AbstractFileSystemTest.kt b/okio-testing-support/src/commonMain/kotlin/okio/AbstractFileSystemTest.kt index 0ec8bae427..3138ded940 100644 --- a/okio-testing-support/src/commonMain/kotlin/okio/AbstractFileSystemTest.kt +++ b/okio-testing-support/src/commonMain/kotlin/okio/AbstractFileSystemTest.kt @@ -90,12 +90,19 @@ abstract class AbstractFileSystemTest( } @Test - fun canonicalizeNoSuchFile() { + fun canonicalizeAbsolutePathNoSuchFile() { assertFailsWith { fileSystem.canonicalize(base / "no-such-file") } } + @Test + fun canonicalizeRelativePathNoSuchFile() { + assertFailsWith { + fileSystem.canonicalize("no-such-file".toPath()) + } + } + @Test fun canonicalizeFollowsSymlinkDirectories() { if (!supportsSymlink()) return @@ -2274,6 +2281,20 @@ abstract class AbstractFileSystemTest( assertEquals(listOf(baseBA, baseBB), fileSystem.list(baseB)) } + @Test + fun listDotDirectory() { + if (!supportsSymlink()) return + + println(fileSystem.metadata(".".toPath())) + + val paths = fileSystem.list(".".toPath()).map(Path::toString) + assertTrue(paths.joinToString()) { + paths.contains("jvm") && + paths.contains("src") && + paths.contains("build.gradle.kts") + } + } + @Test fun symlinkFileLastAccessedAt() { if (!supportsSymlink()) return @@ -2411,7 +2432,6 @@ abstract class AbstractFileSystemTest( if (windowsLimitations) return false return when (fileSystem::class.simpleName) { "JvmSystemFileSystem", - "NioFileSystemWrappingFileSystem", -> false else -> true } diff --git a/okio/src/jvmMain/kotlin/okio/NioFileSystemWrappingFileSystem.kt b/okio/src/jvmMain/kotlin/okio/NioFileSystemWrappingFileSystem.kt index 4131e09eb9..139c0e7aa6 100644 --- a/okio/src/jvmMain/kotlin/okio/NioFileSystemWrappingFileSystem.kt +++ b/okio/src/jvmMain/kotlin/okio/NioFileSystemWrappingFileSystem.kt @@ -46,7 +46,12 @@ internal class NioFileSystemWrappingFileSystem(javaNioFileSystem: JavaNioFileSys * nio file system in order for things to work properly. */ private fun Path.resolve(readSymlink: Boolean = false): NioPath { - val resolved = delegateRoot.resolve(toString()) + val resolved = if (isRelative) { + delegateRoot.resolve(this.toFile().canonicalPath) + } else { + delegateRoot.resolve(toString()) + } + return if (readSymlink && resolved.isSymbolicLink()) { resolved.readSymbolicLink() } else { @@ -54,6 +59,18 @@ internal class NioFileSystemWrappingFileSystem(javaNioFileSystem: JavaNioFileSys } } + override fun canonicalize(path: Path): Path { + if (path.isAbsolute) { + try { + return path.resolve(readSymlink = true).toRealPath().toOkioPath() + } catch (e: NoSuchFileException) { + throw FileNotFoundException("no such file $path") + } + } else { + return super.canonicalize(path) + } + } + override fun metadataOrNull(path: Path): FileMetadata? { return metadataOrNull(path.resolve()) } @@ -195,7 +212,14 @@ internal class NioFileSystemWrappingFileSystem(javaNioFileSystem: JavaNioFileSys } override fun createSymlink(source: Path, target: Path) { - Files.createSymbolicLink(source.resolve(), target.resolve()) + val sourceNioPath = source.resolve() + val targetNioPath = + if (source.isAbsolute && target.isRelative) { + sourceNioPath.parent.resolve(target.toString()) + } else { + target.resolve() + } + Files.createSymbolicLink(sourceNioPath, targetNioPath) } override fun toString(): String = "NioFileSystemWrappingFileSystem" diff --git a/okio/src/jvmTest/kotlin/okio/JvmSystemFileSystemTest.kt b/okio/src/jvmTest/kotlin/okio/JvmSystemFileSystemTest.kt index 1463727c0c..75edf5d0fa 100644 --- a/okio/src/jvmTest/kotlin/okio/JvmSystemFileSystemTest.kt +++ b/okio/src/jvmTest/kotlin/okio/JvmSystemFileSystemTest.kt @@ -18,6 +18,7 @@ package okio import com.google.common.jimfs.Configuration import com.google.common.jimfs.Jimfs import java.io.InterruptedIOException +import java.nio.file.FileSystems import kotlin.test.assertEquals import kotlin.test.assertFalse import kotlin.test.fail @@ -73,3 +74,13 @@ class NioFileSystemWrappingFileSystemTest : AbstractFileSystemTest( allowAtomicMoveFromFileToDirectory = true, temporaryDirectory = FileSystem.SYSTEM_TEMPORARY_DIRECTORY, ) + +class NioDefaultFileSystemWrappingFileSystemTest : AbstractFileSystemTest( + clock = Clock.System, + fileSystem = FileSystems.getDefault().asOkioFileSystem(), + windowsLimitations = false, + allowClobberingEmptyDirectories = Path.DIRECTORY_SEPARATOR == "\\", + allowAtomicMoveFromFileToDirectory = false, + allowRenameWhenTargetIsOpen = Path.DIRECTORY_SEPARATOR != "\\", + temporaryDirectory = FileSystem.SYSTEM_TEMPORARY_DIRECTORY, +)