Introduce Path.createParentDirectories function #KT-53263
This commit is contained in:
committed by
Space Team
parent
cf10bb8871
commit
d2dc23d8bb
@@ -19,10 +19,10 @@ import java.nio.file.attribute.BasicFileAttributes
|
||||
* Note that if this function throws, partial copying may have taken place.
|
||||
*
|
||||
* Unlike `File.copyRecursively`, if some directories on the way to the [target] are missing, then they won't be created automatically.
|
||||
* You can use the following approach to ensure that required intermediate directories are created:
|
||||
* You can use the [createParentDirectories] function to ensure that required intermediate directories are created:
|
||||
* ```
|
||||
* sourcePath.copyToRecursively(
|
||||
* destinationPath.apply { parent?.createDirectories() },
|
||||
* destinationPath.createParentDirectories(),
|
||||
* followLinks = false
|
||||
* )
|
||||
* ```
|
||||
@@ -93,10 +93,10 @@ public fun Path.copyToRecursively(
|
||||
* Note that if this function throws, partial copying may have taken place.
|
||||
*
|
||||
* Unlike `File.copyRecursively`, if some directories on the way to the [target] are missing, then they won't be created automatically.
|
||||
* You can use the following approach to ensure that required intermediate directories are created:
|
||||
* You can use the [createParentDirectories] function to ensure that required intermediate directories are created:
|
||||
* ```
|
||||
* sourcePath.copyToRecursively(
|
||||
* destinationPath.apply { parent?.createDirectories() },
|
||||
* destinationPath.createParentDirectories(),
|
||||
* followLinks = false
|
||||
* )
|
||||
* ```
|
||||
|
||||
@@ -189,9 +189,9 @@ private object PathRelativizer {
|
||||
* Copies a file or directory located by this path to the given [target] path.
|
||||
*
|
||||
* Unlike `File.copyTo`, if some directories on the way to the [target] are missing, then they won't be created automatically.
|
||||
* You can use the following approach to ensure that required intermediate directories are created:
|
||||
* You can use the [createParentDirectories] function to ensure that required intermediate directories are created:
|
||||
* ```
|
||||
* sourcePath.copyTo(destinationPath.apply { parent?.createDirectories() })
|
||||
* sourcePath.copyTo(destinationPath.createParentDirectories())
|
||||
* ```
|
||||
*
|
||||
* If the [target] path already exists, this function will fail unless [overwrite] argument is set to `true`.
|
||||
@@ -226,9 +226,9 @@ public inline fun Path.copyTo(target: Path, overwrite: Boolean = false): Path {
|
||||
* Copies a file or directory located by this path to the given [target] path.
|
||||
*
|
||||
* Unlike `File.copyTo`, if some directories on the way to the [target] are missing, then they won't be created automatically.
|
||||
* You can use the following approach to ensure that required intermediate directories are created:
|
||||
* You can use the [createParentDirectories] function to ensure that required intermediate directories are created:
|
||||
* ```
|
||||
* sourcePath.copyTo(destinationPath.apply { parent?.createDirectories() })
|
||||
* sourcePath.copyTo(destinationPath.createParentDirectories())
|
||||
* ```
|
||||
*
|
||||
* If the [target] path already exists, this function will fail unless the
|
||||
@@ -500,6 +500,8 @@ public inline fun Path.deleteIfExists() =
|
||||
* when creating the directory.
|
||||
*
|
||||
* @see Files.createDirectory
|
||||
* @see Path.createDirectories
|
||||
* @see Path.createParentDirectories
|
||||
*/
|
||||
@SinceKotlin("1.5")
|
||||
@WasExperimental(ExperimentalPathApi::class)
|
||||
@@ -513,15 +515,20 @@ public inline fun Path.createDirectory(vararg attributes: FileAttribute<*>): Pat
|
||||
*
|
||||
* If the directory already exists, this function does not throw an exception, unlike [Path.createDirectory].
|
||||
*
|
||||
* @return the path of this directory if it already exists or has been created successfully.
|
||||
* The returned path can be converted [Path.toAbsolutePath][to absolute path] if it was relative.
|
||||
*
|
||||
* @param attributes an optional list of file attributes to set atomically when creating the directory.
|
||||
*
|
||||
* @throws FileAlreadyExistsException if there is already a file located by this path
|
||||
* @throws FileAlreadyExistsException if there is already a file located by this path or one of its parent paths
|
||||
* (optional specific exception, some implementations may throw more general [IOException]).
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws UnsupportedOperationException if the [attributes ]array contains an attribute that cannot be set atomically
|
||||
* @throws UnsupportedOperationException if the [attributes] array contains an attribute that cannot be set atomically
|
||||
* when creating the directory.
|
||||
*
|
||||
* @see Files.createDirectories
|
||||
* @see Path.createDirectory
|
||||
* @see Path.createParentDirectories
|
||||
*/
|
||||
@SinceKotlin("1.5")
|
||||
@WasExperimental(ExperimentalPathApi::class)
|
||||
@@ -530,6 +537,33 @@ public inline fun Path.createDirectory(vararg attributes: FileAttribute<*>): Pat
|
||||
public inline fun Path.createDirectories(vararg attributes: FileAttribute<*>): Path =
|
||||
Files.createDirectories(this, *attributes)
|
||||
|
||||
/**
|
||||
* Ensures that all parent directories of this path exist, creating them if required.
|
||||
*
|
||||
* If the parent directory already exists, this function does nothing.
|
||||
*
|
||||
* Note that the [parent][Path.getParent] directory is not always the directory that contains the entry specified by this path.
|
||||
* For example, the parent of the path `x/y/.` is `x/y`, which is logically the same directory,
|
||||
* and the parent of `x/y/..` (which means just `x/`) is also `x/y`.
|
||||
* Use the function [Path.normalize] to eliminate redundant name elements from the path.
|
||||
*
|
||||
* @param attributes an optional list of file attributes to set atomically when creating the missing parent directories.
|
||||
*
|
||||
* @return this path unchanged if all parent directories already exist or have been created successfully.
|
||||
*
|
||||
* @throws FileAlreadyExistsException if there is already a file located by the [parent][Path.getParent] path or one of its parent paths
|
||||
* (optional specific exception, some implementations may throw more general [IOException]).
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws UnsupportedOperationException if the [attributes] array contains an attribute that cannot be set atomically
|
||||
* when creating the directory.
|
||||
*
|
||||
* @see Path.getParent
|
||||
* @see Path.createDirectories
|
||||
*/
|
||||
@SinceKotlin("1.9")
|
||||
@Throws(IOException::class)
|
||||
public fun Path.createParentDirectories(vararg attributes: FileAttribute<*>): Path =
|
||||
this.apply { parent?.createDirectories(*attributes) }
|
||||
|
||||
/**
|
||||
* Moves or renames the file located by this path to the [target] path.
|
||||
|
||||
@@ -59,6 +59,45 @@ class PathExtensionsTest : AbstractPathTest() {
|
||||
assertFailsWith<FileAlreadyExistsException> { file.createFile() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createParentDirectories() {
|
||||
val dir = createTempDirectory().cleanupRecursively()
|
||||
val file = dir / "test-dir" / "sub-dir" / "new-file"
|
||||
val parent = file.parent!!
|
||||
|
||||
assertTrue(file.notExists())
|
||||
assertTrue(parent.notExists())
|
||||
|
||||
val result = file.createParentDirectories()
|
||||
assertTrue(file.notExists())
|
||||
assertTrue(parent.isDirectory())
|
||||
assertEquals(file, result)
|
||||
|
||||
file.createFile()
|
||||
file.createParentDirectories()
|
||||
assertTrue(file.exists())
|
||||
assertTrue(parent.isDirectory())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createParentDirectoriesRelativePath() {
|
||||
run {
|
||||
val path = Path("test_path_without_parent")
|
||||
path.createParentDirectories()
|
||||
assertTrue(path.toAbsolutePath().parent!!.isDirectory())
|
||||
}
|
||||
|
||||
run {
|
||||
val path = Path("build/test_subdirectory/test_path")
|
||||
val parent = path.parent!!
|
||||
assertTrue(parent.notExists())
|
||||
parent.cleanupRecursively()
|
||||
path.createParentDirectories()
|
||||
assertTrue(path.notExists())
|
||||
assertTrue(parent.isDirectory())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createTempFileDefaultDir() {
|
||||
val file1 = createTempFile().cleanup()
|
||||
|
||||
@@ -359,7 +359,7 @@ class PathRecursiveFunctionsTest : AbstractPathTest() {
|
||||
OnErrorResult.SKIP_SUBTREE
|
||||
})
|
||||
|
||||
src.copyToRecursively(dst.apply { parent?.createDirectories() }, followLinks = false)
|
||||
src.copyToRecursively(dst.createParentDirectories(), followLinks = false)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+1
@@ -3361,6 +3361,7 @@ public final class kotlin/io/path/PathsKt {
|
||||
public static final fun copyToRecursively (Ljava/nio/file/Path;Ljava/nio/file/Path;Lkotlin/jvm/functions/Function3;ZZ)Ljava/nio/file/Path;
|
||||
public static synthetic fun copyToRecursively$default (Ljava/nio/file/Path;Ljava/nio/file/Path;Lkotlin/jvm/functions/Function3;ZLkotlin/jvm/functions/Function3;ILjava/lang/Object;)Ljava/nio/file/Path;
|
||||
public static synthetic fun copyToRecursively$default (Ljava/nio/file/Path;Ljava/nio/file/Path;Lkotlin/jvm/functions/Function3;ZZILjava/lang/Object;)Ljava/nio/file/Path;
|
||||
public static final fun createParentDirectories (Ljava/nio/file/Path;[Ljava/nio/file/attribute/FileAttribute;)Ljava/nio/file/Path;
|
||||
public static final fun createTempDirectory (Ljava/nio/file/Path;Ljava/lang/String;[Ljava/nio/file/attribute/FileAttribute;)Ljava/nio/file/Path;
|
||||
public static synthetic fun createTempDirectory$default (Ljava/nio/file/Path;Ljava/lang/String;[Ljava/nio/file/attribute/FileAttribute;ILjava/lang/Object;)Ljava/nio/file/Path;
|
||||
public static final fun createTempFile (Ljava/nio/file/Path;Ljava/lang/String;Ljava/lang/String;[Ljava/nio/file/attribute/FileAttribute;)Ljava/nio/file/Path;
|
||||
|
||||
Reference in New Issue
Block a user