Introduce overwrite parameter to File.copyRecursively.
#KT-8924 Fixed
This commit is contained in:
@@ -218,7 +218,7 @@ public enum class OnErrorAction {
|
||||
private class TerminateException(file: File) : FileSystemException(file) {}
|
||||
|
||||
/**
|
||||
* Copies this file with all its children to the specified destination [dst] path.
|
||||
* Copies this file with all its children to the specified destination [target] path.
|
||||
* If some directories on the way to the destination are missing, then they will be created.
|
||||
*
|
||||
* If any errors occur during the copying, then further actions will depend on the result of the call
|
||||
@@ -231,11 +231,13 @@ private class TerminateException(file: File) : FileSystemException(file) {}
|
||||
* AccessDeniedException - if there was an attempt to open a directory that didn't succeed.
|
||||
* IOException - if some problems occur when copying.
|
||||
*
|
||||
* @param overwrite `true` if it is allowed to overwrite existing destination files and directories.
|
||||
* @return `false` if the copying was terminated, `true` otherwise.
|
||||
*
|
||||
* Note that if this function fails, then partial copying may have taken place.
|
||||
*/
|
||||
public fun File.copyRecursively(dst: File,
|
||||
public fun File.copyRecursively(target: File,
|
||||
overwrite: Boolean = false,
|
||||
onError: (File, IOException) -> OnErrorAction =
|
||||
{ file, exception -> throw exception }
|
||||
): Boolean {
|
||||
@@ -252,16 +254,29 @@ public fun File.copyRecursively(dst: File,
|
||||
return false
|
||||
} else {
|
||||
val relPath = src.toRelativeString(this)
|
||||
val dstFile = File(dst, relPath)
|
||||
val dstFile = File(target, relPath)
|
||||
if (dstFile.exists() && !(src.isDirectory && dstFile.isDirectory)) {
|
||||
if (onError(dstFile, FileAlreadyExistsException(file = src,
|
||||
other = dstFile,
|
||||
reason = "The destination file already exists")) == OnErrorAction.TERMINATE)
|
||||
return false
|
||||
} else if (src.isDirectory) {
|
||||
val stillExists = if (!overwrite) true else {
|
||||
if (dstFile.isDirectory)
|
||||
!dstFile.deleteRecursively()
|
||||
else
|
||||
!dstFile.delete()
|
||||
}
|
||||
|
||||
if (stillExists) {
|
||||
if (onError(dstFile, FileAlreadyExistsException(file = src,
|
||||
other = dstFile,
|
||||
reason = "The destination file already exists")) == OnErrorAction.TERMINATE)
|
||||
return false
|
||||
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if (src.isDirectory) {
|
||||
dstFile.mkdirs()
|
||||
} else {
|
||||
if (src.copyTo(dstFile, true) != src.length()) {
|
||||
if (src.copyTo(dstFile, overwrite) != src.length()) {
|
||||
if (onError(src, IOException("src.length() != dst.length()")) == OnErrorAction.TERMINATE)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -451,20 +451,22 @@ class FilesTest {
|
||||
}
|
||||
}
|
||||
|
||||
fun compareDirectories(src: File, dst: File) {
|
||||
for (file in src.walkTopDown()) {
|
||||
val dstFile = dst.resolve(file.relativeTo(src))
|
||||
assertTrue(dstFile.exists())
|
||||
assertEquals(file.isFile, dstFile.isFile)
|
||||
if (dstFile.isFile) {
|
||||
assertEquals(file.readText(), dstFile.readText())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@test fun copyRecursively() {
|
||||
val src = createTempDir()
|
||||
val dst = createTempDir()
|
||||
dst.delete()
|
||||
fun check() {
|
||||
for (file in src.walkTopDown()) {
|
||||
val dstFile = dst.resolve(file.relativeTo(src))
|
||||
assertTrue(dstFile.exists())
|
||||
if (dstFile.isFile) {
|
||||
assertEquals(file.readText(), dstFile.readText())
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
fun check() = compareDirectories(src, dst)
|
||||
|
||||
try {
|
||||
val subDir1 = createTempDir(prefix = "d1_", directory = src)
|
||||
@@ -531,6 +533,40 @@ class FilesTest {
|
||||
}
|
||||
}
|
||||
|
||||
@test fun copyRecursivelyWithOverwrite() {
|
||||
val src = createTempDir()
|
||||
val dst = createTempDir()
|
||||
fun check() = compareDirectories(src, dst)
|
||||
|
||||
try {
|
||||
val srcFile = src.resolve("test")
|
||||
val dstFile = dst.resolve("test")
|
||||
srcFile.writeText("text1")
|
||||
|
||||
src.copyRecursively(dst)
|
||||
|
||||
srcFile.writeText("text1 modified")
|
||||
src.copyRecursively(dst, overwrite = true)
|
||||
check()
|
||||
|
||||
dstFile.delete()
|
||||
dstFile.mkdir()
|
||||
dstFile.resolve("subFile").writeText("subfile")
|
||||
src.copyRecursively(dst, overwrite = true)
|
||||
check()
|
||||
|
||||
srcFile.delete()
|
||||
srcFile.mkdir()
|
||||
srcFile.resolve("subFile").writeText("text2")
|
||||
src.copyRecursively(dst, overwrite = true)
|
||||
check()
|
||||
}
|
||||
finally {
|
||||
src.deleteRecursively()
|
||||
dst.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
@test fun helpers1() {
|
||||
val str = "123456789\n"
|
||||
System.setIn(str.byteInputStream())
|
||||
|
||||
Reference in New Issue
Block a user