Use shell to launch MCP and ACP servers (#42382)
`npx`, and any `npm install`-ed programs, exist as batch scripts/PowerShell scripts on the PATH. We have to use a shell to launch these programs. Fixes https://github.com/zed-industries/zed/issues/41435 Closes https://github.com/zed-industries/zed/pull/42651 Release Notes: - windows: Custom MCP and ACP servers installed through `npm` now launch correctly. --------- Co-authored-by: Lukas Wirth <me@lukaswirth.dev>
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use crate::shell::get_system_shell;
|
||||
use crate::shell::{Shell, ShellKind};
|
||||
|
||||
@@ -42,7 +44,7 @@ impl ShellBuilder {
|
||||
self.program.clone()
|
||||
} else {
|
||||
match self.kind {
|
||||
ShellKind::PowerShell => {
|
||||
ShellKind::PowerShell | ShellKind::Pwsh => {
|
||||
format!("{} -C '{}'", self.program, command_to_use_in_label)
|
||||
}
|
||||
ShellKind::Cmd => {
|
||||
@@ -78,11 +80,27 @@ impl ShellBuilder {
|
||||
task_args: &[String],
|
||||
) -> (String, Vec<String>) {
|
||||
if let Some(task_command) = task_command {
|
||||
let mut combined_command = task_args.iter().fold(task_command, |mut command, arg| {
|
||||
command.push(' ');
|
||||
command.push_str(&self.kind.to_shell_variable(arg));
|
||||
command
|
||||
});
|
||||
let task_command = self.kind.prepend_command_prefix(&task_command);
|
||||
let task_command = if !task_args.is_empty() {
|
||||
match self.kind.try_quote_prefix_aware(&task_command) {
|
||||
Some(task_command) => task_command,
|
||||
None => task_command,
|
||||
}
|
||||
} else {
|
||||
task_command
|
||||
};
|
||||
let mut combined_command =
|
||||
task_args
|
||||
.iter()
|
||||
.fold(task_command.into_owned(), |mut command, arg| {
|
||||
command.push(' ');
|
||||
let shell_variable = self.kind.to_shell_variable(arg);
|
||||
command.push_str(&match self.kind.try_quote(&shell_variable) {
|
||||
Some(shell_variable) => shell_variable,
|
||||
None => Cow::Owned(shell_variable),
|
||||
});
|
||||
command
|
||||
});
|
||||
if self.redirect_stdin {
|
||||
match self.kind {
|
||||
ShellKind::Fish => {
|
||||
@@ -99,7 +117,7 @@ impl ShellBuilder {
|
||||
combined_command.insert(0, '(');
|
||||
combined_command.push_str(") </dev/null");
|
||||
}
|
||||
ShellKind::PowerShell => {
|
||||
ShellKind::PowerShell | ShellKind::Pwsh => {
|
||||
combined_command.insert_str(0, "$null | & {");
|
||||
combined_command.push_str("}");
|
||||
}
|
||||
@@ -115,6 +133,10 @@ impl ShellBuilder {
|
||||
|
||||
(self.program, self.args)
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> ShellKind {
|
||||
self.kind
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -144,7 +166,7 @@ mod test {
|
||||
vec![
|
||||
"-i",
|
||||
"-c",
|
||||
"echo $env.hello $env.world nothing --($env.something) $ ${test"
|
||||
"^echo '$env.hello' '$env.world' nothing '--($env.something)' '$' '${test'"
|
||||
]
|
||||
);
|
||||
}
|
||||
@@ -159,7 +181,7 @@ mod test {
|
||||
.build(Some("echo".into()), &["nothing".to_string()]);
|
||||
|
||||
assert_eq!(program, "nu");
|
||||
assert_eq!(args, vec!["-i", "-c", "(echo nothing) </dev/null"]);
|
||||
assert_eq!(args, vec!["-i", "-c", "(^echo nothing) </dev/null"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user