[ijent] IJPL-232220 additional fixes for path manipulation

GitOrigin-RevId: b8104ca8253150da2e155e960f223549d4c8e608
This commit is contained in:
Mihail Buryakov
2026-02-10 12:09:15 +02:00
committed by intellij-monorepo-bot
parent 6ebd9f17dd
commit dd1be69e58
4 changed files with 47 additions and 32 deletions

View File

@@ -40,10 +40,10 @@ object WindowsPathUtils {
}
/**
* Performs backward conversion.
* Performs backward conversion. Accepts and returns system independent slashes.
*
* `@/C/Users` -> `C:\Users`
* `server.share/dir/` -> `\\server.share\dir\`
* `@/C/Users` -> `C:/Users`
* `server.share/dir/` -> `//server.share/dir/`
*
*/
fun rootRelativeToEelPath(relativePath: String): String {
@@ -51,12 +51,12 @@ object WindowsPathUtils {
"${relativePath[2]}:${relativePath.drop(3)}"
}
else {
"\\\\$relativePath"
"//$relativePath"
}
}
/**
* Performs backward conversion.
* Performs backward conversion. Returns a pair of root and remaining path, both ready for constructing EelPath.
*
* `@/C/Users` -> `C:`, `Users`
* `server.share/dir/tmp` -> `\\server.share\dir`, `tmp`

View File

@@ -13,6 +13,7 @@ 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.eel.provider.utils.WindowsPathUtils
import com.intellij.platform.ijent.community.impl.nio.AbsoluteIjentNioPath
import com.intellij.platform.ijent.community.impl.nio.IjentNioPath
import com.intellij.util.text.nullize
import org.jetbrains.annotations.ApiStatus
@@ -185,7 +186,15 @@ class IjentEphemeralRootAwarePath(
override fun toString(): String {
return if (isAbsolute) {
rootPath.resolve(originalPath.pathString.removePrefix("/").replace("\\", fileSystem.separator)).toString()
when (originalPath.fileSystem.ijentFs.descriptor.osFamily) {
EelOsFamily.Posix -> {
rootPath.resolve(originalPath.pathString.removePrefix("/").replace("\\", fileSystem.separator)).pathString
}
EelOsFamily.Windows -> {
WindowsPathUtils.resolveEelPathOntoRoot(rootPath, (originalPath as AbsoluteIjentNioPath).eelPath).pathString
}
}
}
else {
originalPath.toString()

View File

@@ -16,7 +16,9 @@ import com.intellij.platform.eel.channels.EelDelicateApi
import com.intellij.platform.eel.fs.EelFileInfo
import com.intellij.platform.eel.fs.EelFileSystemApi
import com.intellij.platform.eel.fs.EelFileSystemPosixApi
import com.intellij.platform.eel.fs.EelFileSystemWindowsApi
import com.intellij.platform.eel.fs.EelPosixFileInfo
import com.intellij.platform.eel.fs.EelWindowsFileInfo
import com.intellij.platform.eel.fs.listDirectoryWithAttrs
import com.intellij.platform.eel.fs.readFile
import com.intellij.platform.eel.fs.stat
@@ -167,17 +169,25 @@ internal fun readAttributesUsingEel(nioPath: Path): FileAttributes {
return FileAttributes.fromNio(directAccessNioPath, nioAttributes)
}
return fsBlocking {
when (val eelFsApi = eelPath.descriptor.toEelApi().fs) {
is EelFileSystemPosixApi -> {
val fileInfo = eelFsApi.stat(eelPath).eelIt().getOrThrowFileSystemException()
fileInfo.toVfs(fileInfo.isWritable(eelFsApi))
}
else -> TODO()
}
val eelFsApi = eelPath.descriptor.toEelApi().fs
val fileInfo = eelFsApi.stat(eelPath).eelIt().getOrThrowFileSystemException()
toVfs(fileInfo, eelFsApi)
}
}
}
private fun toVfs(eelFileInfo: EelFileInfo, eelFsApi: EelFileSystemApi): FileAttributes {
return when {
eelFsApi is EelFileSystemPosixApi && eelFileInfo is EelPosixFileInfo -> {
eelFileInfo.toVfs(eelFileInfo.isWritable(eelFsApi))
}
eelFsApi is EelFileSystemWindowsApi && eelFileInfo is EelWindowsFileInfo -> {
eelFileInfo.toVfs(!eelFileInfo.permissions.isReadOnly)
}
else -> error("EelFileInfo ${eelFileInfo} does not belong to EelFileSystemApi ${eelFsApi}")
}
}
internal fun listWithAttributesUsingEel(
dir: VirtualFile,
filter: Set<String>?,
@@ -205,10 +215,10 @@ internal fun listWithAttributesUsingEel(
//We must return a 'normal' (=case-sensitive) map from this method, see BatchingFileSystem.listWithAttributes() contract:
val childrenWithAttributes = CollectionFactory.createFilePathMap<FileAttributes>(expectedSize, /*caseSensitive: */true)
visitDirectory(eelPath, filter) { file: EelPath, attributes: EelPosixFileInfo, eelFsApi: EelFileSystemPosixApi ->
visitDirectory(eelPath, filter) { file: EelPath, attributes: EelFileInfo, eelFsApi: EelFileSystemApi ->
try {
//val attributes = amendAttributes(file, fromNio(file, attributes))
childrenWithAttributes[file.fileName] = attributes.toVfs(attributes.isWritable(eelFsApi))
childrenWithAttributes[file.fileName] = toVfs(attributes, eelFsApi)
}
catch (e: Exception) {
LOG.debug(e)
@@ -237,28 +247,24 @@ internal fun listWithAttributesUsingEel(
private fun visitDirectory(
directory: EelPath,
filter: Set<String>?,
consumer: (EelPath, EelPosixFileInfo, EelFileSystemPosixApi) -> Boolean,
consumer: (EelPath, EelFileInfo, EelFileSystemApi) -> Boolean,
) {
if (filter != null && filter.isEmpty()) {
return //nothing to read
}
fsBlocking {
return@fsBlocking when (val eelFsApi = directory.descriptor.toEelApi().fs) {
is EelFileSystemPosixApi -> {
val directoryList =
eelFsApi.listDirectoryWithAttrs(directory).symlinkPolicy(EelFileSystemApi.SymlinkPolicy.RESOLVE_AND_FOLLOW).eelIt()
.getOrThrowFileSystemException()
for ((childName, childStat) in directoryList) {
val childIjentPath = directory.getChild(childName)
if (filter != null && !filter.contains(childIjentPath.fileName)) {
continue
}
if (!consumer(childIjentPath, childStat, eelFsApi)) {
break
}
}
val eelFsApi = directory.descriptor.toEelApi().fs
val directoryList =
eelFsApi.listDirectoryWithAttrs(directory).symlinkPolicy(EelFileSystemApi.SymlinkPolicy.RESOLVE_AND_FOLLOW).eelIt()
.getOrThrowFileSystemException()
for ((childName, childStat) in directoryList) {
val childIjentPath = directory.getChild(childName)
if (filter != null && !filter.contains(childIjentPath.fileName)) {
continue
}
if (!consumer(childIjentPath, childStat, eelFsApi)) {
break
}
else -> TODO()
}
}
}

View File

@@ -58,7 +58,7 @@ class WindowsPathUtilsTest {
server.share/dir/tmp/nested/file, \\server.share\dir, tmp/nested/file"""
)
fun `test rootRelativeToEelPath with Path parameter`(relativePath: String, expectedRoot: String, expectedSubpath: String) {
assertEquals("$expectedRoot${if (expectedSubpath.isEmpty()) "" else "\\$expectedSubpath"}".replace("\\", File.separator), WindowsPathUtils.rootRelativeToEelPath(relativePath.replace("/", File.separator)).replace("\\", File.separator))
assertEquals("$expectedRoot${if (expectedSubpath.isEmpty()) "" else "/$expectedSubpath"}".replace("\\", "/"), WindowsPathUtils.rootRelativeToEelPath(relativePath))
assertEquals(expectedRoot to Path(expectedSubpath), WindowsPathUtils.rootRelativeToEelPath(Path(relativePath.replace("/", File.separator))))
}
}