Compare commits

...
Sign in to create a new pull request.

4 commits

Author SHA1 Message Date
Junkui Zhang
2ab568670d trigger ci 2025-07-21 19:50:55 +08:00
Junkui Zhang
2f5b84bc7e fix macos 2025-07-21 18:51:02 +08:00
Junkui Zhang
024a36ed61 use quote_shell_invocation 2025-07-21 18:50:25 +08:00
Junkui Zhang
b1c71ca412 init 2025-07-21 18:40:52 +08:00

View file

@ -667,7 +667,8 @@ pub fn wrap_for_ssh(
} else {
format!("cd; {env_changes} {to_run}")
};
let shell_invocation = format!("sh -c {}", shlex::try_quote(&commands).unwrap());
let shell_invocation =
quote_shell_invocation(format!("sh -c {}", shlex::try_quote(&commands).unwrap()));
let program = "ssh".to_string();
let mut args = ssh_command.arguments.clone();
@ -677,6 +678,45 @@ pub fn wrap_for_ssh(
(program, args)
}
#[cfg(not(target_os = "windows"))]
fn quote_shell_invocation(shell_invocation: String) -> String {
shell_invocation
}
#[cfg(target_os = "windows")]
fn quote_shell_invocation(shell_invocation: String) -> String {
fn need_quote(arg_bytes: &[u8]) -> bool {
arg_bytes.iter().any(|c| *c == b' ' || *c == b'\t') || arg_bytes.is_empty()
}
let mut result = Vec::new();
let arg_bytes = shell_invocation.as_bytes();
let quote = need_quote(arg_bytes);
if quote {
result.push('"' as u16);
}
let mut backslashes = 0;
for x in shell_invocation.encode_utf16() {
if x == '\\' as u16 {
backslashes += 1;
} else {
if x == '"' as u16 {
// Add n+1 backslashes to total 2n+1 before internal '"'.
result.extend((0..=backslashes).map(|_| '\\' as u16));
}
backslashes = 0;
}
result.push(x);
}
if quote {
// Add n backslashes to total 2n before ending '"'.
result.extend((0..backslashes).map(|_| '\\' as u16));
result.push('"' as u16);
}
String::from_utf16(&result).unwrap()
}
fn add_environment_path(env: &mut HashMap<String, String>, new_path: &Path) -> Result<()> {
let mut env_paths = vec![new_path.to_path_buf()];
if let Some(path) = env.get("PATH").or(env::var("PATH").ok().as_ref()) {