diff --git a/libraries/stdlib/jdk7/src/kotlin/io/path/PathRecursiveFunctions.kt b/libraries/stdlib/jdk7/src/kotlin/io/path/PathRecursiveFunctions.kt index 1af535e0fb8..6706d3b1e9f 100644 --- a/libraries/stdlib/jdk7/src/kotlin/io/path/PathRecursiveFunctions.kt +++ b/libraries/stdlib/jdk7/src/kotlin/io/path/PathRecursiveFunctions.kt @@ -161,11 +161,13 @@ public fun Path.copyToRecursively( // TODO: KT-38678 // source and target files are the same entry, continue recursive copy operation } else { - val realPath = this.toRealPath() - val isSubdirectory = if (targetExistsAndNotSymlink) { - target.toRealPath().startsWith(realPath) - } else { - target.parent?.let { it.exists() && it.toRealPath().startsWith(realPath) } ?: false + val isSubdirectory = when { + this.fileSystem != target.fileSystem -> + false + targetExistsAndNotSymlink -> + target.toRealPath().startsWith(this.toRealPath()) + else -> + target.parent?.let { it.exists() && it.toRealPath().startsWith(this.toRealPath()) } ?: false } if (isSubdirectory) throw FileSystemException( @@ -178,7 +180,7 @@ public fun Path.copyToRecursively( fun destination(source: Path): Path { val relativePath = source.relativeTo(this@copyToRecursively) - return target.resolve(relativePath) + return target.resolve(relativePath.pathString) } fun error(source: Path, exception: Exception): FileVisitResult { diff --git a/libraries/stdlib/jdk7/test/PathRecursiveFunctionsTest.kt b/libraries/stdlib/jdk7/test/PathRecursiveFunctionsTest.kt index 31334f88358..25c9eba1471 100644 --- a/libraries/stdlib/jdk7/test/PathRecursiveFunctionsTest.kt +++ b/libraries/stdlib/jdk7/test/PathRecursiveFunctionsTest.kt @@ -5,7 +5,10 @@ package kotlin.jdk7.test +import java.net.URI import java.nio.file.* +import java.util.zip.ZipEntry +import java.util.zip.ZipOutputStream import kotlin.io.path.* import kotlin.jdk7.test.PathTreeWalkTest.Companion.createTestFiles import kotlin.jdk7.test.PathTreeWalkTest.Companion.referenceFilenames @@ -970,4 +973,50 @@ class PathRecursiveFunctionsTest : AbstractPathTest() { src.copyToRecursively(dst, followLinks = false, overwrite = true) } + + private fun createZipFile(parent: Path, name: String): Path { + val zipRoot = parent.resolve(name) + ZipOutputStream(zipRoot.outputStream()).use { out -> + out.putNextEntry(ZipEntry("directory/file.txt")) + out.write("hello".toByteArray()) + out.closeEntry() + } + return zipRoot + } + + @Test + fun zipToDefaultPath() { + val root = createTempDirectory().cleanupRecursively() + val zipRoot = createZipFile(root, "src.zip") + val dst = root.resolve("dst") + + val classLoader: ClassLoader? = null + FileSystems.newFileSystem(zipRoot, classLoader).use { zipFs -> + val src = zipFs.getPath("/directory") + + src.copyToRecursively(dst, followLinks = false) + + val expected = listOf("", "file.txt") + testVisitedFiles(expected, dst.walkIncludeDirectories(), dst) + assertEquals("hello", dst.resolve("file.txt").readText()) + } + } + + @Test + fun defaultPathToZip() { + val root = createTestFiles().cleanupRecursively() + val zipRoot = createZipFile(root, "dst.zip") + val src = root.resolve("1").also { it.resolve("3/4.txt").writeText("hello") } + + val classLoader: ClassLoader? = null + FileSystems.newFileSystem(zipRoot, classLoader).use { zipFs -> + val dst = zipFs.getPath("/directory") + + src.copyToRecursively(dst, followLinks = false) + + val expected = listOf("", "2", "3", "3/4.txt", "3/5.txt", "file.txt") + testVisitedFiles(expected, dst.walkIncludeDirectories(), dst) + assertEquals("hello", zipFs.getPath("/directory/3/4.txt").readText()) + } + } }