[eel] generalize all eel result types into a single EelResult

Motivation:
	1.	Allows removing identical "unwrap" functions for each result type
	2.	Makes it easier to add helper functions

GitOrigin-RevId: fd05408f6c756b3220120c87c8738df45573b008
This commit is contained in:
Andrii Zinchenko
2024-09-30 16:17:50 +02:00
committed by intellij-monorepo-bot
parent 775a1655e0
commit ad808e267e
24 changed files with 208 additions and 214 deletions

View File

@@ -17,7 +17,7 @@ interface EelExecApi {
*
* See [executeProcessBuilder]
*/
suspend fun execute(builder: ExecuteProcessBuilder): ExecuteProcessResult
suspend fun execute(builder: ExecuteProcessBuilder): EelResult<EelProcess, ExecuteProcessError>
/** Docs: [executeProcessBuilder] */
interface ExecuteProcessBuilder {
@@ -63,9 +63,9 @@ interface EelExecApi {
*/
suspend fun fetchLoginShellEnvVariables(): Map<String, String>
sealed interface ExecuteProcessResult {
class Success(val process: EelProcess) : ExecuteProcessResult
data class Failure(val errno: Int, val message: String) : ExecuteProcessResult
interface ExecuteProcessError {
val errno: Int
val message: String
}
/** [echo] must be true in general and must be false when the user is asked for a password. */
@@ -73,7 +73,7 @@ interface EelExecApi {
}
/** Docs: [EelExecApi.executeProcessBuilder] */
suspend fun EelExecApi.executeProcess(exe: String, vararg args: String): EelExecApi.ExecuteProcessResult =
suspend fun EelExecApi.executeProcess(exe: String, vararg args: String): EelResult<EelProcess, EelExecApi.ExecuteProcessError> =
execute(EelExecApi.executeProcessBuilder(exe).args(listOf(*args)))
/** Docs: [EelExecApi.executeProcessBuilder] */

View File

@@ -0,0 +1,22 @@
// 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
sealed interface EelResult<out P, out E> {
interface Ok<out P, out E> : EelResult<P, E> {
val value: P
}
interface Error<out P, out E> : EelResult<P, E> {
val error: E
}
}
inline fun <T, E> EelResult<T, E>.getOrThrow(action: (E) -> Nothing = { throw RuntimeException(it.toString()) }): T = when (this) {
is EelResult.Ok -> this.value
is EelResult.Error -> action(this.error)
}
fun <T, E> EelResult<T, E>.getOrNull(): T? = when (this) {
is EelResult.Ok -> this.value
is EelResult.Error -> null
}

View File

@@ -2,7 +2,6 @@
package com.intellij.platform.eel
import com.intellij.platform.eel.EelTunnelsApi.Connection
import com.intellij.platform.eel.impl.IpProtocolPreferenceImpl
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.ReceiveChannel
import kotlinx.coroutines.channels.SendChannel
@@ -36,7 +35,7 @@ sealed interface EelTunnelsApi {
*
* One should not forget to invoke [Connection.close] when the connection is not needed.
*/
suspend fun getConnectionToRemotePort(address: HostAddress): EelNetworkResult<Connection, EelConnectionError>
suspend fun getConnectionToRemotePort(address: HostAddress): EelResult<Connection, EelConnectionError>
/**
* Creates a builder for address on the remote host.
@@ -204,7 +203,7 @@ sealed interface EelTunnelsApi {
*
* One should not forget to invoke [Connection.close] when the connection is not needed.
*/
suspend fun getAcceptorForRemotePort(address: HostAddress): EelNetworkResult<ConnectionAcceptor, EelConnectionError>
suspend fun getAcceptorForRemotePort(address: HostAddress): EelResult<ConnectionAcceptor, EelConnectionError>
/**
* This is a representation of a remote server bound to [boundAddress].
@@ -311,8 +310,8 @@ suspend fun <T> EelTunnelsApi.withConnectionToRemotePort(
action: suspend CoroutineScope.(Connection) -> T,
): T =
when (val connectionResult = getConnectionToRemotePort(hostAddress)) {
is EelNetworkResult.Error -> errorHandler(connectionResult.error)
is EelNetworkResult.Ok -> closeWithExceptionHandling({ action(connectionResult.value) }, { connectionResult.value.close() })
is EelResult.Error -> errorHandler(connectionResult.error)
is EelResult.Ok -> closeWithExceptionHandling({ action(connectionResult.value) }, { connectionResult.value.close() })
}
private suspend fun <T> closeWithExceptionHandling(action: suspend CoroutineScope.() -> T, close: suspend () -> Unit): T {
@@ -360,8 +359,8 @@ suspend fun <T> EelTunnelsApi.withAcceptorForRemotePort(
action: suspend CoroutineScope.(EelTunnelsApi.ConnectionAcceptor) -> T,
): T =
when (val connectionResult = getAcceptorForRemotePort(hostAddress)) {
is EelNetworkResult.Error -> errorHandler(connectionResult.error)
is EelNetworkResult.Ok -> closeWithExceptionHandling({ action(connectionResult.value) }, { connectionResult.value.close() })
is EelResult.Error -> errorHandler(connectionResult.error)
is EelResult.Ok -> closeWithExceptionHandling({ action(connectionResult.value) }, { connectionResult.value.close() })
}
/**
@@ -369,25 +368,6 @@ suspend fun <T> EelTunnelsApi.withAcceptorForRemotePort(
*/
sealed interface EelNetworkError
/**
* Represents a result of a network operation
*/
sealed interface EelNetworkResult<out T, out E : EelNetworkError> {
/**
* Used when a network operation completed successfully
*/
interface Ok<out T> : EelNetworkResult<T, Nothing> {
val value: T
}
/**
* Used when a network operation completed with an error
*/
interface Error<out E : EelNetworkError> : EelNetworkResult<Nothing, E> {
val error: E
}
}
/**
* An error that can happen during the creation of a connection to a remote server
*/

View File

@@ -1,15 +1,16 @@
// 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 com.intellij.platform.eel.EelResult
import com.intellij.platform.eel.EelUserInfo
import com.intellij.platform.eel.EelUserPosixInfo
import com.intellij.platform.eel.EelUserWindowsInfo
import com.intellij.platform.eel.fs.EelFileSystemApi.StatError
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.path.EelPathResult
import com.intellij.platform.eel.path.EelPathError
import java.nio.ByteBuffer
fun EelFileSystemApi.getPath(string: String, vararg other: String): EelPathResult<out EelPath.Absolute> {
fun EelFileSystemApi.getPath(string: String, vararg other: String): EelResult<out EelPath.Absolute, EelPathError> {
return EelPath.Absolute.build(listOf(string, *other), when (this) {
is EelFileSystemPosixApi -> EelPath.Absolute.OS.UNIX
is EelFileSystemWindowsApi -> EelPath.Absolute.OS.WINDOWS
@@ -37,7 +38,7 @@ interface EelFileSystemApi {
/**
* Returns names of files in a directory. If [path] is a symlink, it will be resolved, but no symlinks are resolved among children.
*/
suspend fun listDirectory(path: EelPath.Absolute): EelFsResult<
suspend fun listDirectory(path: EelPath.Absolute): EelResult<
Collection<String>,
ListDirectoryError>
@@ -52,7 +53,7 @@ interface EelFileSystemApi {
suspend fun listDirectoryWithAttrs(
path: EelPath.Absolute,
symlinkPolicy: SymlinkPolicy,
): EelFsResult<
): EelResult<
Collection<Pair<String, EelFileInfo>>,
ListDirectoryError>
@@ -67,7 +68,7 @@ interface EelFileSystemApi {
/**
* Resolves all symlinks in the path. Corresponds to realpath(3) on Unix and GetFinalPathNameByHandle on Windows.
*/
suspend fun canonicalize(path: EelPath.Absolute): EelFsResult<
suspend fun canonicalize(path: EelPath.Absolute): EelResult<
EelPath.Absolute,
CanonicalizeError>
@@ -82,7 +83,7 @@ interface EelFileSystemApi {
/**
* Similar to stat(2) and lstat(2). [symlinkPolicy] has an impact only on [EelFileInfo.type] if [path] points on a symlink.
*/
suspend fun stat(path: EelPath.Absolute, symlinkPolicy: SymlinkPolicy): EelFsResult<EelFileInfo, StatError>
suspend fun stat(path: EelPath.Absolute, symlinkPolicy: SymlinkPolicy): EelResult<EelFileInfo, StatError>
/**
* Defines the behavior of FS operations on symbolic links
@@ -118,7 +119,7 @@ interface EelFileSystemApi {
* On Unix return true if both paths have the same inode.
* On Windows some heuristics are used, for more details see https://docs.rs/same-file/1.0.6/same_file/
*/
suspend fun sameFile(source: EelPath.Absolute, target: EelPath.Absolute): EelFsResult<
suspend fun sameFile(source: EelPath.Absolute, target: EelPath.Absolute): EelResult<
Boolean,
SameFileError>
@@ -133,7 +134,7 @@ interface EelFileSystemApi {
/**
* Opens the file only for reading
*/
suspend fun openForReading(path: EelPath.Absolute): EelFsResult<
suspend fun openForReading(path: EelPath.Absolute): EelResult<
EelOpenedFile.Reader,
FileReaderError>
@@ -151,7 +152,7 @@ interface EelFileSystemApi {
*/
suspend fun openForWriting(
options: WriteOptions,
): EelFsResult<
): EelResult<
EelOpenedFile.Writer,
FileWriterError>
@@ -193,7 +194,7 @@ interface EelFileSystemApi {
interface Other : FileWriterError, EelFsError.Other
}
suspend fun openForReadingAndWriting(options: WriteOptions): EelFsResult<EelOpenedFile.ReaderWriter, FileWriterError>
suspend fun openForReadingAndWriting(options: WriteOptions): EelResult<EelOpenedFile.ReaderWriter, FileWriterError>
@Throws(DeleteException::class)
suspend fun delete(path: EelPath.Absolute, removeContent: Boolean)
@@ -297,7 +298,7 @@ sealed interface EelOpenedFile {
: CloseException(where, additionalMessage), EelFsError.Other
}
suspend fun tell(): EelFsResult<
suspend fun tell(): EelResult<
Long,
TellError>
@@ -305,7 +306,7 @@ sealed interface EelOpenedFile {
interface Other : TellError, EelFsError.Other
}
suspend fun seek(offset: Long, whence: SeekWhence): EelFsResult<
suspend fun seek(offset: Long, whence: SeekWhence): EelResult<
Long,
SeekError>
@@ -325,7 +326,7 @@ sealed interface EelOpenedFile {
* Sometimes, the files are inaccessible via [EelFileSystemApi.stat] -- for example, if they are deleted.
* In this case, one can get the information about the opened file with the use of this function.
*/
suspend fun stat(): EelFsResult<EelFileInfo, StatError>
suspend fun stat(): EelResult<EelFileInfo, StatError>
interface Reader : EelOpenedFile {
@@ -341,7 +342,7 @@ sealed interface EelOpenedFile {
*
* The implementation MAY read less data than the capacity of the buffer even if it's possible to read the whole requested buffer.
*/
suspend fun read(buf: ByteBuffer): EelFsResult<ReadResult, ReadError>
suspend fun read(buf: ByteBuffer): EelResult<ReadResult, ReadError>
/**
* Reads data from the position [offset] of the file.
@@ -350,7 +351,7 @@ sealed interface EelOpenedFile {
*
* The implementation MAY read less than [offset] bytes even if it's possible to read the whole requested buffer.
*/
suspend fun read(buf: ByteBuffer, offset: Long): EelFsResult<ReadResult, ReadError>
suspend fun read(buf: ByteBuffer, offset: Long): EelResult<ReadResult, ReadError>
sealed interface ReadResult {
interface EOF : ReadResult
@@ -372,7 +373,7 @@ sealed interface EelOpenedFile {
*
* The implementation MAY write the part of the [buf] even if it's possible to write the whole buffer.
*/
suspend fun write(buf: ByteBuffer): EelFsResult<
suspend fun write(buf: ByteBuffer): EelResult<
Int,
WriteError>
@@ -381,7 +382,7 @@ sealed interface EelOpenedFile {
*
* The implementation MAY write the part of the [buf] even if it's possible to write the whole buffer.
*/
suspend fun write(buf: ByteBuffer, pos: Long): EelFsResult<
suspend fun write(buf: ByteBuffer, pos: Long): EelResult<
Int,
WriteError>
@@ -459,11 +460,11 @@ interface EelFileSystemPosixApi : EelFileSystemApi {
override suspend fun listDirectoryWithAttrs(
path: EelPath.Absolute,
symlinkPolicy: EelFileSystemApi.SymlinkPolicy,
): EelFsResult<
): EelResult<
Collection<Pair<String, EelPosixFileInfo>>,
EelFileSystemApi.ListDirectoryError>
override suspend fun stat(path: EelPath.Absolute, symlinkPolicy: EelFileSystemApi.SymlinkPolicy): EelFsResult<
override suspend fun stat(path: EelPath.Absolute, symlinkPolicy: EelFileSystemApi.SymlinkPolicy): EelResult<
EelPosixFileInfo,
StatError>
@@ -528,11 +529,11 @@ interface EelFileSystemWindowsApi : EelFileSystemApi {
override suspend fun listDirectoryWithAttrs(
path: EelPath.Absolute,
symlinkPolicy: EelFileSystemApi.SymlinkPolicy,
): EelFsResult<
): EelResult<
Collection<Pair<String, EelWindowsFileInfo>>,
EelFileSystemApi.ListDirectoryError>
override suspend fun stat(path: EelPath.Absolute, symlinkPolicy: EelFileSystemApi.SymlinkPolicy): EelFsResult<
override suspend fun stat(path: EelPath.Absolute, symlinkPolicy: EelFileSystemApi.SymlinkPolicy): EelResult<
EelWindowsFileInfo,
StatError>
}

View File

@@ -5,19 +5,6 @@ import com.intellij.platform.eel.path.EelPath
import org.jetbrains.annotations.Nls
import java.io.IOException
/**
* [T] should not be `Unit`, throw a subclass of [EelFsIOException] in such cases instead.
*/
sealed interface EelFsResult<out T, E : EelFsError> {
interface Ok<out T, E : EelFsError> : EelFsResult<T, E> {
val value: T
}
interface Error<T, E : EelFsError> : EelFsResult<T, E> {
val error: E
}
}
sealed interface EelFsError {
val where: EelPath.Absolute

View File

@@ -1,8 +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.eel.path
import com.intellij.platform.eel.path.EelPathResult.Err
import com.intellij.platform.eel.path.EelPathResult.Ok
import com.intellij.platform.eel.EelResult
internal class ArrayListEelAbsolutePath private constructor(
private val _root: Root,
@@ -34,7 +33,7 @@ internal class ArrayListEelAbsolutePath private constructor(
root.fileName == other.root.fileName &&
(0..<other.nameCount).all { getName(it) == other.getName(it) }
override fun normalize(): EelPathResult<out EelPath.Absolute> {
override fun normalize(): EelResult<out EelPath.Absolute, EelPathError> {
val result = mutableListOf<String>()
for (part in parts) {
when (part) {
@@ -42,7 +41,7 @@ internal class ArrayListEelAbsolutePath private constructor(
".." ->
if (result.isEmpty())
return Err(toString(), "Traversing beyond the root")
return ErrorResult(Err(toString(), "Traversing beyond the root"))
else
result.dropLast(1)
@@ -50,28 +49,28 @@ internal class ArrayListEelAbsolutePath private constructor(
result += part
}
}
return Ok(ArrayListEelAbsolutePath(_root, result))
return OkResult(ArrayListEelAbsolutePath(_root, result))
}
override fun resolve(other: EelPath.Relative): EelPathResult<out EelPath.Absolute> {
override fun resolve(other: EelPath.Relative): EelResult<out EelPath.Absolute, EelPathError> {
val result = parts.toMutableList()
for (index in 0..<other.nameCount) {
val name = other.getName(index).fileName
if (name.isNotEmpty()) {
val error = checkFileName(name)
if (error != null) return Err(other.toString(), error)
if (error != null) return ErrorResult(Err(other.toString(), error))
result += name
}
}
return Ok(ArrayListEelAbsolutePath(_root, result))
return OkResult(ArrayListEelAbsolutePath(_root, result))
}
override fun getChild(name: String): EelPathResult<out EelPath.Absolute> {
override fun getChild(name: String): EelResult<out EelPath.Absolute, EelPathError> {
val error = checkFileName(name)
return if (error == null)
Ok(ArrayListEelAbsolutePath(_root, parts + name))
OkResult(ArrayListEelAbsolutePath(_root, parts + name))
else
Err(name, error)
ErrorResult(Err(name, error))
}
override fun scan(): Sequence<EelPath.Absolute> =
@@ -131,9 +130,9 @@ internal class ArrayListEelAbsolutePath private constructor(
return nameCount - other.nameCount
}
override fun relativize(other: EelPath.Absolute): EelPathResult<out EelPath.Relative> {
override fun relativize(other: EelPath.Absolute): EelResult<out EelPath.Relative, EelPathError> {
if (root != other.root) {
return Err(other.root.toString(), "The other path has a different root")
return ErrorResult(Err(other.root.toString(), "The other path has a different root"))
}
var firstDifferenceIndex = 0
@@ -171,7 +170,7 @@ internal class ArrayListEelAbsolutePath private constructor(
})
companion object {
fun build(parts: List<String>, os: EelPath.Absolute.OS?): EelPathResult<out EelPath.Absolute> {
fun build(parts: List<String>, os: EelPath.Absolute.OS?): EelResult<out EelPath.Absolute, EelPathError> {
require(parts.isNotEmpty()) { "Can't build an absolute path from no path parts" }
val windowsRoot = when (os) {
@@ -190,44 +189,44 @@ internal class ArrayListEelAbsolutePath private constructor(
else parts
for (part in parts) {
val error = checkFileName(part, isWindows = false)
if (error != null) return Err(part, error)
if (error != null) return ErrorResult(Err(part, error))
}
return Ok(ArrayListEelAbsolutePath(Root.Unix, parts))
return OkResult(ArrayListEelAbsolutePath(Root.Unix, parts))
}
is Ok -> {
is EelResult.Ok -> {
@Suppress("NAME_SHADOWING") val parts = parts.drop(1)
for (part in parts) {
val error = checkFileName(part, isWindows = true)
if (error != null) return Err(part, error)
if (error != null) return ErrorResult(Err(part, error))
}
return Ok(ArrayListEelAbsolutePath(windowsRoot.path._root, parts))
return OkResult(ArrayListEelAbsolutePath(windowsRoot.value._root, parts))
}
is Err -> return windowsRoot
is EelResult.Error -> return windowsRoot
}
}
fun parse(raw: String, os: EelPath.Absolute.OS?): EelPathResult<ArrayListEelAbsolutePath> =
fun parse(raw: String, os: EelPath.Absolute.OS?): EelResult<ArrayListEelAbsolutePath, EelPathError> =
when (os) {
EelPath.Absolute.OS.WINDOWS ->
findAbsoluteUncPath(raw)
?: findAbsoluteTraditionalDosPath(raw)
?: reportError(raw)
?: ErrorResult(createErr(raw))
EelPath.Absolute.OS.UNIX ->
findAbsoluteUnixPath(raw)
?: reportError(raw)
?: ErrorResult(createErr(raw))
null ->
findAbsoluteUncPath(raw)
?: findAbsoluteTraditionalDosPath(raw)
?: findAbsoluteUnixPath(raw)
?: reportError(raw)
?: ErrorResult(createErr(raw))
}
/** https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#unc-paths */
private fun findAbsoluteUncPath(raw: String): EelPathResult<ArrayListEelAbsolutePath>? {
private fun findAbsoluteUncPath(raw: String): EelResult<ArrayListEelAbsolutePath, EelPathError>? {
if (raw.length < 3) return null
if (raw.getOrNull(0) != raw.getOrNull(1)) return null
@@ -239,12 +238,12 @@ internal class ArrayListEelAbsolutePath private constructor(
run {
val error = checkFileName(raw.substring(2, index), isWindows = true)
if (error != null) return Err(raw, "Incorrect server name in UNC path")
if (error != null) return ErrorResult(Err(raw, "Incorrect server name in UNC path"))
}
val shareNameStart = index
if (++index == raw.length) return Err(raw, "Empty share name in UNC path")
if (++index == raw.length) return ErrorResult(Err(raw, "Empty share name in UNC path"))
// Skipping the server/host name.
while (raw[index] !in "/\\") {
@@ -253,7 +252,7 @@ internal class ArrayListEelAbsolutePath private constructor(
run {
val error = checkFileName(raw.substring(shareNameStart, index), isWindows = true)
if (error != null) return Err(raw, "Incorrect share name in UNC path")
if (error != null) return ErrorResult(Err(raw, "Incorrect share name in UNC path"))
}
val parts = raw.substring(index)
@@ -263,14 +262,14 @@ internal class ArrayListEelAbsolutePath private constructor(
for (part in parts) {
val error = checkFileName(part, isWindows = true)
if (error != null) return Err(raw, error)
if (error != null) return ErrorResult(Err(raw, error))
}
return Ok(ArrayListEelAbsolutePath(Root.Windows(raw.substring(0, index).replace("/", "\\")), parts))
return OkResult(ArrayListEelAbsolutePath(Root.Windows(raw.substring(0, index).replace("/", "\\")), parts))
}
/** https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#traditional-dos-paths */
private fun findAbsoluteTraditionalDosPath(raw: String): EelPathResult<ArrayListEelAbsolutePath>? {
private fun findAbsoluteTraditionalDosPath(raw: String): EelResult<ArrayListEelAbsolutePath, EelPathError>? {
if (raw.length < 3) return null
if (!raw[0].isLetter()) return null
if (raw[1] != ':') return null
@@ -283,13 +282,13 @@ internal class ArrayListEelAbsolutePath private constructor(
for (part in parts) {
val error = checkFileName(part, isWindows = true)
if (error != null) return Err(raw, error)
if (error != null) return ErrorResult(Err(raw, error))
}
return Ok(ArrayListEelAbsolutePath(Root.Windows(raw.substring(0, 3)), parts))
return OkResult(ArrayListEelAbsolutePath(Root.Windows(raw.substring(0, 3)), parts))
}
private fun findAbsoluteUnixPath(raw: String): EelPathResult<ArrayListEelAbsolutePath>? {
private fun findAbsoluteUnixPath(raw: String): EelResult<ArrayListEelAbsolutePath, EelPathError>? {
if (raw.getOrNull(0) != '/') return null
val parts = raw
@@ -299,13 +298,13 @@ internal class ArrayListEelAbsolutePath private constructor(
for (part in parts) {
val error = checkFileName(part, isWindows = false)
if (error != null) return Err(raw, error)
if (error != null) return ErrorResult(Err(raw, error))
}
return Ok(ArrayListEelAbsolutePath(Root.Unix, parts))
return OkResult(ArrayListEelAbsolutePath(Root.Unix, parts))
}
private fun reportError(raw: String): Err<ArrayListEelAbsolutePath> =
private fun createErr(raw: String): Err =
Err(
raw = raw,
reason = run {

View File

@@ -1,6 +1,8 @@
// 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.path
import com.intellij.platform.eel.EelResult
internal class ArrayListEelRelativePath private constructor(
private val parts: List<String>,
) : EelPath.Relative {
@@ -24,7 +26,7 @@ internal class ArrayListEelRelativePath private constructor(
return true
}
override fun resolve(other: EelPath.Relative): EelPathResult<ArrayListEelRelativePath> {
override fun resolve(other: EelPath.Relative): EelResult<ArrayListEelRelativePath, EelPathError> {
val result = mutableListOf<String>()
result += parts
if (other != EMPTY) {
@@ -33,14 +35,14 @@ internal class ArrayListEelRelativePath private constructor(
result += fileName
}
}
return Ok(ArrayListEelRelativePath(result))
return OkResult(ArrayListEelRelativePath(result))
}
override fun getChild(name: String): EelPathResult<ArrayListEelRelativePath> =
override fun getChild(name: String): EelResult<ArrayListEelRelativePath, EelPathError> =
when {
name.isEmpty() -> Err(name, "Empty child name is not allowed")
"/" in name -> Err(name, "Invalid symbol in child name: /")
else -> Ok(ArrayListEelRelativePath(parts + name))
name.isEmpty() -> ErrorResult(Err(name, "Empty child name is not allowed"))
"/" in name -> ErrorResult(Err(name, "Invalid symbol in child name: /"))
else -> OkResult(ArrayListEelRelativePath(parts + name))
}
override fun compareTo(other: EelPath.Relative): Int {
@@ -108,22 +110,22 @@ internal class ArrayListEelRelativePath private constructor(
val EMPTY = ArrayListEelRelativePath(listOf())
private val REGEX = Regex("""[/\\]""")
fun parse(raw: String): EelPathResult<ArrayListEelRelativePath> =
fun parse(raw: String): EelResult<ArrayListEelRelativePath, EelPathError> =
build(raw.splitToSequence(REGEX).filter(String::isNotEmpty).iterator())
fun build(parts: List<String>): EelPathResult<ArrayListEelRelativePath> =
fun build(parts: List<String>): EelResult<ArrayListEelRelativePath, EelPathError> =
build(parts.iterator())
private fun build(parts: Iterator<String>): EelPathResult<ArrayListEelRelativePath> {
private fun build(parts: Iterator<String>): EelResult<ArrayListEelRelativePath, EelPathError> {
// Not optimal, but DRY.
var result = ArrayListEelRelativePath(listOf())
for (part in parts) {
result = when (val r = result.getChild(part)) {
is EelPathResult.Ok -> r.path
is EelPathResult.Err -> return r
is EelResult.Ok -> r.value
is EelResult.Error -> return r
}
}
return Ok(result)
return OkResult(result)
}
}
}

View File

@@ -2,17 +2,14 @@
package com.intellij.platform.eel.path
import com.intellij.platform.eel.EelPlatform
import com.intellij.platform.eel.EelResult
import com.intellij.platform.eel.getOrThrow
import com.intellij.platform.eel.path.EelPath.Absolute.OS
import java.nio.file.InvalidPathException
sealed interface EelPathResult<P : EelPath> {
interface Ok<P : EelPath> : EelPathResult<P> {
val path: P
}
interface Err<P : EelPath> : EelPathResult<P> {
val raw: String
val reason: String
}
interface EelPathError {
val raw: String
val reason: String
}
/**
@@ -26,10 +23,10 @@ sealed interface EelPathResult<P : EelPath> {
sealed interface EelPath {
companion object {
@JvmStatic
fun parse(raw: String, os: OS?): EelPathResult<out EelPath> =
fun parse(raw: String, os: OS?): EelResult<out EelPath, EelPathError> =
when (val absoluteResult = Absolute.parse(raw, os)) {
is EelPathResult.Ok -> absoluteResult
is EelPathResult.Err -> Relative.parse(raw)
is EelResult.Ok -> absoluteResult
is EelResult.Error -> Relative.parse(raw)
}
}
@@ -102,7 +99,7 @@ sealed interface EelPath {
* // TODO Wouldn't it be better to return different types for relative and absolute paths?
* It should fail in cases like Absolute("/").resolve(Relative("..")).
*/
fun resolve(other: Relative): EelPathResult<out EelPath>
fun resolve(other: Relative): EelResult<out EelPath, EelPathError>
/**
* ```kotlin
@@ -114,28 +111,28 @@ sealed interface EelPath {
* IjentRelativePath.parse("abc", false).getChild("") == Err(...)
* ```
*/
fun getChild(name: String): EelPathResult<out EelPath>
fun getChild(name: String): EelResult<out EelPath, EelPathError>
override fun toString(): String
interface Relative : EelPath, Comparable<Relative> {
companion object {
@JvmStatic
fun parse(raw: String): EelPathResult<out Relative> =
fun parse(raw: String): EelResult<out Relative, EelPathError> =
ArrayListEelRelativePath.parse(raw)
/**
* The parts of the path must not contain / or \.
*/
@JvmStatic
fun build(vararg parts: String): EelPathResult<out Relative> =
fun build(vararg parts: String): EelResult<out Relative, EelPathError> =
build(listOf(*parts))
/**
* The parts of the path must not contain / or \.
*/
@JvmStatic
fun build(parts: List<String>): EelPathResult<out Relative> =
fun build(parts: List<String>): EelResult<out Relative, EelPathError> =
ArrayListEelRelativePath.build(parts)
@JvmField
@@ -147,9 +144,9 @@ sealed interface EelPath {
/** See [java.nio.file.Path.startsWith] */
fun startsWith(other: Relative): Boolean
override fun resolve(other: Relative): EelPathResult<out Relative>
override fun resolve(other: Relative): EelResult<out Relative, EelPathError>
override fun getChild(name: String): EelPathResult<out Relative>
override fun getChild(name: String): EelResult<out Relative, EelPathError>
override fun compareTo(other: Relative): Int
@@ -177,15 +174,15 @@ sealed interface EelPath {
interface Absolute : EelPath, Comparable<Absolute> {
companion object {
@JvmStatic
fun parse(raw: String, os: OS?): EelPathResult<out Absolute> =
fun parse(raw: String, os: OS?): EelResult<out Absolute, EelPathError> =
ArrayListEelAbsolutePath.parse(raw, os)
@JvmStatic
fun build(vararg parts: String): EelPathResult<out Absolute> =
fun build(vararg parts: String): EelResult<out Absolute, EelPathError> =
build(listOf(*parts), null)
@JvmStatic
fun build(parts: List<String>, os: OS?): EelPathResult<out Absolute> =
fun build(parts: List<String>, os: OS?): EelResult<out Absolute, EelPathError> =
ArrayListEelAbsolutePath.build(parts, os)
}
@@ -204,10 +201,10 @@ sealed interface EelPath {
fun startsWith(other: Absolute): Boolean
/** See [java.nio.file.Path.normalize] */
fun normalize(): EelPathResult<out Absolute>
fun normalize(): EelResult<out Absolute, EelPathError>
/** See [java.nio.file.Path.resolve] */
override fun resolve(other: Relative): EelPathResult<out Absolute>
override fun resolve(other: Relative): EelResult<out Absolute, EelPathError>
/**
* See [java.nio.file.Path.relativize].
@@ -217,9 +214,9 @@ sealed interface EelPath {
* == IjentPathAbsolute.parse("..\..\oops", isWindows = true)
* ```
*/
fun relativize(other: Absolute): EelPathResult<out Relative>
fun relativize(other: Absolute): EelResult<out Relative, EelPathError>
override fun getChild(name: String): EelPathResult<out Absolute>
override fun getChild(name: String): EelResult<out Absolute, EelPathError>
fun scan(): Sequence<Absolute>
@@ -232,11 +229,7 @@ sealed interface EelPath {
}
@Throws(InvalidPathException::class)
fun <P : EelPath> EelPathResult<P>.getOrThrow(): P =
when (this) {
is EelPathResult.Ok -> path
is EelPathResult.Err -> throw InvalidPathException(raw, reason)
}
fun <P : EelPath, E : EelPathError> EelResult<P, E>.getOrThrow(): P = getOrThrow { throw InvalidPathException(it.raw, it.reason) }
val EelPlatform.pathOs: OS
get() = when (this) {

View File

@@ -2,5 +2,8 @@
@file:JvmName("EelPathResultImpl")
package com.intellij.platform.eel.path
internal data class Ok<P : EelPath>(override val path: P) : EelPathResult.Ok<P>
internal data class Err<P : EelPath>(override val raw: String, override val reason: String) : EelPathResult.Err<P>
import com.intellij.platform.eel.EelResult
internal data class OkResult<P : EelPath>(override val value: P) : EelResult.Ok<P, EelPathError>
internal data class ErrorResult<P : EelPath>(override val error: EelPathError) : EelResult.Error<P, EelPathError>
internal data class Err(override val raw: String, override val reason: String) : EelPathError

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.eel.path
import com.intellij.platform.eel.EelResult
import io.kotest.matchers.shouldBe
import io.kotest.matchers.types.shouldBeInstanceOf
import org.junit.jupiter.api.DynamicTest
@@ -36,8 +37,8 @@ class EelAbsolutePathTest {
add(dynamicTest(rawPath) {
val eelPath = EelPath.Absolute
.parse(rawPath, null)
.shouldBeInstanceOf<EelPathResult.Ok<EelPath.Absolute>>()
.path
.shouldBeInstanceOf<EelResult.Ok<EelPath.Absolute, EelPathError>>()
.value
eelPath.toString() shouldBe rawPath
})
}

View File

@@ -2,6 +2,9 @@
package com.intellij.platform.eel.impl.local
import com.intellij.platform.eel.EelExecApi
import com.intellij.platform.eel.EelProcess
import com.intellij.platform.eel.EelResult
import com.intellij.platform.eel.provider.EelProcessResultImpl
import com.pty4j.PtyProcessBuilder
import org.jetbrains.annotations.ApiStatus
import java.io.File
@@ -9,7 +12,7 @@ import java.io.IOException
@ApiStatus.Internal
class EelLocalExecApi : EelExecApi {
override suspend fun execute(builder: EelExecApi.ExecuteProcessBuilder): EelExecApi.ExecuteProcessResult {
override suspend fun execute(builder: EelExecApi.ExecuteProcessBuilder): EelResult<EelProcess, EelExecApi.ExecuteProcessError> {
val args = builder.args.toTypedArray()
val pty = builder.pty
@@ -35,9 +38,9 @@ class EelLocalExecApi : EelExecApi {
}
}
catch (e: IOException) {
return EelExecApi.ExecuteProcessResult.Failure(-1, e.toString())
return EelProcessResultImpl.createErrorResult(-1, e.toString())
}
return EelExecApi.ExecuteProcessResult.Success(process)
return EelProcessResultImpl.createOkResult(process)
}
override suspend fun fetchLoginShellEnvVariables(): Map<String, String> = System.getenv()

View File

@@ -7,14 +7,14 @@ import com.intellij.platform.eel.fs.EelFileSystemPosixApi
import com.intellij.platform.eel.fs.EelFileSystemWindowsApi
import com.intellij.platform.eel.fs.getPath
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.path.getOrThrow
import com.intellij.platform.eel.provider.EelUserPosixInfoImpl
import com.intellij.platform.eel.provider.EelUserWindowsInfoImpl
import com.intellij.platform.eel.provider.utils.unwrap
import java.nio.file.Path
internal class LocalEelPathMapper(private val eelApi: EelApi) : EelPathMapper {
override fun getOriginalPath(path: Path): EelPath.Absolute {
return eelApi.fs.getPath(path.toString()).unwrap()
return eelApi.fs.getPath(path.toString()).getOrThrow()
}
override fun toNioPath(path: EelPath.Absolute): Path {

View File

@@ -1,16 +1,16 @@
// 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.provider
import com.intellij.platform.eel.EelResult
import com.intellij.platform.eel.fs.EelFileSystemApi
import com.intellij.platform.eel.fs.EelFsError
import com.intellij.platform.eel.fs.EelFsResult
import com.intellij.platform.eel.fs.EelOpenedFile
import com.intellij.platform.eel.path.EelPath
@Suppress("unused") // Usages are to be implemented later.
object EelFsResultImpl {
data class Ok<T, E : EelFsError>(override val value: T) : EelFsResult.Ok<T, E>
data class Error<T, E : EelFsError>(override val error: E) : EelFsResult.Error<T, E>
data class Ok<T, E : EelFsError>(override val value: T) : EelResult.Ok<T, E>
data class Error<T, E : EelFsError>(override val error: E) : EelResult.Error<T, E>
data class BytesReadImpl(override val bytesRead: Int) : EelOpenedFile.Reader.ReadResult.Bytes
data object EOFImpl : EelOpenedFile.Reader.ReadResult.EOF

View File

@@ -0,0 +1,17 @@
// 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.provider
import com.intellij.platform.eel.EelExecApi
import com.intellij.platform.eel.EelProcess
import com.intellij.platform.eel.EelResult
import org.jetbrains.annotations.ApiStatus.Internal
@Internal
object EelProcessResultImpl {
private data class Ok(override val value: EelProcess) : EelResult.Ok<EelProcess, EelExecApi.ExecuteProcessError>
private data class Error(override val error: EelExecApi.ExecuteProcessError) : EelResult.Error<EelProcess, EelExecApi.ExecuteProcessError>
private data class ExecuteProcessError(override val errno: Int, override val message: String) : EelExecApi.ExecuteProcessError
fun createOkResult(process: EelProcess): EelResult.Ok<EelProcess, EelExecApi.ExecuteProcessError> = Ok(process)
fun createErrorResult(errno: Int, message: String): EelResult.Error<EelProcess, EelExecApi.ExecuteProcessError> = Error(ExecuteProcessError(errno, message))
}

View File

@@ -4,14 +4,6 @@ package com.intellij.platform.eel.provider.utils
import com.intellij.openapi.progress.runBlockingMaybeCancellable
import com.intellij.platform.eel.fs.EelFileSystemApi
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.path.EelPathResult
fun <T : EelPath> EelPathResult<T>.unwrap(): T {
return when (this) {
is EelPathResult.Ok -> path
is EelPathResult.Err -> throw RuntimeException(reason)
}
}
fun EelFileSystemApi.userHomeBlocking(): EelPath.Absolute? {
return runBlockingMaybeCancellable {

View File

@@ -5,27 +5,13 @@ import com.intellij.execution.process.ProcessOutput
import com.intellij.platform.eel.*
import com.intellij.platform.eel.fs.getPath
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.path.getOrThrow
import com.intellij.util.io.computeDetached
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.channels.consumeEach
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import java.io.ByteArrayOutputStream
import java.io.IOException
/**
* Unwraps the `ExecuteProcessResult` instance, returning the underlying `EelProcess` if the result is a success,
* or throws an `IOException` if the result is a failure.
*
* @throws IOException if the `ExecuteProcessResult` is `Failure`.
* @return the `EelProcess` if the `ExecuteProcessResult` is `Success`.
*/
fun EelExecApi.ExecuteProcessResult.unwrap(): EelProcess {
return when (this) {
is EelExecApi.ExecuteProcessResult.Success -> process
is EelExecApi.ExecuteProcessResult.Failure -> throw RuntimeException(toString())
}
}
/**
* Function that awaits the completion of an [EelProcess] and retrieves its execution result,
@@ -92,13 +78,13 @@ suspend fun EelApi.where(exe: String): EelPath.Absolute? {
else -> throw IllegalArgumentException("Unsupported OS: $this")
}
val result = exec.executeProcess(tool, exe).unwrap().awaitProcessResult()
val result = exec.executeProcess(tool, exe).getOrThrow().awaitProcessResult()
if (result.exitCode != 0) {
// TODO: log error?/throw Exception?
return null
}
else {
return fs.getPath(result.stdout).unwrap()
return fs.getPath(result.stdout).getOrThrow()
}
}

View File

@@ -14,7 +14,7 @@ import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.diagnostic.runAndLogException
import com.intellij.openapi.project.DumbAwareAction
import com.intellij.openapi.ui.Messages
import com.intellij.platform.eel.EelExecApi
import com.intellij.platform.eel.EelResult
import com.intellij.platform.eel.executeProcess
import com.intellij.platform.ide.progress.ModalTaskOwner
import com.intellij.platform.ide.progress.TaskCancellation
@@ -77,8 +77,8 @@ abstract class AbstractIjentVerificationAction : DumbAwareAction() {
launch {
val process = when (val p = ijent.exec.executeProcess("uname", "-a")) {
is EelExecApi.ExecuteProcessResult.Failure -> error(p)
is EelExecApi.ExecuteProcessResult.Success -> p.process
is EelResult.Error -> error(p)
is EelResult.Ok -> p.value
}
val stdout = ByteArrayOutputStream()
process.stdout.consumeEach(stdout::write)

View File

@@ -1,8 +1,12 @@
// 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
import com.intellij.platform.eel.EelResult
import com.intellij.platform.eel.EelUserPosixInfo
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
import com.intellij.platform.eel.fs.EelPosixFileInfo
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.ijent.IjentApi
import com.intellij.platform.ijent.IjentPosixApi
@@ -104,7 +108,7 @@ private class IjentFailSafeFileSystemPosixApiImpl(
override suspend fun listDirectory(
path: EelPath.Absolute,
): EelFsResult<Collection<String>, EelFileSystemApi.ListDirectoryError> =
): EelResult<Collection<String>, EelFileSystemApi.ListDirectoryError> =
holder.withDelegateRetrying {
listDirectory(path)
}
@@ -121,7 +125,7 @@ private class IjentFailSafeFileSystemPosixApiImpl(
override suspend fun listDirectoryWithAttrs(
path: EelPath.Absolute,
symlinkPolicy: EelFileSystemApi.SymlinkPolicy,
): EelFsResult<Collection<Pair<String, EelPosixFileInfo>>, EelFileSystemApi.ListDirectoryError> {
): EelResult<Collection<Pair<String, EelPosixFileInfo>>, EelFileSystemApi.ListDirectoryError> {
return holder.withDelegateRetrying {
listDirectoryWithAttrs(path, symlinkPolicy)
}
@@ -129,7 +133,7 @@ private class IjentFailSafeFileSystemPosixApiImpl(
override suspend fun canonicalize(
path: EelPath.Absolute,
): EelFsResult<EelPath.Absolute, EelFileSystemApi.CanonicalizeError> =
): EelResult<EelPath.Absolute, EelFileSystemApi.CanonicalizeError> =
holder.withDelegateRetrying {
canonicalize(path)
}
@@ -137,7 +141,7 @@ private class IjentFailSafeFileSystemPosixApiImpl(
override suspend fun stat(
path: EelPath.Absolute,
symlinkPolicy: EelFileSystemApi.SymlinkPolicy,
): EelFsResult<EelPosixFileInfo, EelFileSystemApi.StatError> =
): EelResult<EelPosixFileInfo, EelFileSystemApi.StatError> =
holder.withDelegateRetrying {
stat(path, symlinkPolicy)
}
@@ -145,28 +149,28 @@ private class IjentFailSafeFileSystemPosixApiImpl(
override suspend fun sameFile(
source: EelPath.Absolute,
target: EelPath.Absolute,
): EelFsResult<Boolean, EelFileSystemApi.SameFileError> =
): EelResult<Boolean, EelFileSystemApi.SameFileError> =
holder.withDelegateRetrying {
sameFile(source, target)
}
override suspend fun openForReading(
path: EelPath.Absolute,
): EelFsResult<EelOpenedFile.Reader, EelFileSystemApi.FileReaderError> =
): EelResult<EelOpenedFile.Reader, EelFileSystemApi.FileReaderError> =
holder.withDelegateRetrying {
openForReading(path)
}
override suspend fun openForWriting(
options: EelFileSystemApi.WriteOptions,
): EelFsResult<EelOpenedFile.Writer, EelFileSystemApi.FileWriterError> =
): EelResult<EelOpenedFile.Writer, EelFileSystemApi.FileWriterError> =
holder.withDelegateRetrying {
openForWriting(options)
}
override suspend fun openForReadingAndWriting(
options: EelFileSystemApi.WriteOptions,
): EelFsResult<EelOpenedFile.ReaderWriter, EelFileSystemApi.FileWriterError> =
): EelResult<EelOpenedFile.ReaderWriter, EelFileSystemApi.FileWriterError> =
holder.withDelegateRetrying {
openForReadingAndWriting(options)
}

View File

@@ -3,7 +3,9 @@ package com.intellij.platform.ijent.community.impl.nio
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.path.getOrThrow
import com.intellij.platform.ijent.fs.*
import com.intellij.platform.ijent.fs.IjentFileSystemApi
import com.intellij.platform.ijent.fs.IjentFileSystemPosixApi
import com.intellij.platform.ijent.fs.IjentFileSystemWindowsApi
import org.jetbrains.annotations.ApiStatus
import java.net.URI
import java.nio.file.FileStore

View File

@@ -3,9 +3,9 @@
package com.intellij.platform.ijent.community.impl.nio
import com.intellij.platform.eel.EelResult
import com.intellij.platform.eel.fs.EelFileSystemApi
import com.intellij.platform.eel.fs.EelFsError
import com.intellij.platform.eel.fs.EelFsResult
import com.intellij.platform.eel.fs.EelOpenedFile
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.path.getOrThrow
@@ -13,16 +13,15 @@ import com.intellij.util.text.nullize
import kotlinx.coroutines.Dispatchers
import java.io.IOException
import java.nio.file.*
import kotlin.Throws
import kotlin.coroutines.Continuation
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.startCoroutine
@Throws(FileSystemException::class)
internal fun <T, E : EelFsError> EelFsResult<T, E>.getOrThrowFileSystemException(): T =
internal fun <T, E : EelFsError> EelResult<T, E>.getOrThrowFileSystemException(): T =
when (this) {
is EelFsResult.Ok -> value
is EelFsResult.Error -> error.throwFileSystemException()
is EelResult.Ok -> value
is EelResult.Error -> error.throwFileSystemException()
}
// TODO There's java.nio.file.FileSystemLoopException, so ELOOP should be added to all error codes for a decent support of all exceptions.

View File

@@ -4,9 +4,10 @@ package com.intellij.execution.eel
import com.intellij.execution.ijent.nio.IjentEphemeralRootAwarePath
import com.intellij.openapi.util.io.FileUtil
import com.intellij.platform.eel.*
import com.intellij.platform.eel.EelExecApi.ExecuteProcessError
import com.intellij.platform.eel.fs.getPath
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.provider.utils.unwrap
import com.intellij.platform.eel.path.getOrThrow
import org.jetbrains.annotations.ApiStatus.Internal
import java.nio.file.Path
import kotlin.io.path.pathString
@@ -47,7 +48,7 @@ private class EelEphemeralRootAwareMapper(
) : EelPathMapper {
override fun getOriginalPath(path: Path): EelPath.Absolute? {
return if (path is IjentEphemeralRootAwarePath) {
eelApi.fs.getPath(path.originalPath.toString()).unwrap()
eelApi.fs.getPath(path.originalPath.toString()).getOrThrow()
}
else {
null
@@ -72,7 +73,7 @@ private class EelExecApiWithNormalization(
private val original: EelExecApi,
private val normalize: (EelExecApi.ExecuteProcessBuilder) -> EelExecApi.ExecuteProcessBuilder,
) : EelExecApi by original {
override suspend fun execute(builder: EelExecApi.ExecuteProcessBuilder): EelExecApi.ExecuteProcessResult {
override suspend fun execute(builder: EelExecApi.ExecuteProcessBuilder): EelResult<EelProcess, ExecuteProcessError> {
return original.execute(normalize(builder))
}
}

View File

@@ -14,6 +14,7 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.util.io.FileUtil
import com.intellij.platform.eel.EelExecApi
import com.intellij.platform.eel.EelExecApi.Arguments.executeProcessBuilder
import com.intellij.platform.eel.EelResult
import com.intellij.platform.ijent.IjentChildProcess
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread
import com.intellij.util.concurrency.annotations.RequiresBlockingContext
@@ -136,13 +137,13 @@ fun runProcessBlocking(
.pty(pty)
.workingDirectory(workingDirectory)
)) {
is EelExecApi.ExecuteProcessResult.Success ->
(processResult.process as IjentChildProcess).toProcess(
is EelResult.Ok ->
(processResult.value as IjentChildProcess).toProcess(
coroutineScope = scope,
isPty = pty != null,
redirectStderr = processBuilder.redirectErrorStream(),
)
is EelExecApi.ExecuteProcessResult.Failure -> throw IOException(processResult.message)
is EelResult.Error -> throw IOException(processResult.error.message)
}
}

View File

@@ -7,6 +7,7 @@ import com.intellij.openapi.util.SystemInfoRt
import com.intellij.platform.eel.EelExecApi
import com.intellij.platform.eel.EelExecApi.Pty
import com.intellij.platform.eel.EelProcess
import com.intellij.platform.eel.EelResult
import com.intellij.platform.eel.impl.local.EelLocalExecApi
import com.intellij.testFramework.UsefulTestCase.IS_UNDER_TEAMCITY
import com.intellij.testFramework.common.timeoutRunBlocking
@@ -90,9 +91,9 @@ class EelLocalExecApiTest {
PTYManagement.PTY_RESIZE_LATER -> Pty(PTY_COLS - 1, PTY_ROWS - 1, true) // wrong tty size: will resize in the test
})
when (val r = EelLocalExecApi().execute(builder)) {
is EelExecApi.ExecuteProcessResult.Failure -> Assertions.fail(r.message)
is EelExecApi.ExecuteProcessResult.Success -> {
val process = r.process
is EelResult.Error -> Assertions.fail(r.error.message)
is EelResult.Ok -> {
val process = r.value
// Resize tty
when (ptyManagement) {

View File

@@ -14,9 +14,9 @@ import com.intellij.openapi.util.Computable
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.use
import com.intellij.platform.eel.EelExecApi
import com.intellij.platform.eel.EelPlatform
import com.intellij.platform.eel.EelUserPosixInfo
import com.intellij.platform.eel.*
import com.intellij.platform.eel.EelExecApi.ExecuteProcessError
import com.intellij.platform.eel.provider.EelProcessResultImpl
import com.intellij.platform.ijent.IjentExecApi
import com.intellij.platform.ijent.IjentPosixApi
import com.intellij.platform.ijent.IjentProcessInfo
@@ -501,7 +501,7 @@ class WSLDistributionTest {
val err = shouldThrow<ProcessNotCreatedException> {
sourceCommandLine.createProcess()
}
err.message should be(executeResultMock.message)
err.message should be(executeResultMock.error.message)
}
adapter
}
@@ -532,7 +532,7 @@ private class MockIjentApi(private val adapter: GeneralCommandLine, val rootUser
private class MockIjentExecApi(private val adapter: GeneralCommandLine, private val rootUser: Boolean) : IjentExecApi {
override suspend fun execute(builder: EelExecApi.ExecuteProcessBuilder): EelExecApi.ExecuteProcessResult = executeResultMock.also {
override suspend fun execute(builder: EelExecApi.ExecuteProcessBuilder): EelResult<EelProcess, ExecuteProcessError> = executeResultMock.also {
adapter.exePath = builder.exe
if (rootUser) {
adapter.putUserData(TEST_ROOT_USER_SET, true)
@@ -549,7 +549,7 @@ private val TEST_ROOT_USER_SET by lazy { Key.create<Boolean>("TEST_ROOT_USER_SET
private val executeResultMock by lazy {
EelExecApi.ExecuteProcessResult.Failure(errno = 12345, message = "mock result ${Ksuid.generate()}")
EelProcessResultImpl.createErrorResult(errno = 12345, message = "mock result ${Ksuid.generate()}")
}
private class WslTestStrategyExtension