diff --git a/libraries/stdlib/src/kotlin/io/files/FilePathComponents.kt b/libraries/stdlib/src/kotlin/io/files/FilePathComponents.kt index ba57839f125..463b15e7305 100644 --- a/libraries/stdlib/src/kotlin/io/files/FilePathComponents.kt +++ b/libraries/stdlib/src/kotlin/io/files/FilePathComponents.kt @@ -29,12 +29,11 @@ private fun String.getRootName(): String { // So in Windows we'll have root of //my.host/home but in Unix just / first = indexOf(File.separatorChar, 2) if (first >= 0) { - val dot = indexOf('.', 2) - if (dot >= 0 && dot < first) { - first = indexOf(File.separatorChar, first + 1) - if (first >= 0) - return substring(0, first + 1) - } + first = indexOf(File.separatorChar, first + 1) + if (first >= 0) + return substring(0, first + 1) + else + return this } } return substring(0, 1) @@ -65,18 +64,23 @@ private fun String.getRootName(): String { * @return string representing the root for this file, or empty string is this file name is relative. */ public val File.rootName: String - get() = separatorsToSystem().getRootName() + get() = path.getRootName() /** * Returns root component of this abstract name, like / from /home/user, or C:\ from C:\file.tmp, - * or //my.host/home for //my.host/home/user, - * or `null` if this name is relative, like bar/gav + * or //my.host/home for //my.host/home/user */ -public val File.root: File? - get() { - val name = rootName - return if (name.length > 0) File(name) else null - } +public val File.root: File + get() = File(rootName) + +/** + * Determines whether this file has a root or it represents a relative path. + * + * Returns `true` when this file has non-empty root. + */ +public val File.isRooted: Boolean + // TODO: Do not calculate root + get() = path.getRootName().isNotEmpty() /** * Represents the path to a file as a collection of directories. @@ -91,12 +95,19 @@ public data class FilePathComponents @Deprecated("This constructor will be removed soon. Use File.toComponents() extension to create an instance of FilePathComponents.") constructor (rootName: String, fileList: List): this(File(rootName), fileList) - @Deprecated("Use 'root' property or 'root.path' instead.", ReplaceWith("root.path")) - public val rootName: String get() = root.path - @Deprecated("Use 'segments' property instead.", ReplaceWith("segments")) public val fileList: List get() = segments + /** + * Returns a string representing the root for this file, or an empty string is this file name is relative. + */ + public val rootName: String get() = root.path + + /** + * Returns `true` when the [root] is not empty. + */ + public val isRooted: Boolean get() = root.path.isNotEmpty() + /** * Returns the number of elements in the path to the file. */ @@ -122,7 +133,7 @@ public data class FilePathComponents * itself) and returns the resulting collection of components. */ public fun File.toComponents(): FilePathComponents { - val path = separatorsToSystem() + val path = path val rootName = path.getRootName() val subPath = path.substring(rootName.length) // if: a special case when we have only root component diff --git a/libraries/stdlib/src/kotlin/io/files/Utils.kt b/libraries/stdlib/src/kotlin/io/files/Utils.kt index b51c0cf0343..298661c3539 100644 --- a/libraries/stdlib/src/kotlin/io/files/Utils.kt +++ b/libraries/stdlib/src/kotlin/io/files/Utils.kt @@ -69,7 +69,7 @@ public val File.extension: String * * @return the pathname with system separators. */ -@Deprecated("Use File.separatorsToSystem instead", ReplaceWith("File(this).separatorsToSystem()", "java.io.File")) +@Deprecated("Use File.path instead", ReplaceWith("File(this).path", "java.io.File")) public fun String.separatorsToSystem(): String { val otherSep = if (File.separator == "/") "\\" else "/" return replace(otherSep, File.separator) @@ -101,10 +101,18 @@ public fun String.allSeparatorsToSystem(): String { * * @return the pathname with system separators. */ +@Deprecated("File has already system separators.") public fun File.separatorsToSystem(): String { return toString().separatorsToSystem() } +/** + * Returns [path] of this File using the invariant separator '/' to + * separate the names in the name sequence. + */ +public val File.invariantSeparatorsPath: String + get() = if (File.separatorChar != '/') path.replace(File.separatorChar, '/') else path + /** * Returns file's name without an extension. */ @@ -118,16 +126,60 @@ public val File.nameWithoutExtension: String * * @return relative path from [base] to this. * - * @throws IllegalArgumentException if child and parent have different roots. + * @throws IllegalArgumentException if this and base paths have different roots. */ +@Deprecated("This function will change return type to File soon. Use toRelativeString instead.", ReplaceWith("toRelativeString(base)")) public fun File.relativeTo(base: File): String - = relativeToOrNull(base) ?: throw IllegalArgumentException("this and base files have different roots: $this and $base") + = toRelativeString(base) -// TODO -//private fun File.relativeToOrPath(base: File): String -// = relativeToOrNull(base) ?: toString() -private fun File.relativeToOrNull(base: File): String? { +/** + * Calculates the relative path for this file from [base] file. + * Note that the [base] file is treated as a directory. + * If this file matches the [base] file, then an empty string will be returned. + * + * @return relative path from [base] to this. + * + * @throws IllegalArgumentException if this and base paths have different roots. + */ +public fun File.toRelativeString(base: File): String + = toRelativeStringOrNull(base) ?: throw IllegalArgumentException("this and base files have different roots: $this and $base") + +/** + * Calculates the relative path for this file from [base] file. + * Note that the [base] file is treated as a directory. + * If this file matches the [base] file, then a [File] with empty path will be returned. + * + * @return File with relative path from [base] to this. + * + * @throws IllegalArgumentException if this and base paths have different roots. + */ +@Deprecated("This function will be renamed to relativeTo soon.") +public fun File.relativeToFile(base: File): File = File(this.relativeTo(base)) + + +/** + * Calculates the relative path for this file from [base] file. + * Note that the [base] file is treated as a directory. + * If this file matches the [base] file, then a [File] with empty path will be returned. + * + * @return File with relative path from [base] to this, or `this` if this and base paths have different roots. + */ +public fun File.relativeToOrSelf(base: File): File + = toRelativeStringOrNull(base)?.let { File(it) } ?: this + +/** + * Calculates the relative path for this file from [base] file. + * Note that the [base] file is treated as a directory. + * If this file matches the [base] file, then a [File] with empty path will be returned. + * + * @return File with relative path from [base] to this, or `null` if this and base paths have different roots. + */ +public fun File.relativeToOrNull(base: File): File? + = toRelativeStringOrNull(base)?.let { File(it) } + + +private fun File.toRelativeStringOrNull(base: File): String? { // Check roots val thisComponents = this.toComponents().normalize() val baseComponents = base.toComponents().normalize() @@ -411,7 +463,7 @@ private fun List.normalize(): List { * @return concatenated this and [relative] paths, or just [relative] if it's absolute. */ public fun File.resolve(relative: File): File { - if (relative.root != null) + if (relative.isRooted) return relative val baseName = this.toString() return if (baseName.isEmpty() || baseName.endsWith(File.separatorChar)) File(baseName + relative) else File(baseName + File.separatorChar + relative) diff --git a/libraries/stdlib/test/io/FileTreeWalks.kt b/libraries/stdlib/test/io/FileTreeWalks.kt index 8f3ffa037cf..44c3a6adf9e 100644 --- a/libraries/stdlib/test/io/FileTreeWalks.kt +++ b/libraries/stdlib/test/io/FileTreeWalks.kt @@ -11,7 +11,6 @@ class FileTreeWalkTest { companion object { val referenceFilenames = listOf("1", "1/2", "1/3", "1/3/4.txt", "1/3/5.txt", "6", "7.txt", "8", "8/9.txt") - .map { it.separatorsToSystem() } fun createTestFiles(): File { val basedir = createTempDir() for (name in referenceFilenames) { @@ -31,14 +30,14 @@ class FileTreeWalkTest { val referenceNames = setOf("") + referenceFilenames val namesTopDown = HashSet() for (file in basedir.walkTopDown()) { - val name = file.relativeTo(basedir) + val name = file.relativeToOrSelf(basedir).invariantSeparatorsPath assertFalse(namesTopDown.contains(name), "$name is visited twice") namesTopDown.add(name) } assertEquals(referenceNames, namesTopDown) val namesBottomUp = HashSet() for (file in basedir.walkBottomUp()) { - val name = file.relativeTo(basedir) + val name = file.relativeToOrSelf(basedir).invariantSeparatorsPath assertFalse(namesBottomUp.contains(name), "$name is visited twice") namesBottomUp.add(name) } @@ -69,13 +68,12 @@ class FileTreeWalkTest { val basedir = createTestFiles() try { val referenceNames = - listOf("", "1", "1/2", "6", "8").map( - { it -> it.separatorsToSystem() }).toHashSet() + setOf("", "1", "1/2", "6", "8") val namesTopDownEnter = HashSet() val namesTopDownLeave = HashSet() val namesTopDown = HashSet() fun enter(file: File): Boolean { - val name = file.relativeTo(basedir) + val name = file.relativeToOrSelf(basedir).invariantSeparatorsPath assertTrue(file.isDirectory, "$name is not directory, only directories should be entered") assertFalse(namesTopDownEnter.contains(name), "$name is entered twice") assertFalse(namesTopDownLeave.contains(name), "$name is left before entrance") @@ -85,7 +83,7 @@ class FileTreeWalkTest { } fun leave(file: File) { - val name = file.relativeTo(basedir) + val name = file.relativeToOrSelf(basedir).invariantSeparatorsPath assertTrue(file.isDirectory, "$name is not directory, only directories should be left") assertFalse(namesTopDownLeave.contains(name), "$name is left twice") namesTopDownLeave.add(name) @@ -93,7 +91,7 @@ class FileTreeWalkTest { } fun visit(file: File) { - val name = file.relativeTo(basedir) + val name = file.relativeToOrSelf(basedir).invariantSeparatorsPath if (file.isDirectory) { assertTrue(namesTopDownEnter.contains(name), "$name is visited before entrance") namesTopDown.add(name) @@ -103,7 +101,7 @@ class FileTreeWalkTest { return val parent = file.parentFile if (parent != null) { - val parentName = parent.relativeTo(basedir) + val parentName = parent.relativeToOrSelf(basedir).invariantSeparatorsPath assertTrue(namesTopDownEnter.contains(parentName), "$name is visited before entering its parent $parentName") assertFalse(namesTopDownLeave.contains(parentName), @@ -131,11 +129,9 @@ class FileTreeWalkTest { @Test fun withFilterAndMap() { val basedir = createTestFiles() try { - val referenceNames = - listOf("", "1", "1/2", "1/3", "6", "8").map( - { it -> it.separatorsToSystem() }).toHashSet() + val referenceNames = setOf("", "1", "1/2", "1/3", "6", "8") assertEquals(referenceNames, basedir.walkTopDown().filter { it.isDirectory() }.map { - it.relativeTo(basedir) + it.relativeToOrSelf(basedir).invariantSeparatorsPath }.toHashSet()) } finally { basedir.deleteRecursively() @@ -146,9 +142,7 @@ class FileTreeWalkTest { @Test fun withDeleteTxtTopDown() { val basedir = createTestFiles() try { - val referenceNames = - listOf("", "1", "1/2", "1/3", "6", "8").map( - { it -> it.separatorsToSystem() }).toHashSet() + val referenceNames = setOf("", "1", "1/2", "1/3", "6", "8") val namesTopDown = HashSet() fun enter(file: File) { assertTrue(file.isDirectory()) @@ -158,7 +152,7 @@ class FileTreeWalkTest { } } for (file in basedir.walkTopDown().enter(::enter)) { - val name = file.relativeTo(basedir) + val name = file.relativeToOrSelf(basedir).invariantSeparatorsPath assertFalse(namesTopDown.contains(name), "$name is visited twice") namesTopDown.add(name) } @@ -171,9 +165,7 @@ class FileTreeWalkTest { @Test fun withDeleteTxtBottomUp() { val basedir = createTestFiles() try { - val referenceNames = - listOf("", "1", "1/2", "1/3", "6", "8").map( - { it -> it.separatorsToSystem() }).toHashSet() + val referenceNames = setOf("", "1", "1/2", "1/3", "6", "8") val namesTopDown = HashSet() fun enter(file: File) { assertTrue(file.isDirectory()) @@ -183,7 +175,7 @@ class FileTreeWalkTest { } } for (file in basedir.walkBottomUp().enter(::enter)) { - val name = file.relativeTo(basedir) + val name = file.relativeToOrSelf(basedir).invariantSeparatorsPath assertFalse(namesTopDown.contains(name), "$name is visited twice") namesTopDown.add(name) } @@ -270,13 +262,13 @@ class FileTreeWalkTest { @Test fun withVisitorAndDepth() { val basedir = createTestFiles() try { - val files = HashSet() - val dirs = HashSet() + val files = HashSet() + val dirs = HashSet() val failed = HashSet() val stack = ArrayList() fun beforeVisitDirectory(dir: File) { stack.add(dir) - dirs.add(dir.relativeTo(basedir)) + dirs.add(dir.relativeToOrSelf(basedir)) } fun afterVisitDirectory(dir: File) { @@ -286,7 +278,7 @@ class FileTreeWalkTest { fun visitFile(file: File) { assert(stack.last().listFiles().contains(file)) { file } - files.add(file.relativeTo(basedir)) + files.add(file.relativeToOrSelf(basedir)) } fun visitDirectoryFailed(dir: File, e: IOException) { @@ -298,10 +290,10 @@ class FileTreeWalkTest { fail(::visitDirectoryFailed).forEach { it -> if (!it.isDirectory()) visitFile(it) } assert(stack.isEmpty()) val sep = File.separator - for (fileName in arrayOf("", "1", "1${sep}2", "1${sep}3", "6", "8")) { + for (fileName in arrayOf("", "1", "1/2", "1/3", "6", "8")) { assert(dirs.contains(fileName)) { fileName } } - for (fileName in arrayOf("1${sep}3${sep}4.txt", "1${sep}3${sep}4.txt", "7.txt", "8${sep}9.txt")) { + for (fileName in arrayOf("1/3/4.txt", "1/3/4.txt", "7.txt", "8/9.txt")) { assert(files.contains(fileName)) { fileName } } @@ -311,9 +303,9 @@ class FileTreeWalkTest { basedir.walkTopDown().enter(::beforeVisitDirectory).leave(::afterVisitDirectory).maxDepth(1). forEach { it -> if (it != basedir) visitFile(it) } assert(stack.isEmpty()) - assert(dirs.size == 1 && dirs.contains("")) { dirs.size } + assert(dirs.size == 1 && dirs.contains(File(""))) { dirs.size } for (file in arrayOf("1", "6", "7.txt", "8")) { - assert(files.contains(file)) { file } + assert(files.contains(File(file))) { file } } //restrict access @@ -327,11 +319,11 @@ class FileTreeWalkTest { assert(failed.size == 1 && failed.contains("1")) { failed.size } assert(dirs.size == 4) { dirs.size } for (dir in arrayOf("", "1", "6", "8")) { - assert(dirs.contains(dir)) { dir } + assert(dirs.contains(File(dir))) { dir } } assert(files.size == 2) { files.size } - for (file in arrayOf("7.txt", "8${sep}9.txt")) { - assert(files.contains(file)) { file } + for (file in arrayOf("7.txt", "8/9.txt")) { + assert(files.contains(File(file))) { file } } } finally { File(basedir, "1").setReadable(true) @@ -418,7 +410,7 @@ class FileTreeWalkTest { @Test fun find() { val basedir = createTestFiles() try { - File(basedir, "8/4.txt".separatorsToSystem()).createNewFile() + File(basedir, "8/4.txt").createNewFile() var count = 0 basedir.walkTopDown().takeWhile { it -> count == 0 }.forEach { if (it.name == "4.txt") { diff --git a/libraries/stdlib/test/io/Files.kt b/libraries/stdlib/test/io/Files.kt index 4fb7022c006..e20a975fa8d 100644 --- a/libraries/stdlib/test/io/Files.kt +++ b/libraries/stdlib/test/io/Files.kt @@ -75,7 +75,7 @@ class FilesTest { val file1 = File("/foo/bar/baz") val file2 = File("/foo/baa/ghoo") - assertEquals("../../bar/baz".separatorsToSystem(), file1.relativeTo(file2)) + assertEquals("../../bar/baz", file1.relativeToFile(file2).invariantSeparatorsPath) val file3 = File("/foo/bar") @@ -91,10 +91,10 @@ class FilesTest { val file5 = File("/foo/baran") - assertEquals("../bar".separatorsToSystem(), file3.relativeTo(file5)) - assertEquals("../baran".separatorsToSystem(), file5.relativeTo(file3)) - assertEquals("../bar".separatorsToSystem(), file4.relativeTo(file5)) - assertEquals("../baran".separatorsToSystem(), file5.relativeTo(file4)) + assertEquals("../bar", file3.relativeToFile(file5).invariantSeparatorsPath) + assertEquals("../baran", file5.relativeToFile(file3).invariantSeparatorsPath) + assertEquals("../bar", file4.relativeToFile(file5).invariantSeparatorsPath) + assertEquals("../baran", file5.relativeToFile(file4).invariantSeparatorsPath) val file6 = File("C:\\Users\\Me") val file7 = File("C:\\Users\\Me\\Documents") @@ -109,8 +109,8 @@ class FilesTest { val file8 = File("""\\my.host\home/user/documents/vip""") val file9 = File("""\\my.host\home/other/images/nice""") - assertEquals("../../../user/documents/vip".separatorsToSystem(), file8.relativeTo(file9)) - assertEquals("../../../other/images/nice".separatorsToSystem(), file9.relativeTo(file8)) + assertEquals("../../../user/documents/vip", file8.relativeToFile(file9).invariantSeparatorsPath) + assertEquals("../../../other/images/nice", file9.relativeToFile(file8).invariantSeparatorsPath) } @test fun relativeToRelative() { @@ -165,56 +165,66 @@ class FilesTest { } assertFailsRelativeTo(File("y"), File("../x")) + + // This test operates correctly only at Windows PCs with C & D drives + val fileOnC = File("C:/dir1") + val fileOnD = File("D:/dir2") + assertFailsRelativeTo(fileOnC, fileOnD) } @test fun relativeTo() { - assertEquals("kotlin", File("src/kotlin".separatorsToSystem()).relativeTo(File("src"))) + assertEquals("kotlin", File("src/kotlin").relativeTo(File("src"))) assertEquals("", File("dir").relativeTo(File("dir"))) - assertEquals("..", File("dir").relativeTo(File("dir/subdir".separatorsToSystem()))) - assertEquals("../../test".separatorsToSystem(), File("test").relativeTo(File("dir/dir".separatorsToSystem()))) - - // This test operates correctly only at Windows PCs with C & D drives - val file1 = File("C:/dir1".separatorsToSystem()) - val file2 = File("D:/dir2".separatorsToSystem()) - try { - file1.relativeTo(file2) - assert(false); - } catch (e: IllegalArgumentException) { - // It's the thing we should get here - } catch (e: IOException) { - // The device is not ready (D) ==> DO NOTHING - } + assertEquals("..", File("dir").relativeTo(File("dir/subdir"))) + assertEquals(File("../../test"), File("test").relativeToFile(File("dir/dir"))) } - private fun checkFileElements(f: File, root: File?, elements: List) { - var i = 0 + private fun checkFilePathComponents(f: File, root: File, elements: List) { assertEquals(root, f.root) - for (elem in f.toComponents().segments) { - assertTrue(i < elements.size, i.toString()) - assertEquals(elements[i++], elem.toString()) - } - assertEquals(elements.size, i) + val components = f.toComponents() + assertEquals(root, components.root) + assertEquals(elements, components.segments.map { it.toString() }) } - @test fun fileIterator() { - checkFileElements(File("/foo/bar"), File("/"), listOf("foo", "bar")) - checkFileElements(File("\\foo\\bar"), File("\\".separatorsToSystem()), listOf("foo", "bar")) - checkFileElements(File("/foo/bar/gav"), File("/"), listOf("foo", "bar", "gav")) - checkFileElements(File("/foo/bar/gav/"), File("/"), listOf("foo", "bar", "gav")) - checkFileElements(File("bar/gav"), null, listOf("bar", "gav")) - checkFileElements(File("C:\\bar\\gav"), File("C:\\".separatorsToSystem()), listOf("bar", "gav")) - checkFileElements(File("C:/bar/gav"), File("C:/"), listOf("bar", "gav")) - checkFileElements(File("C:\\"), File("C:\\".separatorsToSystem()), listOf()) - checkFileElements(File("C:/"), File("C:/"), listOf()) - checkFileElements(File("C:"), File("C:"), listOf()) - if (File.separatorChar == '\\') { + @test fun filePathComponents() { + checkFilePathComponents(File("/foo/bar"), File("/"), listOf("foo", "bar")) + checkFilePathComponents(File("/foo/bar/gav"), File("/"), listOf("foo", "bar", "gav")) + checkFilePathComponents(File("/foo/bar/gav/"), File("/"), listOf("foo", "bar", "gav")) + checkFilePathComponents(File("bar/gav"), File(""), listOf("bar", "gav")) + checkFilePathComponents(File("C:/bar/gav"), File("C:/"), listOf("bar", "gav")) + checkFilePathComponents(File("C:/"), File("C:/"), listOf()) + checkFilePathComponents(File("C:"), File("C:"), listOf()) + if (File.separator == "\\") { // Check only in Windows - checkFileElements(File("\\\\host.ru\\home\\mike"), File("\\\\host.ru\\home"), listOf("mike")) - checkFileElements(File("//host.ru/home/mike"), File("//host.ru/home"), listOf("mike")) + checkFilePathComponents(File("\\\\host.ru\\home\\mike"), File("\\\\host.ru\\home"), listOf("mike")) + checkFilePathComponents(File("//host.ru/home/mike"), File("//host.ru/home"), listOf("mike")) + checkFilePathComponents(File("\\foo\\bar"), File("\\"), listOf("foo", "bar")) + checkFilePathComponents(File("C:\\bar\\gav"), File("C:\\"), listOf("bar", "gav")) + checkFilePathComponents(File("C:\\"), File("C:\\"), listOf()) } - checkFileElements(File(""), null, listOf()) - checkFileElements(File("."), null, listOf(".")) - checkFileElements(File(".."), null, listOf("..")) + checkFilePathComponents(File(""), File(""), listOf()) + checkFilePathComponents(File("."), File(""), listOf(".")) + checkFilePathComponents(File(".."), File(""), listOf("..")) + } + + @test fun fileRoot() { + val rooted = File("/foo/bar") + assertTrue(rooted.isRooted) + assertEquals("/", rooted.root.invariantSeparatorsPath) + + if (File.separator == "\\") { + val diskRooted = File("""C:\foo\bar""") + assertTrue(rooted.isRooted) + assertEquals("""C:\""", diskRooted.rootName) + + val networkRooted = File("""\\network\share\""") + assertTrue(networkRooted.isRooted) + assertEquals("""\\network\share""", networkRooted.rootName) + } + + val relative = File("foo/bar") + assertFalse(relative.isRooted) + assertEquals("", relative.rootName) } @test fun startsWith() { @@ -254,9 +264,10 @@ class FilesTest { assertEquals(File("/foo/bar/baaz"), File("/foo/bak/../bar/gav/../baaz").normalize()) assertEquals(File("../../bar"), File("../foo/../../bar").normalize()) // For Unix C:\windows is not correct so it's not the same as C:/windows - assertEquals(File("C:\\windows").separatorsToSystem(), - File("C:\\home\\..\\documents\\..\\windows").normalize().separatorsToSystem()) - assertEquals(File("C:/windows"), File("C:/home/../documents/../windows").normalize()) + if (File.separator == "\\") { + assertEquals(File("C:\\windows"), File("C:\\home\\..\\documents\\..\\windows").normalize()) + assertEquals(File("C:/windows"), File("C:/home/../documents/../windows").normalize()) + } assertEquals(File("foo"), File("gav/bar/../../foo").normalize()) assertEquals(File("/../foo"), File("/bar/../../foo").normalize()) } @@ -266,11 +277,12 @@ class FilesTest { assertEquals(File("/foo/bar/gav"), File("/foo/bar/").resolve("gav")) assertEquals(File("/gav"), File("/foo/bar").resolve("/gav")) // For Unix C:\path is not correct so it's cannot be automatically converted - assertEquals(File("C:\\Users\\Me\\Documents\\important.doc").separatorsToSystem(), - File("C:\\Users\\Me").resolve("Documents\\important.doc").separatorsToSystem()) - assertEquals(File("C:/Users/Me/Documents/important.doc"), - File("C:/Users/Me").resolve("Documents/important.doc")) - + if (File.separator == "\\") { + assertEquals(File("C:\\Users\\Me\\Documents\\important.doc"), + File("C:\\Users\\Me").resolve("Documents\\important.doc")) + assertEquals(File("C:/Users/Me/Documents/important.doc"), + File("C:/Users/Me").resolve("Documents/important.doc")) + } assertEquals(File(""), File("").resolve("")) assertEquals(File("bar"), File("").resolve("bar")) assertEquals(File("foo/bar"), File("foo").resolve("bar")) @@ -285,10 +297,12 @@ class FilesTest { assertEquals(File("/foo/gav"), File("/foo/bar/").resolveSibling("gav")) assertEquals(File("/gav"), File("/foo/bar").resolveSibling("/gav")) // For Unix C:\path is not correct so it's cannot be automatically converted - assertEquals(File("C:\\Users\\Me\\Documents\\important.doc").separatorsToSystem(), - File("C:\\Users\\Me\\profile.ini").resolveSibling("Documents\\important.doc").separatorsToSystem()) - assertEquals(File("C:/Users/Me/Documents/important.doc"), - File("C:/Users/Me/profile.ini").resolveSibling("Documents/important.doc")) + if (File.separator == "\\") { + assertEquals(File("C:\\Users\\Me\\Documents\\important.doc"), + File("C:\\Users\\Me\\profile.ini").resolveSibling("Documents\\important.doc")) + assertEquals(File("C:/Users/Me/Documents/important.doc"), + File("C:/Users/Me/profile.ini").resolveSibling("Documents/important.doc")) + } assertEquals(File("gav"), File("foo").resolveSibling("gav")) assertEquals(File("../gav"), File("").resolveSibling("gav")) }