diff --git a/platform/eel/src/com/intellij/platform/eel/fs/EelFileSystemApi.kt b/platform/eel/src/com/intellij/platform/eel/fs/EelFileSystemApi.kt index a248cb0e8936..bdbe4d25c723 100644 --- a/platform/eel/src/com/intellij/platform/eel/fs/EelFileSystemApi.kt +++ b/platform/eel/src/com/intellij/platform/eel/fs/EelFileSystemApi.kt @@ -261,12 +261,22 @@ interface EelFileSystemApi { class Other(where: EelPath.Absolute, additionalMessage: String) : CopyException(where, additionalMessage), EelFsError.Other } + enum class ReplaceExistingDuringMove { + REPLACE_EVERYTHING, + + /** For compatibility with Java NIO. */ + DO_NOT_REPLACE_DIRECTORIES, + + DO_NOT_REPLACE, + } + @Throws(MoveException::class) - suspend fun move(source: EelPath.Absolute, target: EelPath.Absolute, replaceExisting: Boolean, followLinks: Boolean) + suspend fun move(source: EelPath.Absolute, target: EelPath.Absolute, replaceExisting: ReplaceExistingDuringMove, followLinks: Boolean) sealed class MoveException(where: EelPath.Absolute, additionalMessage: String) : EelFsIOException(where, additionalMessage) { class SourceDoesNotExist(where: EelPath.Absolute) : MoveException(where, "Source does not exist"), EelFsError.DoesNotExist class TargetAlreadyExists(where: EelPath.Absolute) : MoveException(where, "Target already exists"), EelFsError.AlreadyExists + class TargetIsDirectory(where: EelPath.Absolute) : MoveException(where, "Target already exists and it is a directory"), EelFsError.AlreadyExists class PermissionDenied(where: EelPath.Absolute) : MoveException(where, "Permission denied"), EelFsError.PermissionDenied class NameTooLong(where: EelPath.Absolute) : MoveException(where, "Name too long"), EelFsError.NameTooLong class ReadOnlyFileSystem(where: EelPath.Absolute) : MoveException(where, "File system is read-only"), EelFsError.ReadOnlyFileSystem diff --git a/platform/ijent/impl/src/com/intellij/platform/ijent/community/impl/IjentFailSafeFileSystemPosixApi.kt b/platform/ijent/impl/src/com/intellij/platform/ijent/community/impl/IjentFailSafeFileSystemPosixApi.kt index e80532c55eac..697b685c3ac1 100644 --- a/platform/ijent/impl/src/com/intellij/platform/ijent/community/impl/IjentFailSafeFileSystemPosixApi.kt +++ b/platform/ijent/impl/src/com/intellij/platform/ijent/community/impl/IjentFailSafeFileSystemPosixApi.kt @@ -187,7 +187,12 @@ private class IjentFailSafeFileSystemPosixApiImpl( } } - override suspend fun move(source: EelPath.Absolute, target: EelPath.Absolute, replaceExisting: Boolean, followLinks: Boolean) { + override suspend fun move( + source: EelPath.Absolute, + target: EelPath.Absolute, + replaceExisting: EelFileSystemApi.ReplaceExistingDuringMove, + followLinks: Boolean, + ) { holder.withDelegateRetrying { move(source, target, replaceExisting, followLinks) } diff --git a/platform/ijent/impl/src/com/intellij/platform/ijent/community/impl/nio/IjentNioFileSystemProvider.kt b/platform/ijent/impl/src/com/intellij/platform/ijent/community/impl/nio/IjentNioFileSystemProvider.kt index cef650ce8d04..c50d9ed74cb5 100644 --- a/platform/ijent/impl/src/com/intellij/platform/ijent/community/impl/nio/IjentNioFileSystemProvider.kt +++ b/platform/ijent/impl/src/com/intellij/platform/ijent/community/impl/nio/IjentNioFileSystemProvider.kt @@ -5,6 +5,7 @@ import com.intellij.openapi.diagnostic.thisLogger import com.intellij.platform.core.nio.fs.BasicFileAttributesHolder2.FetchAttributesFilter import com.intellij.platform.eel.fs.* import com.intellij.platform.eel.fs.EelFileInfo.Type.* +import com.intellij.platform.eel.fs.EelFileSystemApi.ReplaceExistingDuringMove.* import com.intellij.platform.eel.fs.EelFileSystemPosixApi.CreateDirectoryException import com.intellij.platform.eel.fs.EelFileSystemPosixApi.CreateSymbolicLinkException import com.intellij.platform.eel.fs.EelPosixFileInfo.Type.Symlink @@ -328,7 +329,14 @@ class IjentNioFileSystemProvider : FileSystemProvider() { source.nioFs.ijentFs.move( sourcePath, targetPath, - replaceExisting = true, + replaceExisting = run { + // This code may change when implementing Windows support. + when { + StandardCopyOption.ATOMIC_MOVE in options -> DO_NOT_REPLACE_DIRECTORIES + StandardCopyOption.REPLACE_EXISTING in options -> REPLACE_EVERYTHING + else -> DO_NOT_REPLACE + } + }, // In NIO, `move` does not follow links. This behavior is not influenced by the presense of NOFOLLOW_LINKS in CopyOptions // See java.nio.file.CopyMoveHelper.convertMoveToCopyOptions followLinks = false)