Use ShellKind::try_quote whenever we need to quote shell args (#40912)
Using `shlex` unconditionally is dangerous as it assumes the underlying shell is POSIX which is not the case for PowerShell, CMD, or Nushell. Therefore, whenever we want to quote the args we should utilise our helper `util::shell::ShellKind::try_quote` which takes into account which shell is being used to actually exec/spawn the invocation. Release Notes: - N/A --------- Co-authored-by: Lukas Wirth <me@lukaswirth.dev>
This commit is contained in:
co-authored by
Lukas Wirth
parent
18daa9a839
commit
8f4646d6c3
+26
-77
@@ -3,7 +3,6 @@
|
||||
mod adapter_schema;
|
||||
mod debug_format;
|
||||
mod serde_helpers;
|
||||
mod shell_builder;
|
||||
pub mod static_source;
|
||||
mod task_template;
|
||||
mod vscode_debug_format;
|
||||
@@ -12,23 +11,22 @@ mod vscode_format;
|
||||
use anyhow::Context as _;
|
||||
use collections::{HashMap, HashSet, hash_map};
|
||||
use gpui::SharedString;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::borrow::Cow;
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use util::get_system_shell;
|
||||
|
||||
pub use adapter_schema::{AdapterSchema, AdapterSchemas};
|
||||
pub use debug_format::{
|
||||
AttachRequest, BuildTaskDefinition, DebugRequest, DebugScenario, DebugTaskFile, LaunchRequest,
|
||||
Request, TcpArgumentsTemplate, ZedDebugConfig,
|
||||
};
|
||||
pub use shell_builder::{ShellBuilder, ShellKind};
|
||||
pub use task_template::{
|
||||
DebugArgsRequest, HideStrategy, RevealStrategy, TaskTemplate, TaskTemplates,
|
||||
substitute_variables_in_map, substitute_variables_in_str,
|
||||
};
|
||||
pub use util::shell::{Shell, ShellKind};
|
||||
pub use util::shell_builder::ShellBuilder;
|
||||
pub use vscode_debug_format::VsCodeDebugTaskFile;
|
||||
pub use vscode_format::VsCodeTaskFile;
|
||||
pub use zed_actions::RevealTarget;
|
||||
@@ -318,81 +316,32 @@ pub struct TaskContext {
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RunnableTag(pub SharedString);
|
||||
|
||||
/// Shell configuration to open the terminal with.
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, Hash)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum Shell {
|
||||
/// Use the system's default terminal configuration in /etc/passwd
|
||||
#[default]
|
||||
System,
|
||||
/// Use a specific program with no arguments.
|
||||
Program(String),
|
||||
/// Use a specific program with arguments.
|
||||
WithArguments {
|
||||
/// The program to run.
|
||||
program: String,
|
||||
/// The arguments to pass to the program.
|
||||
args: Vec<String>,
|
||||
/// An optional string to override the title of the terminal tab
|
||||
title_override: Option<SharedString>,
|
||||
},
|
||||
pub fn shell_from_proto(proto: proto::Shell) -> anyhow::Result<Shell> {
|
||||
let shell_type = proto.shell_type.context("invalid shell type")?;
|
||||
let shell = match shell_type {
|
||||
proto::shell::ShellType::System(_) => Shell::System,
|
||||
proto::shell::ShellType::Program(program) => Shell::Program(program),
|
||||
proto::shell::ShellType::WithArguments(program) => Shell::WithArguments {
|
||||
program: program.program,
|
||||
args: program.args,
|
||||
title_override: None,
|
||||
},
|
||||
};
|
||||
Ok(shell)
|
||||
}
|
||||
|
||||
impl Shell {
|
||||
pub fn program(&self) -> String {
|
||||
match self {
|
||||
Shell::Program(program) => program.clone(),
|
||||
Shell::WithArguments { program, .. } => program.clone(),
|
||||
Shell::System => get_system_shell(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn program_and_args(&self) -> (String, &[String]) {
|
||||
match self {
|
||||
Shell::Program(program) => (program.clone(), &[]),
|
||||
Shell::WithArguments { program, args, .. } => (program.clone(), args),
|
||||
Shell::System => (get_system_shell(), &[]),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn shell_kind(&self, is_windows: bool) -> ShellKind {
|
||||
match self {
|
||||
Shell::Program(program) => ShellKind::new(program, is_windows),
|
||||
Shell::WithArguments { program, .. } => ShellKind::new(program, is_windows),
|
||||
Shell::System => ShellKind::system(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_proto(proto: proto::Shell) -> anyhow::Result<Self> {
|
||||
let shell_type = proto.shell_type.context("invalid shell type")?;
|
||||
let shell = match shell_type {
|
||||
proto::shell::ShellType::System(_) => Self::System,
|
||||
proto::shell::ShellType::Program(program) => Self::Program(program),
|
||||
proto::shell::ShellType::WithArguments(program) => Self::WithArguments {
|
||||
program: program.program,
|
||||
args: program.args,
|
||||
title_override: None,
|
||||
},
|
||||
};
|
||||
Ok(shell)
|
||||
}
|
||||
|
||||
pub fn to_proto(self) -> proto::Shell {
|
||||
let shell_type = match self {
|
||||
Shell::System => proto::shell::ShellType::System(proto::System {}),
|
||||
Shell::Program(program) => proto::shell::ShellType::Program(program),
|
||||
Shell::WithArguments {
|
||||
program,
|
||||
args,
|
||||
title_override: _,
|
||||
} => proto::shell::ShellType::WithArguments(proto::shell::WithArguments {
|
||||
program,
|
||||
args,
|
||||
}),
|
||||
};
|
||||
proto::Shell {
|
||||
shell_type: Some(shell_type),
|
||||
}
|
||||
pub fn shell_to_proto(shell: Shell) -> proto::Shell {
|
||||
let shell_type = match shell {
|
||||
Shell::System => proto::shell::ShellType::System(proto::System {}),
|
||||
Shell::Program(program) => proto::shell::ShellType::Program(program),
|
||||
Shell::WithArguments {
|
||||
program,
|
||||
args,
|
||||
title_override: _,
|
||||
} => proto::shell::ShellType::WithArguments(proto::shell::WithArguments { program, args }),
|
||||
};
|
||||
proto::Shell {
|
||||
shell_type: Some(shell_type),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user