[eel] IJPL-172897: remove EelPath.OS, use only EelPlatform in the API

GitOrigin-RevId: 1a1b676865f759f4dbabc97165b62c77decb5087
This commit is contained in:
Andrii Zinchenko
2025-04-23 10:29:19 +02:00
committed by intellij-monorepo-bot
parent 566c7c026a
commit c92d860f76
43 changed files with 225 additions and 236 deletions

View File

@@ -9,6 +9,7 @@ import com.intellij.openapi.projectRoots.ProjectJdkTable
import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.projectRoots.SimpleJavaSdkType
import com.intellij.openapi.util.Disposer
import com.intellij.platform.eel.EelPlatform
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.provider.LocalEelDescriptor
import com.intellij.platform.eel.provider.utils.EelPathUtils
@@ -24,7 +25,7 @@ import java.nio.file.Path
@TestApplication
class ProjectWizardJdkComboBoxTest {
val eelFixture = eelFixture(EelPath.OS.UNIX)
val eelFixture = eelFixture(EelPlatform.Linux(EelPlatform.Arch.Unknown))
@Test
fun `changing eel changes available sdks`(@TestDisposable disposable: Disposable): Unit = timeoutRunBlocking {

View File

@@ -27,8 +27,6 @@ import kotlin.io.path.fileStore
import kotlin.streams.asSequence
abstract class NioBasedEelFileSystemApi(@VisibleForTesting val fs: FileSystem) : EelFileSystemApi {
abstract val pathOs: EelPath.OS
protected fun EelPath.toNioPath(): Path =
fs.getPath(toString())
@@ -337,7 +335,6 @@ abstract class PosixNioBasedEelFileSystemApi(
fs: FileSystem,
override val user: EelUserPosixInfo,
) : NioBasedEelFileSystemApi(fs), LocalEelFileSystemPosixApi {
override val pathOs: EelPath.OS = EelPath.OS.UNIX
override suspend fun createDirectory(
path: EelPath,
@@ -407,7 +404,6 @@ abstract class WindowsNioBasedEelFileSystemApi(
fs: FileSystem,
override val user: EelUserWindowsInfo,
) : NioBasedEelFileSystemApi(fs), LocalEelFileSystemWindowsApi {
override val pathOs: EelPath.OS = EelPath.OS.WINDOWS
override suspend fun getRootDirectories(): Collection<EelPath> =
FileSystems.getDefault().rootDirectories.map { path ->

View File

@@ -35,7 +35,6 @@ internal class LocalWindowsEelApiImpl(nioFs: FileSystem = FileSystems.getDefault
override val tunnels: EelTunnelsWindowsApi get() = EelLocalTunnelsApiImpl
override val descriptor: EelDescriptor get() = LocalEelDescriptor
override val platform: EelPlatform.Windows get() = EelPlatform.Windows(CpuArch.CURRENT.toEelArch())
override val exec: EelExecApi = EelLocalExecApi()
override val userInfo: EelUserWindowsInfo = EelUserWindowsInfoImpl(getLocalUserHome())
override val archive: EelArchiveApi = LocalEelArchiveApiImpl
@@ -62,19 +61,6 @@ class LocalPosixEelApiImpl(private val nioFs: FileSystem = FileSystems.getDefaul
override val tunnels: EelTunnelsPosixApi get() = EelLocalTunnelsApiImpl
override val descriptor: EelDescriptor get() = LocalEelDescriptor
override val platform: EelPlatform.Posix
get() {
val arch = CpuArch.CURRENT.toEelArch()
return when {
SystemInfo.isMac -> EelPlatform.Darwin(arch)
SystemInfo.isLinux -> EelPlatform.Linux(arch)
SystemInfo.isFreeBSD -> EelPlatform.FreeBSD(arch)
else -> {
LOG.info("Eel is not supported on current platform")
EelPlatform.Linux(arch)
}
}
}
override val exec: EelExecApi = EelLocalExecApi()
override val archive: EelArchiveApi = LocalEelArchiveApiImpl
@@ -85,7 +71,6 @@ class LocalPosixEelApiImpl(private val nioFs: FileSystem = FileSystems.getDefaul
}
override val fs: LocalEelFileSystemPosixApi = object : PosixNioBasedEelFileSystemApi(nioFs, userInfo) {
override val pathOs: EelPath.OS = EelPath.OS.UNIX
override val descriptor: EelDescriptor get() = LocalEelDescriptor
override suspend fun createTemporaryDirectory(

View File

@@ -8,6 +8,7 @@ import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.diagnostic.trace
import com.intellij.openapi.project.Project
import com.intellij.platform.eel.EelDescriptor
import com.intellij.platform.eel.EelPlatform
import com.intellij.platform.eel.path.EelPath
import org.jetbrains.annotations.NonNls
import java.nio.file.FileSystem
@@ -155,7 +156,7 @@ fun Path.asEelPath(): EelPath {
val descriptor = service.tryGetEelDescriptor(this) ?: return EelPath.parse(toString(), LocalEelDescriptor)
val root = service.tryGetNioRoots(descriptor)?.firstOrNull { this.startsWith(it) } ?: error("unreachable") // since the descriptor is not null, the root should be as well
val relative = root.relativize(this)
if (descriptor.operatingSystem == EelPath.OS.UNIX) {
if (descriptor.platform is EelPlatform.Posix) {
return relative.fold(EelPath.parse("/", descriptor), { path, part -> path.resolve(part.toString()) })
}
else {

View File

@@ -12,7 +12,9 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.util.SystemInfo
import com.intellij.platform.eel.*
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.provider.utils.toEelArch
import com.intellij.platform.util.coroutines.forEachConcurrent
import com.intellij.util.system.CpuArch
import com.intellij.util.system.OS
import kotlinx.coroutines.CancellationException
import org.jetbrains.annotations.ApiStatus
@@ -83,13 +85,22 @@ fun EelDescriptor.upgradeBlocking(): EelApi {
}
data object LocalEelDescriptor : EelDescriptor {
override val operatingSystem: EelPath.OS
get() = if (SystemInfo.isWindows) {
EelPath.OS.WINDOWS
}
else {
EelPath.OS.UNIX
private val LOG = logger<LocalEelDescriptor>()
override val platform: EelPlatform by lazy {
val arch = CpuArch.CURRENT.toEelArch()
when {
SystemInfo.isWindows -> EelPlatform.Windows(arch)
SystemInfo.isMac -> EelPlatform.Darwin(arch)
SystemInfo.isLinux -> EelPlatform.Linux(arch)
SystemInfo.isFreeBSD -> EelPlatform.FreeBSD(arch)
else -> {
LOG.info("Eel is not supported on current platform")
EelPlatform.Linux(arch)
}
}
}
override suspend fun upgrade(): EelApi {
return localEel

View File

@@ -7,6 +7,7 @@ import com.intellij.openapi.progress.runBlockingMaybeCancellable
import com.intellij.openapi.project.Project
import com.intellij.platform.eel.EelApi
import com.intellij.platform.eel.EelDescriptor
import com.intellij.platform.eel.EelPlatform
import com.intellij.platform.eel.fs.createTemporaryDirectory
import com.intellij.platform.eel.fs.createTemporaryFile
import com.intellij.platform.eel.path.EelPath
@@ -145,7 +146,7 @@ object EelPathUtils {
}
val root = eelPath.root.toString().replace('\\', '/')
// see sun.nio.fs.WindowsUriSupport#toUri(java.lang.String, boolean, boolean)
val trailing = if (eelPath.descriptor.operatingSystem == EelPath.OS.WINDOWS) "/" else ""
val trailing = if (eelPath.descriptor.platform is EelPlatform.Windows) "/" else ""
return URI("file", null, trailing + root + eelPath.parts.joinToString("/"), null, null)
}

View File

@@ -19,11 +19,11 @@ fun EelExecApi.fetchLoginShellEnvVariablesBlocking(): Map<String, String> {
}
fun CpuArch.toEelArch(): EelPlatform.Arch = when (this) {
CpuArch.X86 -> EelPlatform.X86
CpuArch.X86_64 -> EelPlatform.X86_64
CpuArch.ARM32 -> EelPlatform.ARM_32
CpuArch.ARM64 -> EelPlatform.ARM_64
CpuArch.OTHER, CpuArch.UNKNOWN -> EelPlatform.Unknown
CpuArch.X86 -> EelPlatform.Arch.X86
CpuArch.X86_64 -> EelPlatform.Arch.X86_64
CpuArch.ARM32 -> EelPlatform.Arch.ARM_32
CpuArch.ARM64 -> EelPlatform.Arch.ARM_64
CpuArch.OTHER, CpuArch.UNKNOWN -> EelPlatform.Arch.Unknown
}
@Throws(FileSystemException::class)

View File

@@ -14,7 +14,8 @@ interface LocalEelApi : EelApi
interface EelApi {
val descriptor: EelDescriptor
val platform: EelPlatform
// TODO: should it be extension property?
val platform: EelPlatform get() = descriptor.platform
/** Docs: [EelFileSystemApi] */
val fs: EelFileSystemApi
@@ -42,14 +43,12 @@ interface EelApi {
}
interface EelPosixApi : EelApi {
override val platform: EelPlatform.Posix
override val tunnels: EelTunnelsPosixApi
override val userInfo: EelUserPosixInfo
override val fs: EelFileSystemPosixApi
}
interface EelWindowsApi : EelApi {
override val platform: EelPlatform.Windows
override val tunnels: EelTunnelsWindowsApi
override val userInfo: EelUserWindowsInfo
override val fs: EelFileSystemWindowsApi

View File

@@ -2,6 +2,7 @@
package com.intellij.platform.eel
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.path.EelPath.OS
/**
* A descriptor of an environment where [EelApi] may exist.
@@ -33,11 +34,17 @@ import com.intellij.platform.eel.path.EelPath
* If you need to access the remote environment, you can use the method [upgrade], which can suspend for some time before returning a working instance of [EelApi]
*/
interface EelDescriptor {
@Deprecated("Use platform instead", ReplaceWith("platform"))
val operatingSystem: OS
get() = when (platform) {
is EelPlatform.Windows -> OS.WINDOWS
is EelPlatform.Posix -> OS.UNIX
}
/**
* The platform of an environment corresponding to this [EelDescriptor].
*/
val operatingSystem: EelPath.OS
val platform: EelPlatform
/**
* Retrieves an instance of [EelApi] corresponding to this [EelDescriptor].

View File

@@ -2,29 +2,36 @@
package com.intellij.platform.eel
import com.intellij.platform.eel.EelPlatform.*
import com.intellij.platform.eel.path.pathOs
import com.intellij.platform.eel.path.pathSeparator
val EelPlatform.isMac: Boolean get() = this is Darwin
val EelPlatform.isLinux: Boolean get() = this is Linux
val EelPlatform.isWindows: Boolean get() = this is Windows
val EelPlatform.isFreeBSD: Boolean get() = this is FreeBSD
val EelPlatform.isArm32: Boolean get() = arch is ARM_32
val EelPlatform.isArm64: Boolean get() = arch is ARM_64
val EelPlatform.isX86: Boolean get() = arch is X86
val EelPlatform.isX86_64: Boolean get() = arch is X86_64
val EelPlatform.isArm32: Boolean get() = arch is Arch.ARM_32
val EelPlatform.isArm64: Boolean get() = arch is Arch.ARM_64
val EelPlatform.isX86: Boolean get() = arch is Arch.X86
val EelPlatform.isX86_64: Boolean get() = arch is Arch.X86_64
private val UNIX_DIRECTORY_SEPARATORS = charArrayOf('/')
private val WINDOWS_DIRECTORY_SEPARATORS = charArrayOf('/', '\\')
val EelPlatform.directorySeparators: CharArray
get() = when (this) {
is Windows -> WINDOWS_DIRECTORY_SEPARATORS
is Posix -> UNIX_DIRECTORY_SEPARATORS
}
sealed interface EelPlatform {
val arch: Arch
sealed interface Arch
data object X86_64 : Arch
data object ARM_64 : Arch
data object ARM_32 : Arch
data object X86 : Arch
data object Unknown : Arch
sealed interface Arch {
data object X86_64 : Arch
data object ARM_64 : Arch
data object ARM_32 : Arch
data object X86 : Arch
data object Unknown : Arch
}
sealed interface Posix : EelPlatform
@@ -48,18 +55,18 @@ sealed interface EelPlatform {
fun getFor(os: String, arch: String): EelPlatform? =
when (os.lowercase()) {
"darwin" -> when (arch.lowercase()) {
"arm64", "aarch64" -> Darwin(ARM_64)
"amd64", "x86_64", "x86-64" -> Darwin(X86_64)
"arm64", "aarch64" -> Darwin(Arch.ARM_64)
"amd64", "x86_64", "x86-64" -> Darwin(Arch.X86_64)
else -> null
}
"linux" -> when (arch.lowercase()) {
"arm64", "aarch64" -> Linux(ARM_64)
"amd64", "x86_64", "x86-64" -> Linux(X86_64)
"arm64", "aarch64" -> Linux(Arch.ARM_64)
"amd64", "x86_64", "x86-64" -> Linux(Arch.X86_64)
else -> null
}
"windows" -> when (arch.lowercase()) {
"amd64", "x86_64", "x86-64" -> Windows(X86_64)
"arm64", "aarch64" -> Windows(ARM_64)
"amd64", "x86_64", "x86-64" -> Windows(Arch.X86_64)
"arm64", "aarch64" -> Windows(Arch.ARM_64)
else -> null
}
else -> null
@@ -68,4 +75,7 @@ sealed interface EelPlatform {
}
val EelPlatform.pathSeparator: String
get(): String = pathOs.pathSeparator
get() = when (this) {
is Windows -> ";"
is Posix -> ":"
}

View File

@@ -7,13 +7,6 @@ import com.intellij.platform.eel.path.EelPath
import org.jetbrains.annotations.CheckReturnValue
import java.nio.ByteBuffer
val EelFileSystemApi.pathOs: EelPath.OS
get() = when (this) {
is EelFileSystemPosixApi -> EelPath.OS.UNIX
is EelFileSystemWindowsApi -> EelPath.OS.WINDOWS
else -> throw UnsupportedOperationException("Unsupported OS: ${this::class.java}")
}
val EelFileSystemApi.pathSeparator: String
get() = when (this) {
is EelFileSystemPosixApi -> ":"

View File

@@ -2,6 +2,8 @@
package com.intellij.platform.eel.path
import com.intellij.platform.eel.EelDescriptor
import com.intellij.platform.eel.EelPlatform
import com.intellij.platform.eel.directorySeparators
internal class ArrayListEelAbsolutePath private constructor(
override val descriptor: EelDescriptor,
@@ -51,7 +53,7 @@ internal class ArrayListEelAbsolutePath private constructor(
}
override fun resolve(other: String): EelPath {
val delimiters = this.os.directorySeparators
val delimiters = this.platform.directorySeparators
val otherParts = other.split(*delimiters).filter(String::isNotEmpty)
for (name in otherParts) {
if (name.isNotEmpty()) {
@@ -115,12 +117,6 @@ internal class ArrayListEelAbsolutePath private constructor(
return nameCount - other.nameCount
}
override val os: EelPath.OS
get() = when (this._root) {
Root.Unix -> EelPath.OS.UNIX
is Root.Windows -> EelPath.OS.WINDOWS
}
override fun equals(other: Any?): Boolean =
other is EelPath &&
nameCount == other.nameCount &&
@@ -140,9 +136,9 @@ internal class ArrayListEelAbsolutePath private constructor(
fun build(parts: List<String>, descriptor: EelDescriptor): EelPath {
require(parts.isNotEmpty()) { "Can't build an absolute path from no path parts" }
val windowsRoot = when (descriptor.operatingSystem) {
EelPath.OS.WINDOWS -> findAbsoluteUncPath(parts.first(), descriptor) ?: findAbsoluteTraditionalDosPath(parts.first(), descriptor)
EelPath.OS.UNIX -> null
val windowsRoot = when (descriptor.platform) {
is EelPlatform.Windows -> findAbsoluteUncPath(parts.first(), descriptor) ?: findAbsoluteTraditionalDosPath(parts.first(), descriptor)
is EelPlatform.Posix -> null
}
when (windowsRoot) {
null -> {
@@ -174,9 +170,9 @@ internal class ArrayListEelAbsolutePath private constructor(
@Throws(EelPathException::class)
fun parseOrNull(raw: String, descriptor: EelDescriptor): ArrayListEelAbsolutePath? =
when (descriptor.operatingSystem) {
EelPath.OS.WINDOWS -> findAbsoluteUncPath(raw, descriptor) ?: findAbsoluteTraditionalDosPath(raw, descriptor)
EelPath.OS.UNIX -> findAbsoluteUnixPath(raw, descriptor)
when (descriptor.platform) {
is EelPlatform.Windows -> findAbsoluteUncPath(raw, descriptor) ?: findAbsoluteTraditionalDosPath(raw, descriptor)
is EelPlatform.Posix -> findAbsoluteUnixPath(raw, descriptor)
}
/** https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#unc-paths */

View File

@@ -3,7 +3,8 @@ package com.intellij.platform.eel.path
import com.intellij.platform.eel.EelDescriptor
import com.intellij.platform.eel.EelPlatform
import com.intellij.platform.eel.path.EelPath.OS
val EelPath.platform: EelPlatform get() = descriptor.platform
/**
* An interface for **absolute** paths on some environment.
@@ -130,16 +131,6 @@ sealed interface EelPath {
/** See [java.nio.file.Path.endsWith] */
fun endsWith(suffix: List<String>): Boolean
/**
* Returns [EelPath.OS] that corresponds to this path.
*
* ```kotlin
* EelPath.parse("/abc/").os == EelPath.OS.UNIX
* EelPath.parse("C:\\abc\").os == EelPath.OS.WINDOWS
* ```
*/
val os: OS
/**
* ```kotlin
* EelPath.parse("/abc", OS.UNIX).getChild("..") == EelPath.parse("abc/..", false)
@@ -156,6 +147,7 @@ sealed interface EelPath {
override fun toString(): String
@Deprecated("Use EelPlatform instead, will be removed soon")
enum class OS {
WINDOWS, UNIX
}
@@ -163,26 +155,4 @@ sealed interface EelPath {
operator fun EelPath.div(part: String): EelPath = resolve(part)
val OS.pathSeparator: String
get() = when (this) {
OS.UNIX -> ":"
OS.WINDOWS -> ";"
}
val EelPlatform.pathOs: OS
get() = when (this) {
is EelPlatform.Posix -> OS.UNIX
is EelPlatform.Windows -> OS.WINDOWS
}
private val UNIX_DIRECTORY_SEPARATORS = charArrayOf('/')
private val WINDOWS_DIRECTORY_SEPARATORS = charArrayOf('/', '\\')
val OS.directorySeparators: CharArray
get() = when (this) {
OS.UNIX -> UNIX_DIRECTORY_SEPARATORS
OS.WINDOWS -> WINDOWS_DIRECTORY_SEPARATORS
}
class EelPathException(val raw: String, val reason: String) : RuntimeException("`$raw`: $reason")

View File

@@ -3,12 +3,14 @@ package com.intellij.platform.eel.path
import com.intellij.platform.eel.EelApi
import com.intellij.platform.eel.EelDescriptor
import com.intellij.platform.eel.EelPlatform
import io.kotest.matchers.shouldBe
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.DynamicTest
import org.junit.jupiter.api.DynamicTest.dynamicTest
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestFactory
import kotlin.collections.component1
class EelAbsolutePathTest {
@TestFactory
@@ -20,7 +22,7 @@ class EelAbsolutePathTest {
"/foo/bar/.",
"/foo/bar/./baz",
"/foo/bar/./baz/..",
).map { it to EelPath.OS.UNIX }
).map { it to EelPlatform.Linux(EelPlatform.Arch.Unknown) }
val windowsPaths = listOf(
"""C:\""", // Keep in mind that "C:" is not an absolute path, it actually points to a current directory.
@@ -33,7 +35,7 @@ class EelAbsolutePathTest {
"""\\wsl${'$'}\Ubuntu-22.04""",
"""\\wsl${'$'}\Ubuntu-22.04\home""",
"""\\wsl${'$'}\Ubuntu-22.04\home\user""",
).map { it to EelPath.OS.WINDOWS }
).map { it to EelPlatform.Windows(EelPlatform.Arch.Unknown) }
for ((rawPath, os) in (unixPaths + windowsPaths)) {
add(dynamicTest(rawPath) {
@@ -45,8 +47,8 @@ class EelAbsolutePathTest {
@TestFactory
fun `os-dependent separators`(): List<DynamicTest> = buildList {
val unixPath = EelPath.parse("/", DummyEelDescriptor(EelPath.OS.UNIX))
val windowsPath = EelPath.parse("C:\\", DummyEelDescriptor(EelPath.OS.WINDOWS))
val unixPath = EelPath.parse("/", DummyEelDescriptor(EelPlatform.Linux(EelPlatform.Arch.Unknown)))
val windowsPath = EelPath.parse("C:\\", DummyEelDescriptor(EelPlatform.Windows(EelPlatform.Arch.Unknown)))
val parts = listOf(Triple("a/b/c/d", listOf("a", "b", "c", "d"), listOf("a", "b", "c", "d")),
Triple("a\\b\\c\\d", listOf("a\\b\\c\\d"), listOf("a", "b", "c", "d")),
Triple("a\\b/c\\d", listOf("a\\b", "c\\d"), listOf("a", "b", "c", "d")))
@@ -62,13 +64,13 @@ class EelAbsolutePathTest {
@Test
fun endsWith() {
val path = EelPath.parse("C:\\foo\\bar\\baz", DummyEelDescriptor(EelPath.OS.WINDOWS))
val path = EelPath.parse("C:\\foo\\bar\\baz", DummyEelDescriptor(EelPlatform.Windows(EelPlatform.Arch.Unknown)))
path.endsWith(listOf("bar", "baz")) shouldBe true
path.endsWith(listOf("bar", "baz", "qux")) shouldBe false
path.endsWith(listOf("C:", "foo", "bar", "bax")) shouldBe false
}
class DummyEelDescriptor(override val operatingSystem: EelPath.OS) : EelDescriptor {
class DummyEelDescriptor(override val platform: EelPlatform) : EelDescriptor {
override suspend fun upgrade(): EelApi {
return Assertions.fail<Nothing>()
}

View File

@@ -1,9 +1,9 @@
// 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.ijent.community.impl.nio
import com.intellij.platform.eel.directorySeparators
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.path.EelPathException
import com.intellij.platform.eel.path.directorySeparators
import com.intellij.platform.ijent.fs.IjentFileSystemApi
import com.intellij.platform.ijent.fs.IjentFileSystemPosixApi
import com.intellij.platform.ijent.fs.IjentFileSystemWindowsApi
@@ -67,15 +67,11 @@ class IjentNioFileSystem internal constructor(
}
override fun getPath(first: String, vararg more: String): IjentNioPath {
val os = when (ijentFs) {
is IjentFileSystemPosixApi -> EelPath.OS.UNIX
is IjentFileSystemWindowsApi -> EelPath.OS.WINDOWS
}
return try {
more.fold(EelPath.parse(first, ijentFs.descriptor)) { path, newPart -> path.resolve(newPart) }.toNioPath()
}
catch (_: EelPathException) {
RelativeIjentNioPath(first.split(*os.directorySeparators) + more, this)
RelativeIjentNioPath(first.split(*ijentFs.descriptor.platform.directorySeparators) + more, this)
}
}

View File

@@ -3,12 +3,12 @@ package com.intellij.platform.ijent.community.impl.nio
import com.intellij.openapi.diagnostic.thisLogger
import com.intellij.platform.core.nio.fs.BasicFileAttributesHolder2.FetchAttributesFilter
import com.intellij.platform.eel.directorySeparators
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.EelPosixFileInfo.Type.Symlink
import com.intellij.platform.eel.impl.fs.EelFsResultImpl
import com.intellij.platform.eel.path.directorySeparators
import com.intellij.platform.eel.provider.utils.getOrThrowFileSystemException
import com.intellij.platform.eel.provider.utils.throwFileSystemException
import com.intellij.platform.ijent.community.impl.nio.IjentNioFileSystemProvider.Companion.newFileSystemMap
@@ -577,7 +577,7 @@ class IjentNioFileSystemProvider : FileSystemProvider() {
override fun readSymbolicLink(link: Path): Path {
val fs = ensureAbsoluteIjentNioPath(link).nioFs
val absolutePath = link.eelPath
val os = fs.ijentFs.pathOs
val os = fs.ijentFs.descriptor.platform
return fsBlocking {
when (val ijentFs = fs.ijentFs) {
is IjentFileSystemPosixApi -> when (val type = ijentFs.stat(absolutePath).justResolve().getOrThrowFileSystemException().type) {

View File

@@ -2,8 +2,10 @@
package com.intellij.platform.ijent.community.impl.nio
import com.intellij.platform.core.nio.fs.BasicFileAttributesHolder2
import com.intellij.platform.eel.EelPlatform
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.path.EelPathException
import com.intellij.platform.eel.path.platform
import com.intellij.platform.eel.provider.utils.getOrThrowFileSystemException
import org.jetbrains.annotations.ApiStatus
import java.net.URI
@@ -155,9 +157,9 @@ internal class AbsoluteIjentNioPath(val eelPath: EelPath, nioFs: IjentNioFileSys
}
override fun toUri(): URI {
val prefix = when (eelPath.os) {
EelPath.OS.WINDOWS -> "/" + eelPath.root.toString().replace('\\', '/')
EelPath.OS.UNIX -> null
val prefix = when (eelPath.platform) {
is EelPlatform.Windows -> "/" + eelPath.root.toString().replace('\\', '/')
is EelPlatform.Posix -> null
}
val allParts = listOfNotNull(prefix) + eelPath.parts
return allParts.fold(nioFs.uri, URI::resolve)

View File

@@ -7,22 +7,22 @@ val EelPlatform.executableName: String
get() = when (this) {
is EelPlatform.Darwin -> {
when (arch) {
EelPlatform.ARM_64 -> "ijent-aarch64-apple-darwin-release"
EelPlatform.X86_64 -> "ijent-x86_64-apple-darwin-release"
EelPlatform.Arch.ARM_64 -> "ijent-aarch64-apple-darwin-release"
EelPlatform.Arch.X86_64 -> "ijent-x86_64-apple-darwin-release"
else -> throw IllegalArgumentException("Unsupported darwin arch: $arch")
}
}
is EelPlatform.Linux -> {
when (arch) {
EelPlatform.ARM_64 -> "ijent-aarch64-unknown-linux-musl-release"
EelPlatform.X86_64 -> "ijent-x86_64-unknown-linux-musl-release"
EelPlatform.Arch.ARM_64 -> "ijent-aarch64-unknown-linux-musl-release"
EelPlatform.Arch.X86_64 -> "ijent-x86_64-unknown-linux-musl-release"
else -> throw IllegalArgumentException("Unsupported linux arch: $arch")
}
}
is EelPlatform.Windows -> {
when (arch) {
EelPlatform.ARM_64 -> "ijent-aarch64-pc-windows-gnu-release" // todo: refine later when we support windows
EelPlatform.X86_64 -> "ijent-x86_64-pc-windows-gnu-release.exe"
EelPlatform.Arch.ARM_64 -> "ijent-aarch64-pc-windows-gnu-release" // todo: refine later when we support windows
EelPlatform.Arch.X86_64 -> "ijent-x86_64-pc-windows-gnu-release.exe"
else -> throw IllegalArgumentException("Unsupported windows arch: $arch")
}
}

View File

@@ -58,12 +58,16 @@ abstract class IjentDeployingOverShellProcessStrategy(scope: CoroutineScope) : I
context
}
override suspend fun getTargetPlatform(): EelPlatform.Posix {
return myContext.await().execCommand {
private val myTargetPlatform = scope.async(start = CoroutineStart.LAZY) {
myContext.await().execCommand {
getTargetPlatform()
}
}
override suspend fun getTargetPlatform(): EelPlatform.Posix {
return myTargetPlatform.await()
}
final override suspend fun createProcess(binaryPath: String): IjentSessionMediator {
return myContext.await().execCommand {
execIjent(binaryPath)
@@ -301,8 +305,8 @@ private suspend fun DeployingContextAndShell.getTargetPlatform(): EelPlatform.Po
val targetPlatform = when {
arch.isEmpty() -> throw IjentStartupError.IncompatibleTarget("Empty output of `uname`")
"x86_64" in arch -> EelPlatform.Linux(EelPlatform.X86_64)
"aarch64" in arch -> EelPlatform.Linux(EelPlatform.ARM_64)
"x86_64" in arch -> EelPlatform.Linux(EelPlatform.Arch.X86_64)
"aarch64" in arch -> EelPlatform.Linux(EelPlatform.Arch.ARM_64)
else -> throw IjentStartupError.IncompatibleTarget("No binary for architecture $arch")
}
return targetPlatform

View File

@@ -19,7 +19,7 @@ import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.JarUtil;
import com.intellij.platform.eel.EelDescriptor;
import com.intellij.platform.eel.path.EelPath;
import com.intellij.platform.eel.EelPlatform;
import com.intellij.platform.eel.provider.EelProviderUtil;
import com.intellij.util.lang.JavaVersion;
import org.jetbrains.annotations.ApiStatus;
@@ -204,12 +204,12 @@ public final class JdkUtil {
}
private static boolean isCompatibleWithOs(@NotNull EelDescriptor descriptor) {
EelPath.OS os = descriptor.getOperatingSystem();
EelPlatform os = descriptor.getPlatform();
if (SystemInfo.isWindows) {
return os == EelPath.OS.WINDOWS;
return os instanceof EelPlatform.Windows;
}
else {
return os == EelPath.OS.UNIX;
return os instanceof EelPlatform.Posix;
}
}

View File

@@ -6,6 +6,7 @@ import com.intellij.openapi.application.edtWriteAction
import com.intellij.openapi.roots.ui.configuration.SdkTestCase.TestSdkGenerator.SdkInfo
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel
import com.intellij.openapi.roots.ui.configuration.testSdkFixture
import com.intellij.platform.eel.EelPlatform
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.provider.utils.EelPathUtils
import com.intellij.platform.testFramework.junit5.eel.fixture.eelFixture
@@ -25,7 +26,7 @@ import java.nio.file.Files
@TestApplication
class ProjectJdkEelTest {
val eel = eelFixture(EelPath.OS.UNIX)
val eel = eelFixture(EelPlatform.Linux(EelPlatform.Arch.Unknown))
val localProject = projectFixture(openAfterCreation = true)

View File

@@ -4,7 +4,7 @@
import com.intellij.ide.IdeCoreBundle;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.platform.eel.path.EelPath;
import com.intellij.platform.eel.EelPlatform;
import com.intellij.platform.eel.provider.utils.JEelUtils;
import com.intellij.util.SystemProperties;
import org.jetbrains.annotations.NotNull;
@@ -40,7 +40,7 @@
if (contextPath != null) {
var eelPath = JEelUtils.toEelPath(contextPath);
if (eelPath != null) {
return eelPath.getOs() == EelPath.OS.WINDOWS;
return eelPath.getDescriptor().getPlatform() instanceof EelPlatform.Windows;
}
}
return SystemInfo.isWindows;

View File

@@ -5,29 +5,39 @@ import com.intellij.execution.wsl.WSLDistribution
import com.intellij.execution.wsl.WslDistributionManager
import com.intellij.execution.wsl.WslIjentManager
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.progress.runBlockingMaybeCancellable
import com.intellij.platform.eel.EelPlatform
import com.intellij.platform.eel.provider.EelNioBridgeService
import com.intellij.platform.eel.provider.getEelDescriptor
import com.intellij.platform.ijent.community.impl.IjentFailSafeFileSystemPosixApi
import com.intellij.platform.ijent.community.impl.nio.IjentNioFileSystemProvider
import com.intellij.platform.ijent.community.impl.nio.telemetry.TracingFileSystemProvider
import com.intellij.platform.ide.impl.wsl.ijent.nio.IjentWslNioFileSystemProvider
import com.intellij.platform.ijent.IjentPosixApi
import com.intellij.util.containers.ContainerUtil
import com.intellij.util.containers.forEachGuaranteed
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.job
import kotlinx.coroutines.launch
import org.jetbrains.annotations.ApiStatus
import org.jetbrains.annotations.VisibleForTesting
import java.net.URI
import java.nio.file.FileSystem
import java.nio.file.FileSystemAlreadyExistsException
import java.nio.file.spi.FileSystemProvider
import java.util.concurrent.ConcurrentHashMap
import java.util.function.BiConsumer
private suspend fun WSLDistribution.getIjent(): IjentPosixApi {
return WslIjentManager.instanceAsync().getIjentApi(this, null, false)
}
@ApiStatus.Internal
@VisibleForTesting
class IjentWslNioFsToggleStrategy(
private val coroutineScope: CoroutineScope,
) {
internal val enabledInDistros: MutableSet<WSLDistribution> = ContainerUtil.newConcurrentSet()
internal val enabledInDistros: MutableMap<WSLDistribution, WslEelDescriptor> = ConcurrentHashMap()
private val providersCache = ContainerUtil.createConcurrentWeakMap<String, IjentWslNioFileSystemProvider>()
@@ -60,23 +70,27 @@ class IjentWslNioFsToggleStrategy(
}
private fun handleWslDistributionAddition(distro: WSLDistribution) {
enabledInDistros += distro
switchToIjentFs(distro)
}
private fun handleWslDistributionDeletion(distro: WSLDistribution) {
enabledInDistros -= distro
recomputeEel(distro) { _, actualFs ->
actualFs
val descriptor = enabledInDistros.remove(distro)
if (descriptor != null) {
recomputeEel(descriptor) { _, actualFs ->
actualFs
}
}
}
fun switchToIjentFs(distro: WSLDistribution) {
val ijentFsProvider = TracingFileSystemProvider(IjentNioFileSystemProvider.getInstance())
val descriptor = runBlockingMaybeCancellable { distro.getIjent() }.descriptor as WslEelDescriptor
enabledInDistros[distro] = descriptor
try {
val ijentFs = IjentFailSafeFileSystemPosixApi(coroutineScope) {
WslIjentManager.instanceAsync().getIjentApi(distro, null, false)
}
val ijentFs = IjentFailSafeFileSystemPosixApi(coroutineScope) { distro.getIjent() }
ijentFsProvider.newFileSystem(
URI("ijent", "wsl", "/${distro.id}", null, null),
IjentNioFileSystemProvider.newFileSystemMap(ijentFs),
@@ -86,7 +100,7 @@ class IjentWslNioFsToggleStrategy(
// Nothing.
}
recomputeEel(distro) { underlyingProvider, _ ->
recomputeEel(descriptor) { underlyingProvider, _ ->
val fileSystemProvider = providersCache.computeIfAbsent(distro.id) {
IjentWslNioFileSystemProvider(
wslDistribution = distro,
@@ -100,9 +114,9 @@ class IjentWslNioFsToggleStrategy(
}
}
fun switchToTracingWsl9pFs(distro: WSLDistribution) {
recomputeEel(distro) { underlyingProvider, previousFs ->
LOG.info("Switching $distro to the original file system but with tracing")
fun switchToTracingWsl9pFs(descriptor: WslEelDescriptor) {
recomputeEel(descriptor) { underlyingProvider, previousFs ->
LOG.info("Switching $descriptor to the original file system but with tracing")
try {
previousFs?.close()
@@ -118,14 +132,11 @@ class IjentWslNioFsToggleStrategy(
fun unregisterAll() {
val service = EelNioBridgeService.getInstanceSync()
val distros = mutableListOf<WSLDistribution>()
enabledInDistros.removeIf {
distros += it
true
}
for (distro in distros) {
service.unregister(WslEelDescriptor(distro))
enabledInDistros.entries.forEachGuaranteed { (_, descriptor) ->
service.unregister(descriptor)
}
enabledInDistros.clear()
}
}
@@ -144,13 +155,12 @@ private val WSLDistribution.roots: Set<String>
}
private fun recomputeEel(
distro: WSLDistribution,
descriptor: WslEelDescriptor,
action: (underlyingProvider: FileSystemProvider, previousFs: FileSystem?) -> FileSystem?,
) {
val service = EelNioBridgeService.getInstanceSync()
val descriptor = WslEelDescriptor(distro)
distro.roots.forEachGuaranteed { localRoot ->
service.register(localRoot, descriptor, distro.id, false, false, action)
descriptor.distribution.roots.forEachGuaranteed { localRoot ->
service.register(localRoot, descriptor, descriptor.distribution.id, false, false, action)
}
}

View File

@@ -12,6 +12,7 @@ import com.intellij.openapi.util.SystemInfo
import com.intellij.platform.core.nio.fs.MultiRoutingFileSystemProvider
import com.intellij.platform.eel.EelApi
import com.intellij.platform.eel.EelDescriptor
import com.intellij.platform.eel.EelPlatform
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.provider.EelProvider
import com.intellij.platform.ide.impl.wsl.ijent.nio.toggle.IjentWslNioFsToggler.WslEelProvider
@@ -47,15 +48,14 @@ class IjentWslNioFsToggler(private val coroutineScope: CoroutineScope) {
fun switchToIjentFs(distro: WSLDistribution) {
logErrorIfNotWindows()
strategy ?: error("Not available")
strategy.enabledInDistros.add(distro)
strategy.switchToIjentFs(distro)
}
@TestOnly
fun switchToTracingWsl9pFs(distro: WSLDistribution) {
fun switchToTracingWsl9pFs(descriptor: WslEelDescriptor) {
logErrorIfNotWindows()
strategy ?: error("Not available")
strategy.switchToTracingWsl9pFs(distro)
strategy.switchToTracingWsl9pFs(descriptor)
}
@TestOnly
@@ -154,9 +154,7 @@ private suspend fun tryInitializeEelOnWsl(path: String) {
}
data class WslEelDescriptor(val distribution: WSLDistribution) : EelDescriptor {
override val operatingSystem: EelPath.OS = EelPath.OS.UNIX
data class WslEelDescriptor(val distribution: WSLDistribution, override val platform: EelPlatform) : EelDescriptor {
override suspend fun upgrade(): EelApi {
return WslEelProvider().getApiByDistribution(distribution)

View File

@@ -47,7 +47,7 @@ class WslIjentDeployingStrategy(
}
override suspend fun getTargetDescriptor(): EelDescriptor {
return WslEelDescriptor(distribution)
return WslEelDescriptor(distribution, getTargetPlatform())
}
override suspend fun getConnectionStrategy(): IjentConnectionStrategy {

View File

@@ -521,16 +521,13 @@ enum class WslTestStrategy { Legacy, Ijent }
private class MockIjentApi(private val adapter: GeneralCommandLine, val rootUser: Boolean) : IjentPosixApi {
override val descriptor: EelDescriptor
get() = object : EelDescriptor {
override val operatingSystem: EelPath.OS
get() = EelPath.OS.UNIX
override val platform: EelPlatform = EelPlatform.Linux(EelPlatform.Arch.Unknown)
override suspend fun upgrade(): EelApi {
throw UnsupportedOperationException()
}
}
override val platform: EelPlatform.Posix get() = throw UnsupportedOperationException()
override val archive: EelArchiveApi get() = throw UnsupportedOperationException()
override val isRunning: Boolean get() = true

View File

@@ -3,6 +3,7 @@ package com.intellij.platform.testFramework.junit5.eel.fixture
import com.intellij.platform.eel.EelApi
import com.intellij.platform.eel.EelDescriptor
import com.intellij.platform.eel.EelPlatform
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.testFramework.junit5.eel.impl.currentOs
import com.intellij.platform.testFramework.junit5.eel.impl.eelInitializer
@@ -38,7 +39,7 @@ interface IsolatedFileSystem {
* The local file system would not be able to recognize these paths, so you can test whether your feature is eel-agnostic.
*/
@TestOnly
fun eelFixture(os: EelPath.OS = currentOs): TestFixture<IsolatedFileSystem> {
fun eelFixture(os: EelPlatform = currentOs): TestFixture<IsolatedFileSystem> {
return testFixture("eel-test-fixture", eelInitializer(os))
}

View File

@@ -3,11 +3,10 @@ package com.intellij.platform.testFramework.junit5.eel.impl
import com.intellij.platform.eel.EelApi
import com.intellij.platform.eel.EelDescriptor
import com.intellij.platform.eel.EelPlatform
import com.intellij.platform.eel.path.EelPath
internal class EelTestDescriptor(val id: String, os: EelPath.OS, val apiProvider: () -> EelApi) : EelDescriptor {
override val operatingSystem: EelPath.OS = os
internal class EelTestDescriptor(val id: String, override val platform: EelPlatform, val apiProvider: () -> EelApi) : EelDescriptor {
override suspend fun upgrade(): EelApi {
return apiProvider()
}

View File

@@ -15,8 +15,6 @@ import java.nio.file.Path
internal class EelTestPosixApi(override val descriptor: EelTestDescriptor, fileSystem: EelUnitTestFileSystem, localPrefix: String) : EelPosixApi {
override val userInfo: EelUserPosixInfo = EelTestPosixUserInfo(descriptor)
override val platform: EelPlatform.Posix = EelPlatform.Linux(CpuArch.CURRENT.toEelArch())
override val fs: PosixNioBasedEelFileSystemApi = EelTestFileSystemPosixApi(descriptor, fileSystem)
override val archive: EelArchiveApi

View File

@@ -13,8 +13,6 @@ import com.intellij.util.system.CpuArch
internal class EelTestWindowsApi(override val descriptor: EelTestDescriptor, fileSystem: EelUnitTestFileSystem, localPrefix: String) : EelWindowsApi {
override val userInfo: EelUserWindowsInfo = EelTestWindowsUserInfo(descriptor)
override val platform: EelPlatform.Windows = EelPlatform.Windows(CpuArch.CURRENT.toEelArch())
override val fs: WindowsNioBasedEelFileSystemApi = EelTestFileSystemWindowsApi(descriptor, fileSystem)
override val archive: EelArchiveApi

View File

@@ -2,6 +2,7 @@
package com.intellij.platform.testFramework.junit5.eel.impl.nio
import com.intellij.openapi.util.SystemInfo
import com.intellij.platform.eel.EelPlatform
import com.intellij.platform.eel.path.EelPath
import java.io.File
import java.nio.file.FileStore
@@ -12,7 +13,7 @@ import java.nio.file.WatchService
import java.nio.file.attribute.UserPrincipalLookupService
import java.nio.file.spi.FileSystemProvider
internal class EelUnitTestFileSystem(val provider: FileSystemProvider, val os: EelPath.OS, val rootDirectory: Path, val fakeLocalRoot: String) : FileSystem() {
internal class EelUnitTestFileSystem(val provider: FileSystemProvider, val os: EelPlatform, val rootDirectory: Path, val fakeLocalRoot: String) : FileSystem() {
val root: EelUnitTestPath = EelUnitTestPath(this, rootDirectory)
override fun provider(): FileSystemProvider {

View File

@@ -7,9 +7,9 @@ import com.intellij.openapi.util.SystemInfo
import com.intellij.platform.core.nio.fs.MultiRoutingFileSystem
import com.intellij.platform.eel.EelApi
import com.intellij.platform.eel.EelDescriptor
import com.intellij.platform.eel.EelPlatform
import com.intellij.platform.eel.fs.createTemporaryDirectory
import com.intellij.platform.eel.getOrThrow
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.provider.EelNioBridgeService
import com.intellij.platform.eel.provider.asNioPath
import com.intellij.platform.testFramework.junit5.eel.fixture.IsolatedFileSystem
@@ -28,26 +28,31 @@ import kotlin.io.path.name
internal const val FAKE_WINDOWS_ROOT = "\\\\dummy-ij-root\\test-eel\\"
internal val currentOs: EelPath.OS
private val EelPlatform.name: String get() = when (this) {
is EelPlatform.Posix -> "posix"
is EelPlatform.Windows -> "windows"
}
internal val currentOs: EelPlatform
get() = if (SystemInfo.isWindows) {
EelPath.OS.WINDOWS
EelPlatform.Windows(EelPlatform.Arch.Unknown)
}
else {
EelPath.OS.UNIX
EelPlatform.Linux(EelPlatform.Arch.Unknown)
}
internal fun eelApiByOs(fileSystem: EelUnitTestFileSystem, descriptor: EelTestDescriptor, os: EelPath.OS): EelApi {
internal fun eelApiByOs(fileSystem: EelUnitTestFileSystem, descriptor: EelTestDescriptor, os: EelPlatform): EelApi {
return when (os) {
EelPath.OS.UNIX -> EelTestPosixApi(descriptor, fileSystem, fileSystem.fakeLocalRoot)
EelPath.OS.WINDOWS -> EelTestWindowsApi(descriptor, fileSystem, fileSystem.fakeLocalRoot)
is EelPlatform.Posix -> EelTestPosixApi(descriptor, fileSystem, fileSystem.fakeLocalRoot)
is EelPlatform.Windows -> EelTestWindowsApi(descriptor, fileSystem, fileSystem.fakeLocalRoot)
}
}
internal data class IsolatedFileSystemImpl(override val storageRoot: Path, override val eelDescriptor: EelDescriptor, override val eelApi: EelApi) : IsolatedFileSystem
internal fun eelInitializer(os: EelPath.OS): TestFixtureInitializer<IsolatedFileSystem> = TestFixtureInitializer { initialized ->
internal fun eelInitializer(os: EelPlatform): TestFixtureInitializer<IsolatedFileSystem> = TestFixtureInitializer { initialized ->
checkMultiRoutingFileSystem()
val meaningfulDirName = "eel-fixture-${os.name.lowercase()}"
val meaningfulDirName = "eel-fixture-${os.name}"
val directory = Files.createTempDirectory(meaningfulDirName)
val fakeRoot = if (SystemInfo.isUnix) {
@@ -63,7 +68,7 @@ internal fun eelInitializer(os: EelPath.OS): TestFixtureInitializer<IsolatedFile
val fakeLocalFileSystem = EelUnitTestFileSystem(EelUnitTestFileSystemProvider(defaultProvider), os, directory, fakeRoot)
val apiRef = AtomicReference<EelApi>(null)
val descriptor = EelTestDescriptor(Ksuid.generate().toString(), os, apiRef::get)
service.register(fakeRoot, descriptor, descriptor.id, true, (os == EelPath.OS.WINDOWS)) { _, _ ->
service.register(fakeRoot, descriptor, descriptor.id, true, (os is EelPlatform.Windows)) { _, _ ->
fakeLocalFileSystem
}
val eelApi = eelApiByOs(fakeLocalFileSystem, descriptor, os)

View File

@@ -2,6 +2,7 @@
package com.intellij.platform.testFramework.junit5.eel.showcase
import com.intellij.openapi.util.io.OSAgnosticPathUtil
import com.intellij.platform.eel.EelPlatform
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.provider.asEelPath
import com.intellij.platform.eel.provider.asNioPath
@@ -19,13 +20,13 @@ import java.nio.file.Path
@TestApplication
class EelFsShowcase {
val fsAndEelUnix: TestFixture<IsolatedFileSystem> = eelFixture(EelPath.OS.UNIX)
val fsAndEelUnix: TestFixture<IsolatedFileSystem> = eelFixture(EelPlatform.Linux(EelPlatform.Arch.Unknown))
val fsAndEelWindows: TestFixture<IsolatedFileSystem> = eelFixture(EelPath.OS.WINDOWS)
val fsAndEelWindows: TestFixture<IsolatedFileSystem> = eelFixture(EelPlatform.Windows(EelPlatform.Arch.Unknown))
fun EelPath.OS.osDependentFixture(): TestFixture<IsolatedFileSystem> = when (this) {
EelPath.OS.WINDOWS -> fsAndEelWindows
EelPath.OS.UNIX -> fsAndEelUnix
fun EelPlatform.osDependentFixture(): TestFixture<IsolatedFileSystem> = when (this) {
is EelPlatform.Windows -> fsAndEelWindows
is EelPlatform.Posix -> fsAndEelUnix
}
@Test
@@ -59,15 +60,16 @@ class EelFsShowcase {
Assertions.assertEquals(eelNio, eelNioEel)
}
@ParameterizedTest
@EnumSource(EelPath.OS::class)
fun `uri validity`(os: EelPath.OS) {
val root = os.osDependentFixture().get().storageRoot
val path = root.resolve("a/b/c/d/e")
val uri = EelPathUtils.getUriLocalToEel(path)
Assertions.assertEquals("file", uri.scheme)
Assertions.assertNull(uri.authority)
Assertions.assertTrue(uri.path.contains("a/b/c/d/e"))
@Test
fun `uri validity`() {
for (eel in listOf(fsAndEelUnix, fsAndEelWindows)) {
val root = eel.get().storageRoot
val path = root.resolve("a/b/c/d/e")
val uri = EelPathUtils.getUriLocalToEel(path)
Assertions.assertEquals("file", uri.scheme)
Assertions.assertNull(uri.authority)
Assertions.assertTrue(uri.path.contains("a/b/c/d/e"))
}
}
@Test

View File

@@ -1,6 +1,7 @@
// 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.testFramework.junit5.eel.showcase
import com.intellij.platform.eel.EelPlatform
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.provider.asEelPath
import com.intellij.platform.eel.provider.utils.EelPathUtils
@@ -14,7 +15,7 @@ import java.nio.file.Path
@TestApplication
class EelProjectShowcase {
val eel = eelFixture(EelPath.OS.UNIX)
val eel = eelFixture(EelPlatform.Linux(EelPlatform.Arch.Unknown))
val tempDir = eel.tempDirFixture()
val project = projectFixture(tempDir, openAfterCreation = true)

View File

@@ -6,6 +6,7 @@ import com.intellij.openapi.application.edtWriteAction
import com.intellij.openapi.components.service
import com.intellij.openapi.util.registry.Registry
import com.intellij.platform.backend.workspace.GlobalWorkspaceModelCache
import com.intellij.platform.eel.EelPlatform
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.provider.getEelDescriptor
import com.intellij.platform.testFramework.junit5.eel.fixture.eelFixture
@@ -25,7 +26,7 @@ import org.junit.jupiter.api.Test
@TestApplication
class GlobalWorkspaceModelEelTest {
val eel = eelFixture(EelPath.OS.UNIX)
val eel = eelFixture(EelPlatform.Linux(EelPlatform.Arch.Unknown))
val eelTempDir = eel.tempDirFixture()
val eelProject = projectFixture(eelTempDir)

View File

@@ -26,6 +26,7 @@ import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskType
import com.intellij.openapi.externalSystem.service.execution.ExternalSystemRunConfigurationViewManager
import com.intellij.platform.eel.EelApi
import com.intellij.platform.eel.EelExecApi.Pty
import com.intellij.platform.eel.EelPlatform
import com.intellij.platform.eel.EelResult
import com.intellij.platform.eel.execute
import com.intellij.platform.eel.path.EelPath
@@ -321,7 +322,7 @@ class MavenShCommandLineState(val environment: ExecutionEnvironment, private val
}
private fun isWindows() =
myConfiguration.project.getEelDescriptor().operatingSystem == EelPath.OS.WINDOWS
myConfiguration.project.getEelDescriptor().platform is EelPlatform.Windows
private fun isWrapperedOutput(): Boolean {
val mavenDistribution = MavenDistributionsCache.getInstance(myConfiguration.project).getMavenDistribution(myConfiguration.runnerParameters.workingDirPath)

View File

@@ -10,6 +10,7 @@ import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.platform.eel.EelPlatform
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.provider.LocalEelDescriptor
import com.intellij.platform.eel.provider.getEelDescriptor
@@ -113,7 +114,7 @@ internal class MavenWrapperSupport {
throw IllegalStateException(SyncBundle.message("zip.is.not.correct", zipFile.toAbsolutePath()))
}
val mavenHome = dirs[0]
if (mavenHome.getEelDescriptor().operatingSystem == EelPath.OS.UNIX) {
if (mavenHome.getEelDescriptor().platform is EelPlatform.Posix) {
makeMavenBinRunnable(mavenHome)
}
return mavenHome

View File

@@ -13,7 +13,7 @@ import com.intellij.openapi.util.text.HtmlChunk
import com.intellij.openapi.util.text.StringUtil
import com.intellij.platform.eel.EelDescriptor
import com.intellij.platform.eel.path.EelPath.Companion.parse
import com.intellij.platform.eel.path.pathSeparator
import com.intellij.platform.eel.pathSeparator
import com.intellij.platform.eel.provider.asNioPath
import com.intellij.platform.eel.provider.getEelDescriptor
import com.intellij.platform.eel.where
@@ -100,7 +100,7 @@ internal class ShDocumentationProvider(private val scope: CoroutineScope) : Docu
val path = eel.exec.fetchLoginShellEnvVariables()["PATH"]
if (path != null) {
for (dir in StringUtil.tokenize(path, eelDescriptor.operatingSystem.pathSeparator)) {
for (dir in StringUtil.tokenize(path, eelDescriptor.platform.pathSeparator)) {
val eelDir = runCatching { parse(dir, eelDescriptor) }.getOrNull() ?: continue
val file = eelDir.resolve("info").asNioPath()

View File

@@ -17,7 +17,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.platform.eel.EelDescriptor;
import com.intellij.platform.eel.path.EelPath;
import com.intellij.platform.eel.EelPlatform;
import com.intellij.platform.eel.provider.EelNioBridgeServiceKt;
import com.intellij.platform.eel.provider.LocalEelDescriptor;
import com.intellij.sh.ShBundle;
@@ -217,7 +217,7 @@ final class ShRunConfigurationProfileState implements RunProfileState {
@NotNull EelDescriptor eelDescriptor) {
systemDependentPath = convertPathUsingEel(systemDependentPath, eelDescriptor);
if (eelDescriptor.getOperatingSystem() != EelPath.OS.WINDOWS) return ShStringUtil.quote(systemDependentPath);
if (!(eelDescriptor.getPlatform() instanceof EelPlatform.Windows)) return ShStringUtil.quote(systemDependentPath);
String escapedPath = StringUtil.escapeQuotes(systemDependentPath);
return StringUtil.containsWhitespaces(systemDependentPath) ? StringUtil.QUOTER.apply(escapedPath) : escapedPath;
}

View File

@@ -14,7 +14,7 @@ import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.impl.wsl.WslConstants;
import com.intellij.platform.eel.EelDescriptor;
import com.intellij.platform.eel.path.EelPath;
import com.intellij.platform.eel.EelPlatform;
import com.intellij.platform.eel.provider.EelProviderUtil;
import com.intellij.platform.eel.provider.LocalEelDescriptor;
import com.intellij.platform.eel.provider.utils.EelUtilsKt;
@@ -115,7 +115,7 @@ public final class LocalOptionsConfigurer {
@NotNull String workingDir,
@NotNull Project project,
@Nullable EelDescriptor eelDescriptor) {
final var isWindows = eelDescriptor != null ? eelDescriptor.getOperatingSystem() == EelPath.OS.WINDOWS : SystemInfo.isWindows;
final var isWindows = eelDescriptor != null ? eelDescriptor.getPlatform() instanceof EelPlatform.Windows : SystemInfo.isWindows;
Map<String, String> envs = isWindows ? CollectionFactory.createCaseInsensitiveStringMap() : new HashMap<>();
EnvironmentVariablesData envData = TerminalProjectOptionsProvider.getInstance(project).getEnvData();

View File

@@ -1,6 +1,7 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.python.junit5Tests.framework
import com.intellij.platform.eel.EelPlatform
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.provider.getEelDescriptor
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread
@@ -33,9 +34,9 @@ suspend fun waitNoError(delay: Duration = 100.milliseconds, repeat: Int = 50, ch
}
@RequiresBackgroundThread
fun PythonHomePath.resolvePythonTool(name: String): Path = when (getEelDescriptor().operatingSystem) {
EelPath.OS.WINDOWS -> resolve("Scripts/$name.exe")
EelPath.OS.UNIX -> resolve("bin/$name")
fun PythonHomePath.resolvePythonTool(name: String): Path = when (getEelDescriptor().platform) {
is EelPlatform.Windows -> resolve("Scripts/$name.exe")
is EelPlatform.Posix-> resolve("bin/$name")
}
@@ -53,12 +54,12 @@ private class PathMatcher(private val parent: Path) : TypeSafeMatcher<Path>(Path
private fun Path.expandWinPath(): Path =
try {
when (getEelDescriptor().operatingSystem) {
when (getEelDescriptor().platform) {
// On Windows we change 8.3 problem (c:\users\William.~1 -> c:\users\William.Gates)
// But you are encountered to disable 8.3 with `fsutil 8dot3name set 1`
EelPath.OS.WINDOWS -> toRealPath()
is EelPlatform.Windows -> toRealPath()
// On Unix, this function resolves symlinks (i.e `~/.venv/python` -> `/usr/bin/python`) which isn't what we want.
EelPath.OS.UNIX -> this
is EelPlatform.Posix -> this
}
toRealPath()
}

View File

@@ -1,6 +1,7 @@
package com.jetbrains.python
import com.intellij.openapi.util.NlsSafe
import com.intellij.platform.eel.EelPlatform
import com.intellij.platform.eel.getOr
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.provider.getEelDescriptor
@@ -63,12 +64,12 @@ private suspend fun PythonBinary.executeWithResult(vararg args: String): Result<
}
@RequiresBackgroundThread
fun PythonBinary.resolvePythonHome(): PythonHomePath = when (getEelDescriptor().operatingSystem) {
EelPath.OS.WINDOWS -> parent.takeIf { it.name.lowercase() != "scripts" } ?: parent.parent
EelPath.OS.UNIX -> parent.takeIf { it.name != "bin" } ?: parent.parent
fun PythonBinary.resolvePythonHome(): PythonHomePath = when (getEelDescriptor().platform) {
is EelPlatform.Windows -> parent.takeIf { it.name.lowercase() != "scripts" } ?: parent.parent
is EelPlatform.Posix -> parent.takeIf { it.name != "bin" } ?: parent.parent
}
@RequiresBackgroundThread
fun PythonHomePath.resolvePythonBinary(): PythonBinary? {
return VirtualEnvReader(isWindows = getEelDescriptor().operatingSystem == EelPath.OS.WINDOWS).findPythonInPythonRoot(this)
return VirtualEnvReader(isWindows = getEelDescriptor().platform is EelPlatform.Windows).findPythonInPythonRoot(this)
}

View File

@@ -1,8 +1,7 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.python.community.services.internal.impl
import com.intellij.platform.eel.fs.pathOs
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.EelPlatform
import com.intellij.platform.eel.provider.asNioPath
import com.intellij.platform.eel.provider.getEelDescriptor
import com.intellij.python.community.services.internal.impl.PythonWithLanguageLevelImpl.Companion.concurrentLimit
@@ -72,9 +71,9 @@ class PythonWithLanguageLevelImpl internal constructor(
override suspend fun getReadableName(): @Nls String {
val eelApi = pythonBinary.getEelDescriptor().upgrade()
val home = eelApi.userInfo.home.asNioPath()
val separator = when (eelApi.fs.pathOs) {
EelPath.OS.WINDOWS -> "\\"
EelPath.OS.UNIX -> "/"
val separator = when (eelApi.platform) {
is EelPlatform.Windows -> "\\"
is EelPlatform.Posix -> "/"
}
val pythonString = (if (pythonBinary.startsWith(home)) "~$separator" + pythonBinary.relativeTo(home).pathString
else pythonBinary.pathString)