mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-03-22 15:19:59 +07:00
[ijent] IJPL-234507 implement eel filesystem todo for windows
GitOrigin-RevId: 0f3f6dcfd56a49956006f2a3ac645f957b7791bc
This commit is contained in:
committed by
intellij-monorepo-bot
parent
c19af13f06
commit
2239489cfd
@@ -13,6 +13,7 @@ import com.intellij.platform.eel.path.EelPath
|
||||
import com.intellij.platform.eel.path.EelPathException
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.pathString
|
||||
|
||||
/**
|
||||
* Converts [EelPath], which is likely a path from a remote machine, to a [Path] for the local machine.
|
||||
@@ -105,7 +106,11 @@ fun Path.asEelPath(descriptor: EelDescriptor): EelPath {
|
||||
}
|
||||
}
|
||||
is EelPathBoundDescriptor -> {
|
||||
TODO() // on Windows, we need additional logic to guess the new root
|
||||
val root = descriptor.rootPath
|
||||
val relative = root.relativize(this)
|
||||
return relative.drop(1).fold(EelPath.parse(relative.first().pathString, descriptor)) { path, part ->
|
||||
part.toString().takeIf { it.isNotEmpty() }?.let { path.getChild(it) } ?: path
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
throw NoSuchElementException("Cannot find a root for $this")
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.platform.eel.fs.EelFileSystemApi.WalkDirectoryOptions.WalkDi
|
||||
import com.intellij.platform.eel.fs.EelFileSystemApi.WalkDirectoryOptions.WalkDirectoryTraversalOrder
|
||||
import com.intellij.platform.eel.fs.EelPosixFileInfo
|
||||
import com.intellij.platform.eel.fs.EelPosixFileInfoImpl
|
||||
import com.intellij.platform.eel.fs.EelWindowsFileInfo
|
||||
import com.intellij.platform.eel.fs.StreamingWriteResult
|
||||
import com.intellij.platform.eel.fs.WalkDirectoryEntry
|
||||
import com.intellij.platform.eel.fs.WalkDirectoryEntryPosix
|
||||
@@ -1690,6 +1691,21 @@ object EelPathUtils {
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* returns one of [modes] which is not satisfied, or `null` if all modes are satisfied
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
fun checkAccess(fileInfo: EelWindowsFileInfo, vararg modes: AccessMode): AccessMode? {
|
||||
// TODO check other permissions
|
||||
if (AccessMode.WRITE in modes) {
|
||||
val canWrite = !fileInfo.permissions.isReadOnly
|
||||
if (!canWrite) {
|
||||
return AccessMode.WRITE
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun getCaseSensitivity(directoryType: EelFileInfo.Type.Directory): FileAttributes.CaseSensitivity {
|
||||
return when (directoryType.sensitivity) {
|
||||
EelFileInfo.CaseSensitivity.SENSITIVE -> FileAttributes.CaseSensitivity.SENSITIVE
|
||||
|
||||
@@ -4,7 +4,7 @@ package com.intellij.platform.eel.tcp
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.platform.eel.annotations.MultiRoutingFileSystemPath
|
||||
import com.intellij.platform.eel.provider.MultiRoutingFileSystemBackend
|
||||
import com.intellij.platform.ijent.community.impl.IjentFailSafeFileSystemPosixApi
|
||||
import com.intellij.platform.ijent.community.impl.ijentFailSafeFileSystemApi
|
||||
import com.intellij.platform.ijent.community.impl.nio.IjentNioFileSystemProvider
|
||||
import com.intellij.platform.ijent.community.impl.nio.fs.IjentEphemeralRootAwareFileSystemProvider
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -40,7 +40,7 @@ class TcpEelMrfsBackend(private val scope: CoroutineScope) : MultiRoutingFileSys
|
||||
val ijentDefaultProvider = IjentNioFileSystemProvider.getInstance()
|
||||
|
||||
try {
|
||||
val ijentFs = IjentFailSafeFileSystemPosixApi(scope, descriptor, checkIsIjentInitialized = null)
|
||||
val ijentFs = ijentFailSafeFileSystemApi(scope, descriptor, checkIsIjentInitialized = null)
|
||||
ijentDefaultProvider.newFileSystem(ijentUri, IjentNioFileSystemProvider.newFileSystemMap(ijentFs))
|
||||
}
|
||||
catch (_: FileSystemAlreadyExistsException) {
|
||||
@@ -51,7 +51,8 @@ class TcpEelMrfsBackend(private val scope: CoroutineScope) : MultiRoutingFileSys
|
||||
root = localPath,
|
||||
ijentFsProvider = ijentDefaultProvider,
|
||||
originalFsProvider = localFS.provider(),
|
||||
useRootDirectoriesFromOriginalFs = false
|
||||
useRootDirectoriesFromOriginalFs = false,
|
||||
eelDescriptor = descriptor,
|
||||
).getFileSystem(ijentUri)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.platform.eel.fs
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
@ApiStatus.Internal
|
||||
data class EelWindowsFileInfoImpl(
|
||||
override val type: EelFileInfo.Type,
|
||||
override val permissions: EelWindowsFileInfo.Permissions,
|
||||
override val creationTime: ZonedDateTime?,
|
||||
override val lastModifiedTime: ZonedDateTime?,
|
||||
override val lastAccessTime: ZonedDateTime?,
|
||||
) : EelWindowsFileInfo {
|
||||
data class Permissions(
|
||||
override val isReadOnly: Boolean,
|
||||
override val isHidden: Boolean,
|
||||
override val isArchive: Boolean,
|
||||
override val isSystem: Boolean
|
||||
) : EelWindowsFileInfo.Permissions
|
||||
}
|
||||
@@ -4,8 +4,11 @@ package com.intellij.platform.ijent.community.impl
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.eel.EelOsFamily
|
||||
import com.intellij.platform.eel.EelResult
|
||||
import com.intellij.platform.eel.EelUserPosixInfo
|
||||
import com.intellij.platform.eel.EelUserWindowsInfo
|
||||
import com.intellij.platform.eel.fs.*
|
||||
import com.intellij.platform.eel.fs.EelFileSystemApi
|
||||
import com.intellij.platform.eel.fs.EelFileSystemPosixApi
|
||||
import com.intellij.platform.eel.fs.EelOpenedFile
|
||||
@@ -18,8 +21,10 @@ import com.intellij.platform.eel.provider.toEelApi
|
||||
import com.intellij.platform.ijent.IjentApi
|
||||
import com.intellij.platform.ijent.IjentPosixApi
|
||||
import com.intellij.platform.ijent.IjentUnavailableException
|
||||
import com.intellij.platform.ijent.IjentWindowsApi
|
||||
import com.intellij.platform.ijent.fs.IjentFileSystemApi
|
||||
import com.intellij.platform.ijent.fs.IjentFileSystemPosixApi
|
||||
import com.intellij.platform.ijent.fs.IjentFileSystemWindowsApi
|
||||
import com.intellij.util.ui.EDT
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.CoroutineStart
|
||||
@@ -51,14 +56,21 @@ import java.util.concurrent.atomic.AtomicReference
|
||||
* twice if a networking issue happens during the first attempt of writing.
|
||||
* In order to solve this problem, IjentFileSystemApi MUST guarantee idempotency of every call.
|
||||
*/
|
||||
@Suppress("FunctionName")
|
||||
fun IjentFailSafeFileSystemPosixApi(
|
||||
fun ijentFailSafeFileSystemApi(
|
||||
coroutineScope: CoroutineScope,
|
||||
descriptor: EelDescriptor,
|
||||
checkIsIjentInitialized: (() -> Boolean)?,
|
||||
): IjentFileSystemApi {
|
||||
val holder = DelegateHolder<IjentPosixApi, IjentFileSystemPosixApi>(coroutineScope, descriptor, checkIsIjentInitialized)
|
||||
return IjentFailSafeFileSystemPosixApiImpl(holder, descriptor)
|
||||
return when (descriptor.osFamily) {
|
||||
EelOsFamily.Posix -> {
|
||||
val holder = DelegateHolder<IjentPosixApi, IjentFileSystemPosixApi>(coroutineScope, descriptor, checkIsIjentInitialized)
|
||||
IjentFailSafeFileSystemPosixApiImpl(holder, descriptor)
|
||||
}
|
||||
EelOsFamily.Windows -> {
|
||||
val holder = DelegateHolder<IjentWindowsApi, IjentFileSystemWindowsApi>(coroutineScope, descriptor, checkIsIjentInitialized)
|
||||
IjentFailSafeFileSystemWindowsApiImpl(holder, descriptor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class DelegateHolder<I : IjentApi, F : IjentFileSystemApi>(
|
||||
@@ -320,4 +332,162 @@ private class IjentFailSafeFileSystemPosixApiImpl(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unfortunately, [IjentFileSystemApi] is a sealed interface,
|
||||
* so implementing it's a full copy-paste of [ijentFailSafeFileSystemApi]
|
||||
*/
|
||||
private class IjentFailSafeFileSystemWindowsApiImpl(
|
||||
private val holder: DelegateHolder<IjentWindowsApi, IjentFileSystemWindowsApi>,
|
||||
override val descriptor: EelDescriptor
|
||||
) : IjentFileSystemWindowsApi {
|
||||
// TODO Make user suspendable again?
|
||||
override val user: EelUserWindowsInfo by lazy {
|
||||
runBlocking {
|
||||
holder.withDelegateRetrying { user }
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun walkDirectory(options: EelFileSystemApi.WalkDirectoryOptions): Flow<WalkDirectoryEntryResult> = flow {
|
||||
val seen = HashSet<EelPath>()
|
||||
holder.withDelegateRetrying {
|
||||
walkDirectory(options).collect { entry ->
|
||||
val path = when (entry) {
|
||||
is WalkDirectoryEntryResult.Error -> entry.error.where
|
||||
is WalkDirectoryEntryResult.Ok -> entry.value.path
|
||||
}
|
||||
if (seen.add(path)) {
|
||||
emit(entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun streamingWrite(chunks: Flow<ByteBuffer>, targetFileOpenOptions: EelFileSystemApi.WriteOptions): StreamingWriteResult =
|
||||
holder.withDelegateRetrying {
|
||||
streamingWrite(chunks, targetFileOpenOptions)
|
||||
}
|
||||
override suspend fun streamingRead(path: EelPath): Flow<StreamingReadResult> =
|
||||
holder.withDelegateRetrying {
|
||||
streamingRead(path)
|
||||
}
|
||||
|
||||
override suspend fun listDirectory(
|
||||
path: EelPath,
|
||||
): EelResult<Collection<String>, EelFileSystemApi.ListDirectoryError> =
|
||||
holder.withDelegateRetrying {
|
||||
listDirectory(path)
|
||||
}
|
||||
|
||||
override suspend fun getRootDirectories(): Collection<EelPath> {
|
||||
return holder.withDelegateRetrying {
|
||||
getRootDirectories()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun listDirectoryWithAttrs(
|
||||
path: EelPath,
|
||||
symlinkPolicy: EelFileSystemApi.SymlinkPolicy,
|
||||
): EelResult<Collection<Pair<String, EelWindowsFileInfo>>, EelFileSystemApi.ListDirectoryError> {
|
||||
return holder.withDelegateRetrying {
|
||||
listDirectoryWithAttrs(path, symlinkPolicy)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun canonicalize(
|
||||
path: EelPath,
|
||||
): EelResult<EelPath, EelFileSystemApi.CanonicalizeError> =
|
||||
holder.withDelegateRetrying {
|
||||
canonicalize(path)
|
||||
}
|
||||
|
||||
override suspend fun stat(
|
||||
path: EelPath,
|
||||
symlinkPolicy: EelFileSystemApi.SymlinkPolicy,
|
||||
): EelResult<EelWindowsFileInfo, EelFileSystemApi.StatError> =
|
||||
holder.withDelegateRetrying {
|
||||
stat(path, symlinkPolicy)
|
||||
}
|
||||
|
||||
override suspend fun sameFile(
|
||||
source: EelPath,
|
||||
target: EelPath,
|
||||
): EelResult<Boolean, EelFileSystemApi.SameFileError> =
|
||||
holder.withDelegateRetrying {
|
||||
sameFile(source, target)
|
||||
}
|
||||
|
||||
override suspend fun openForReading(
|
||||
args: EelFileSystemApi.OpenForReadingArgs,
|
||||
): EelResult<EelOpenedFile.Reader, EelFileSystemApi.FileReaderError> =
|
||||
holder.withDelegateRetrying {
|
||||
openForReading(args)
|
||||
}
|
||||
|
||||
override suspend fun readFile(
|
||||
args: EelFileSystemApi.ReadFileArgs,
|
||||
): EelResult<EelFileSystemApi.ReadFileResult, EelFileSystemApi.FileReaderError> =
|
||||
holder.withDelegateRetrying {
|
||||
readFile(args)
|
||||
}
|
||||
|
||||
override suspend fun openForWriting(
|
||||
options: EelFileSystemApi.WriteOptions,
|
||||
): EelResult<EelOpenedFile.Writer, EelFileSystemApi.FileWriterError> =
|
||||
holder.withDelegateRetrying {
|
||||
openForWriting(options)
|
||||
}
|
||||
|
||||
override suspend fun openForReadingAndWriting(
|
||||
options: EelFileSystemApi.WriteOptions,
|
||||
): EelResult<EelOpenedFile.ReaderWriter, EelFileSystemApi.FileWriterError> =
|
||||
holder.withDelegateRetrying {
|
||||
openForReadingAndWriting(options)
|
||||
}
|
||||
|
||||
override suspend fun delete(path: EelPath, removeContent: Boolean): EelResult<Unit, EelFileSystemApi.DeleteError> =
|
||||
holder.withDelegateRetrying {
|
||||
delete(path, removeContent)
|
||||
}
|
||||
|
||||
override suspend fun copy(options: EelFileSystemApi.CopyOptions): EelResult<Unit, EelFileSystemApi.CopyError> =
|
||||
holder.withDelegateRetrying {
|
||||
copy(options)
|
||||
}
|
||||
|
||||
override suspend fun move(
|
||||
source: EelPath,
|
||||
target: EelPath,
|
||||
replaceExisting: EelFileSystemApi.ReplaceExistingDuringMove,
|
||||
followLinks: Boolean,
|
||||
): EelResult<Unit, EelFileSystemApi.MoveError> =
|
||||
holder.withDelegateRetrying {
|
||||
move(source, target, replaceExisting, followLinks)
|
||||
}
|
||||
|
||||
override suspend fun changeAttributes(
|
||||
path: EelPath,
|
||||
options: EelFileSystemApi.ChangeAttributesOptions,
|
||||
): EelResult<Unit, EelFileSystemApi.ChangeAttributesError> =
|
||||
holder.withDelegateRetrying {
|
||||
changeAttributes(path, options)
|
||||
}
|
||||
|
||||
override suspend fun getDiskInfo(path: EelPath): EelResult<EelFileSystemApi.DiskInfo, EelFileSystemApi.DiskInfoError> {
|
||||
return holder.withDelegateRetrying {
|
||||
getDiskInfo(path)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun createTemporaryDirectory(
|
||||
options: EelFileSystemApi.CreateTemporaryEntryOptions,
|
||||
): EelResult<EelPath, EelFileSystemApi.CreateTemporaryEntryError> =
|
||||
holder.withDelegateRetrying {
|
||||
createTemporaryDirectory(options)
|
||||
}
|
||||
|
||||
override suspend fun createTemporaryFile(options: EelFileSystemApi.CreateTemporaryEntryOptions): EelResult<EelPath, EelFileSystemApi.CreateTemporaryEntryError> = holder.withDelegateRetrying {
|
||||
createTemporaryFile(options)
|
||||
}
|
||||
}
|
||||
|
||||
private val LOG = logger<IjentFailSafeFileSystemPosixApiImpl>()
|
||||
@@ -5,6 +5,7 @@ import com.intellij.platform.eel.fs.EelFileSystemApi
|
||||
import com.intellij.platform.eel.getOrThrow
|
||||
import com.intellij.platform.eel.path.EelPath
|
||||
import com.intellij.platform.ijent.fs.IjentFileSystemApi
|
||||
import com.intellij.platform.ijent.fs.IjentFileSystemPosixApi
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.attribute.BasicFileAttributeView
|
||||
import java.nio.file.attribute.BasicFileAttributes
|
||||
@@ -38,7 +39,7 @@ internal open class IjentNioBasicFileAttributeView(val api: IjentFileSystemApi,
|
||||
}
|
||||
}
|
||||
|
||||
internal class IjentNioPosixFileAttributeView(api: IjentFileSystemApi, path: EelPath, nioPath: IjentNioPath) : IjentNioBasicFileAttributeView(api, path, nioPath), PosixFileAttributeView {
|
||||
internal class IjentNioPosixFileAttributeView(api: IjentFileSystemPosixApi, path: EelPath, nioPath: IjentNioPath) : IjentNioBasicFileAttributeView(api, path, nioPath), PosixFileAttributeView {
|
||||
override fun name(): String? {
|
||||
return "posix"
|
||||
}
|
||||
|
||||
@@ -54,10 +54,13 @@ import java.nio.file.StandardOpenOption.DELETE_ON_CLOSE
|
||||
import java.nio.file.StandardOpenOption.READ
|
||||
import java.nio.file.StandardOpenOption.TRUNCATE_EXISTING
|
||||
import java.nio.file.StandardOpenOption.WRITE
|
||||
import java.nio.file.attribute.AclFileAttributeView
|
||||
import java.nio.file.attribute.BasicFileAttributeView
|
||||
import java.nio.file.attribute.BasicFileAttributes
|
||||
import java.nio.file.attribute.DosFileAttributeView
|
||||
import java.nio.file.attribute.FileAttribute
|
||||
import java.nio.file.attribute.FileAttributeView
|
||||
import java.nio.file.attribute.FileOwnerAttributeView
|
||||
import java.nio.file.attribute.FileTime
|
||||
import java.nio.file.attribute.PosixFileAttributeView
|
||||
import java.nio.file.attribute.PosixFileAttributes
|
||||
@@ -250,7 +253,7 @@ class IjentNioFileSystemProvider : FileSystemProvider() {
|
||||
val childIjentPath = dir.eelPath.getChild(childName)
|
||||
val childAttrs = when (childStat) {
|
||||
is EelPosixFileInfo -> IjentNioPosixFileAttributes(childStat)
|
||||
is EelWindowsFileInfo -> TODO()
|
||||
is EelWindowsFileInfo -> IjentNioBasicFileAttributes(childStat)
|
||||
}
|
||||
AbsoluteIjentNioPath(childIjentPath, nioFs, childAttrs)
|
||||
}
|
||||
@@ -392,29 +395,62 @@ class IjentNioFileSystemProvider : FileSystemProvider() {
|
||||
EelFsResultImpl.PermissionDenied(path.eelPath, "Permission denied: ${error.name}").throwFileSystemException()
|
||||
}
|
||||
}
|
||||
is IjentFileSystemWindowsApi -> TODO()
|
||||
is IjentFileSystemWindowsApi -> {
|
||||
val fileInfo = ijentFs
|
||||
// According to the Javadoc, this method must follow symlinks.
|
||||
.stat(path.eelPath)
|
||||
.resolveAndFollow()
|
||||
.getOrThrowFileSystemException()
|
||||
|
||||
val error = EelPathUtils.checkAccess(fileInfo, *modes)
|
||||
if (error != null) {
|
||||
EelFsResultImpl.PermissionDenied(path.eelPath, "Permission denied: ${error.name}").throwFileSystemException()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun <V : FileAttributeView?> getFileAttributeView(path: Path, type: Class<V>?, vararg options: LinkOption): V? {
|
||||
// TODO why link options are ignored?
|
||||
ensureAbsoluteIjentNioPath(path)
|
||||
if (type == BasicFileAttributeView::class.java) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return IjentNioBasicFileAttributeView(path.nioFs.ijentFs, path.eelPath, path) as V
|
||||
}
|
||||
val nioFs = ensureIjentNioPath(path).nioFs
|
||||
when (nioFs.ijentFs) {
|
||||
is IjentFileSystemPosixApi -> {
|
||||
if (type == PosixFileAttributeView::class.java) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return IjentNioPosixFileAttributeView(path.nioFs.ijentFs, path.eelPath, path) as V
|
||||
}
|
||||
else {
|
||||
return null
|
||||
}
|
||||
val ijentFs = path.nioFs.ijentFs
|
||||
when (type) {
|
||||
BasicFileAttributeView::class.java -> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return IjentNioBasicFileAttributeView(path.nioFs.ijentFs, path.eelPath, path) as V
|
||||
}
|
||||
is IjentFileSystemWindowsApi -> TODO()
|
||||
PosixFileAttributeView::class.java -> {
|
||||
if (ijentFs is IjentFileSystemPosixApi) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return IjentNioPosixFileAttributeView(ijentFs, path.eelPath, path) as V
|
||||
}
|
||||
else return null
|
||||
}
|
||||
AclFileAttributeView::class.java -> {
|
||||
// TODO
|
||||
return null
|
||||
}
|
||||
DosFileAttributeView::class.java -> {
|
||||
// TODO
|
||||
return null
|
||||
}
|
||||
FileOwnerAttributeView::class.java -> {
|
||||
// TODO
|
||||
return null
|
||||
}
|
||||
else -> {
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Array<out LinkOption>.toLinkPolicy(): EelFileSystemApi.SymlinkPolicy {
|
||||
return if (LinkOption.NOFOLLOW_LINKS in this) {
|
||||
EelFileSystemApi.SymlinkPolicy.DO_NOT_RESOLVE
|
||||
}
|
||||
else {
|
||||
EelFileSystemApi.SymlinkPolicy.RESOLVE_AND_FOLLOW
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,20 +458,23 @@ class IjentNioFileSystemProvider : FileSystemProvider() {
|
||||
override fun <A : BasicFileAttributes> readAttributes(path: Path, type: Class<A>, vararg options: LinkOption): A {
|
||||
val fs = ensureAbsoluteIjentNioPath(path).nioFs
|
||||
|
||||
val linkPolicy = if (LinkOption.NOFOLLOW_LINKS in options) {
|
||||
EelFileSystemApi.SymlinkPolicy.DO_NOT_RESOLVE
|
||||
}
|
||||
else {
|
||||
EelFileSystemApi.SymlinkPolicy.RESOLVE_AND_FOLLOW
|
||||
}
|
||||
val linkPolicy = options.toLinkPolicy()
|
||||
|
||||
val result = when (val ijentFs = fs.ijentFs) {
|
||||
is IjentFileSystemPosixApi ->
|
||||
IjentNioPosixFileAttributes(fsBlocking {
|
||||
val ijentFs = fs.ijentFs
|
||||
val result = when (ijentFs) {
|
||||
is IjentFileSystemPosixApi -> {
|
||||
val fileInfo = fsBlocking {
|
||||
ijentFs.stat(path.eelPath).symlinkPolicy(linkPolicy).getOrThrowFileSystemException()
|
||||
})
|
||||
|
||||
is IjentFileSystemWindowsApi -> TODO()
|
||||
}
|
||||
IjentNioPosixFileAttributes(fileInfo)
|
||||
}
|
||||
is IjentFileSystemWindowsApi -> {
|
||||
// TODO DosFileAttributes
|
||||
val fileInfo = fsBlocking {
|
||||
ijentFs.stat(path.eelPath).symlinkPolicy(linkPolicy).getOrThrowFileSystemException()
|
||||
}
|
||||
IjentNioBasicFileAttributes(fileInfo)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
||||
@@ -8,6 +8,8 @@ import com.intellij.platform.core.nio.fs.DelegatingFileSystem
|
||||
import com.intellij.platform.core.nio.fs.DelegatingFileSystemProvider
|
||||
import com.intellij.platform.core.nio.fs.MultiRoutingFsPath
|
||||
import com.intellij.platform.core.nio.fs.RoutingAwareFileSystemProvider
|
||||
import com.intellij.platform.eel.EelDescriptor
|
||||
import com.intellij.platform.eel.EelOsFamily
|
||||
import com.intellij.platform.eel.provider.getEelDescriptor
|
||||
import com.intellij.platform.eel.provider.utils.EelPathUtils
|
||||
import com.intellij.platform.ijent.community.impl.nio.IjentNioPath
|
||||
@@ -183,7 +185,7 @@ class IjentEphemeralRootAwarePath(
|
||||
|
||||
override fun toString(): String {
|
||||
return if (isAbsolute) {
|
||||
rootPath.resolve(originalPath.pathString.removePrefix("/")).toString()
|
||||
rootPath.resolve(originalPath.pathString.removePrefix("/").replace("\\", fileSystem.separator)).toString()
|
||||
}
|
||||
else {
|
||||
originalPath.toString()
|
||||
@@ -216,6 +218,7 @@ class IjentEphemeralRootAwareFileSystemProvider(
|
||||
private val ijentFsProvider: FileSystemProvider,
|
||||
private val originalFsProvider: FileSystemProvider,
|
||||
private val useRootDirectoriesFromOriginalFs: Boolean,
|
||||
private val eelDescriptor: EelDescriptor
|
||||
) : DelegatingFileSystemProvider<IjentEphemeralRootAwareFileSystemProvider, IjentEphemeralRootAwareFileSystem>(), RoutingAwareFileSystemProvider {
|
||||
private val originalFs = originalFsProvider.getFileSystem(URI("file:/"))
|
||||
|
||||
@@ -224,7 +227,8 @@ class IjentEphemeralRootAwareFileSystemProvider(
|
||||
rootAwareFileSystemProvider = this,
|
||||
ijentFs = delegateFs,
|
||||
originalFs = originalFs,
|
||||
useRootDirectoriesFromOriginalFs = useRootDirectoriesFromOriginalFs
|
||||
useRootDirectoriesFromOriginalFs = useRootDirectoriesFromOriginalFs,
|
||||
eelDescriptor = eelDescriptor
|
||||
)
|
||||
}
|
||||
|
||||
@@ -327,6 +331,7 @@ class IjentEphemeralRootAwareFileSystem(
|
||||
private val ijentFs: FileSystem,
|
||||
private val originalFs: FileSystem,
|
||||
private val useRootDirectoriesFromOriginalFs: Boolean,
|
||||
private val eelDescriptor: EelDescriptor
|
||||
) : DelegatingFileSystem<IjentEphemeralRootAwareFileSystemProvider>() {
|
||||
private val root: Path = rootAwareFileSystemProvider.root
|
||||
private val invariantSeparatorRootPathString = root.invariantSeparatorsPathString.removeSuffix("/")
|
||||
@@ -346,7 +351,8 @@ class IjentEphemeralRootAwareFileSystem(
|
||||
override fun getPath(first: String, vararg more: String): Path {
|
||||
if (isPathUnderRoot(first)) {
|
||||
val parts = more.flatMap { it.split(root.fileSystem.separator) }.filter(String::isNotEmpty).toTypedArray()
|
||||
val ijentNioPath = ijentFs.getPath(relativizeToRoot(first), *parts) as IjentNioPath
|
||||
val relativized = relativizeToRoot(first, parts, eelDescriptor)
|
||||
val ijentNioPath = ijentFs.getPath(relativized.first(), *relativized.drop(1).toTypedArray()) as IjentNioPath
|
||||
return IjentEphemeralRootAwarePath(this,root, ijentNioPath)
|
||||
}
|
||||
|
||||
@@ -383,8 +389,18 @@ class IjentEphemeralRootAwareFileSystem(
|
||||
return toSystemIndependentName(path).startsWith(invariantSeparatorRootPathString)
|
||||
}
|
||||
|
||||
// TODO: improve this function when we will support ijent on windows
|
||||
private fun relativizeToRoot(path: String): String {
|
||||
return (toSystemIndependentName(path).removePrefix(invariantSeparatorRootPathString)).nullize() ?: "/"
|
||||
private fun relativizeToRoot(path: String, parts: Array<String>, eelDescriptor: EelDescriptor): Array<String> {
|
||||
val relativePath = (toSystemIndependentName(path).removePrefix(invariantSeparatorRootPathString)).nullize()
|
||||
return when (eelDescriptor.osFamily) {
|
||||
EelOsFamily.Posix -> {
|
||||
arrayOf(relativePath ?: "/", *parts)
|
||||
}
|
||||
EelOsFamily.Windows -> {
|
||||
if (relativePath != null) {
|
||||
arrayOf(relativePath.removePrefix("/"), *parts)
|
||||
}
|
||||
else parts
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,8 @@ fun CoroutineScope.registerIjentNioFs(
|
||||
root = nioRoot,
|
||||
ijentFsProvider = IjentNioFileSystemProvider.getInstance(),
|
||||
originalFsProvider = localFS.provider(),
|
||||
useRootDirectoriesFromOriginalFs = false
|
||||
useRootDirectoriesFromOriginalFs = false,
|
||||
eelDescriptor = ijentFs.ijentFs.descriptor
|
||||
).let { wrapFileSystemProvider?.invoke(it) ?: it }.getFileSystem(uri)
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import com.intellij.platform.eel.annotations.MultiRoutingFileSystemPath
|
||||
import com.intellij.platform.eel.provider.EelProvider
|
||||
import com.intellij.platform.eel.provider.MultiRoutingFileSystemBackend
|
||||
import com.intellij.platform.ide.impl.wsl.ijent.nio.IjentWslNioFileSystemProvider
|
||||
import com.intellij.platform.ijent.community.impl.IjentFailSafeFileSystemPosixApi
|
||||
import com.intellij.platform.ijent.community.impl.ijentFailSafeFileSystemApi
|
||||
import com.intellij.platform.ijent.community.impl.nio.IjentNioFileSystemProvider
|
||||
import com.intellij.platform.ijent.community.impl.nio.fs.IjentEphemeralRootAwareFileSystemProvider
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
@@ -83,9 +83,9 @@ class EelWslMrfsBackend(private val coroutineScope: CoroutineScope) : MultiRouti
|
||||
|
||||
val ijentFsProvider = IjentNioFileSystemProvider.getInstance()
|
||||
|
||||
val descriptor = WslEelDescriptor(WSLDistribution(distributionId), wslRoot)
|
||||
try {
|
||||
val descriptor = WslEelDescriptor(WSLDistribution(distributionId), wslRoot)
|
||||
val ijentFs = IjentFailSafeFileSystemPosixApi(coroutineScope, descriptor, checkIsIjentInitialized = {
|
||||
val ijentFs = ijentFailSafeFileSystemApi(coroutineScope, descriptor, checkIsIjentInitialized = {
|
||||
WslIjentManager.getInstance().isIjentInitialized(descriptor)
|
||||
})
|
||||
val fs = ijentFsProvider.newFileSystem(ijentUri, IjentNioFileSystemProvider.newFileSystemMap(ijentFs))
|
||||
@@ -116,6 +116,7 @@ class EelWslMrfsBackend(private val coroutineScope: CoroutineScope) : MultiRouti
|
||||
// This function avoids fetching root directories directly from IJent.
|
||||
// This way, various UI file trees don't start all WSL containers during loading the file system root.
|
||||
useRootDirectoriesFromOriginalFs = true,
|
||||
eelDescriptor = descriptor
|
||||
).getFileSystem(ijentUri)
|
||||
}
|
||||
else {
|
||||
|
||||
Reference in New Issue
Block a user