Python ExecService: Add ability to configure target command dynamically as it is used by Sdk

See `configureBuilderToRunPythonOnTarget`.

GitOrigin-RevId: a96a8b34a6d4cf1dbe3a08b26627b6ca5491df47
This commit is contained in:
Ilya.Kazakevich
2025-08-06 19:26:40 +02:00
committed by intellij-monorepo-bot
parent cff50ba3fc
commit 837468c5f6
2 changed files with 18 additions and 13 deletions

View File

@@ -5,6 +5,7 @@ import com.intellij.execution.process.AnsiEscapeDecoder
import com.intellij.execution.process.ProcessOutputTypes
import com.intellij.execution.target.FullPathOnTarget
import com.intellij.execution.target.TargetEnvironmentConfiguration
import com.intellij.execution.target.TargetedCommandLineBuilder
import com.intellij.openapi.util.NlsSafe
import com.intellij.platform.eel.EelApi
import com.intellij.platform.eel.getShell
@@ -43,13 +44,15 @@ sealed interface BinaryToExec
* [workDir] is pwd. As it should be on the same eel as [path] for most cases (except WSL), it is better not to set it at all.
* Prefer full [path] over relative.
*/
data class BinOnEel(val path: Path, val workDir: Path? = null) : BinaryToExec
data class BinOnEel(val path: Path, internal val workDir: Path? = null) : BinaryToExec
/**
* Legacy Targets-based approach. Do not use it, unless you know what you are doing
* if [target] "local" target is used
*/
data class BinOnTarget(val path: FullPathOnTarget, val target: TargetEnvironmentConfiguration?) : BinaryToExec
data class BinOnTarget(internal val configureTargetCmdLine: (TargetedCommandLineBuilder) -> Unit, val target: TargetEnvironmentConfiguration?) : BinaryToExec {
constructor(exePath: FullPathOnTarget, target: TargetEnvironmentConfiguration?) : this({ it.setExePath(exePath) }, target)
}
/**

View File

@@ -49,16 +49,24 @@ internal suspend fun createProcessLauncherOnTarget(binOnTarget: BinOnTarget, lau
val args = launchRequest.args.getArgs { localFile ->
targetEnv.getTargetPaths(localFile.pathString).first()
}
return@withContext Result.success(ProcessLauncher(exeForError = Exe.OnTarget(binOnTarget.path), args = args, processCommands = TargetProcessCommands(launchRequest.scopeToBind, binOnTarget.path, request, targetEnv, args, launchRequest.env)))
val exePath: FullPathOnTarget
val cmdLine = TargetedCommandLineBuilder(request).also {
binOnTarget.configureTargetCmdLine(it)
// exe path is always fixed (pre-presolved) promise. It can't be obtained directly because of Targets API limitation
exePath = it.exePath.localValue.blockingGet(1000) ?: error("Exe path not set: $binOnTarget is broken")
it.addParameters(args)
for ((k, v) in launchRequest.env) {
it.addEnvironmentVariable(k, v)
}
}.build()
return@withContext Result.success(ProcessLauncher(exeForError = Exe.OnTarget(exePath), args = args, processCommands = TargetProcessCommands(launchRequest.scopeToBind, exePath, targetEnv, cmdLine)))
}
private class TargetProcessCommands(
private val scopeToBind: CoroutineScope,
private val exePath: FullPathOnTarget,
private val request: TargetEnvironmentRequest,
private val targetEnv: TargetEnvironment,
private val args: List<String>,
private val env: Map<String, String>,
private val cmdLine: TargetedCommandLine,
) : ProcessCommands {
private var process: Process? = null
@@ -70,13 +78,7 @@ private class TargetProcessCommands(
}, killProcess = { process?.destroyForcibly() })
override suspend fun start(): Result<Process, ExecErrorReason.CantStart> {
val cmdLine = TargetedCommandLineBuilder(request).also {
it.setExePath(exePath)
it.addParameters(args)
for ((k, v) in env) {
it.addEnvironmentVariable(k, v)
}
}.build()
try {
val process = targetEnv.createProcess(cmdLine)
this.process = process