diff --git a/crates/tui/src/tools/shell.rs b/crates/tui/src/tools/shell.rs index defebe1b..7932d0c0 100644 --- a/crates/tui/src/tools/shell.rs +++ b/crates/tui/src/tools/shell.rs @@ -192,8 +192,15 @@ fn push_shell_args(cmd: &mut Command, program: &str, args: &[String]) { use std::os::windows::process::CommandExt; // The `cmd /C ` shape is the only place std's per-arg escaping // corrupts a quoted command. Pass `/C` and the payload raw so the quotes - // survive; any other program keeps normal (correct) escaping. - if program.eq_ignore_ascii_case("cmd") + // survive; any other program keeps normal (correct) escaping. Match `cmd` + // by file stem so a full path (`C:\Windows\System32\cmd.exe`) or `.exe` + // suffix still triggers the raw-arg path. + let is_cmd = std::path::Path::new(program) + .file_stem() + .and_then(|s| s.to_str()) + .map(|s| s.eq_ignore_ascii_case("cmd")) + .unwrap_or(false); + if is_cmd && args.len() == 2 && args[0].eq_ignore_ascii_case("/C") { diff --git a/crates/tui/src/tools/shell/tests.rs b/crates/tui/src/tools/shell/tests.rs index 5fe30548..775fb491 100644 --- a/crates/tui/src/tools/shell/tests.rs +++ b/crates/tui/src/tools/shell/tests.rs @@ -852,6 +852,10 @@ fn issue_1691_quoted_commit_message_round_trips() { ); let mut built = Command::new(&spec.program); push_shell_args(&mut built, &spec.program, &spec.args); - assert_eq!(built.get_args().count(), 2); + let got: Vec = built + .get_args() + .map(|a| a.to_string_lossy().into_owned()) + .collect(); + assert_eq!(got, spec.args); } }