terminal: Escape strings with backticks rather than backslashes in PowerShell (#39657)
Closes #39007 Strings should be escaped with backticks in PowerShell, so the following ``` \"pwsh.exe -C pytest -m \\\"some_test\\\"\" ``` becomes ``` \"pwsh.exe -C pytest -m `\"some_test`\"\" ``` Otherwise PowerShell will misinterpret the invocation resulting in weirdness all-around such as the issue linked above. Release Notes: - N/A
This commit is contained in:
@@ -145,7 +145,7 @@ impl Project {
|
||||
project.update(cx, move |this, cx| {
|
||||
let format_to_run = || {
|
||||
if let Some(command) = &spawn_task.command {
|
||||
let mut command: Option<Cow<str>> = shlex::try_quote(command).ok();
|
||||
let mut command: Option<Cow<str>> = shell_kind.try_quote(command);
|
||||
if let Some(command) = &mut command
|
||||
&& command.starts_with('"')
|
||||
&& let Some(prefix) = shell_kind.command_prefix()
|
||||
@@ -156,7 +156,8 @@ impl Project {
|
||||
let args = spawn_task
|
||||
.args
|
||||
.iter()
|
||||
.filter_map(|arg| shlex::try_quote(arg).ok());
|
||||
.filter_map(|arg| shell_kind.try_quote(&arg));
|
||||
|
||||
command.into_iter().chain(args).join(" ")
|
||||
} else {
|
||||
// todo: this breaks for remotes to windows
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::{fmt, path::Path, sync::LazyLock};
|
||||
use std::{borrow::Cow, fmt, path::Path, sync::LazyLock};
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum ShellKind {
|
||||
@@ -241,6 +241,7 @@ impl ShellKind {
|
||||
input.into()
|
||||
}
|
||||
}
|
||||
|
||||
fn to_powershell_variable(input: &str) -> String {
|
||||
if let Some(var_str) = input.strip_prefix("${") {
|
||||
if var_str.find(':').is_none() {
|
||||
@@ -359,4 +360,14 @@ impl ShellKind {
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_quote<'a>(&self, arg: &'a str) -> Option<Cow<'a, str>> {
|
||||
shlex::try_quote(arg).ok().map(|arg| match self {
|
||||
// If we are running in PowerShell, we want to take extra care when escaping strings.
|
||||
// In particular, we want to escape strings with a backtick (`) rather than a backslash (\).
|
||||
// TODO double escaping backslashes is not necessary in PowerShell and probably CMD
|
||||
ShellKind::PowerShell => Cow::Owned(arg.replace("\\\"", "`\"")),
|
||||
_ => arg,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user