diff --git a/gix-command/src/lib.rs b/gix-command/src/lib.rs index 29a58964a7e..197abac4e80 100644 --- a/gix-command/src/lib.rs +++ b/gix-command/src/lib.rs @@ -34,7 +34,8 @@ mod prepare { /// Builder impl Prepare { - /// If called, the command will not be executed directly, but with `sh`. + /// If called, the command will not be executed directly, but with `sh`, but ony if the + /// command passed to [`prepare`](super::prepare()) requires this. /// /// This also allows to pass shell scripts as command, or use commands that contain arguments which are subsequently /// parsed by `sh`. diff --git a/gix-command/tests/command.rs b/gix-command/tests/command.rs index 606066da131..179236e7a10 100644 --- a/gix-command/tests/command.rs +++ b/gix-command/tests/command.rs @@ -1,14 +1,65 @@ use gix_testtools::Result; mod prepare { + #[cfg(windows)] + const SH: &str = "sh"; + #[cfg(not(windows))] + const SH: &str = "/bin/sh"; + fn quoted(input: &[&str]) -> String { input.iter().map(|s| format!("\"{s}\"")).collect::>().join(" ") } + + #[test] + fn empty() { + let cmd = std::process::Command::from(gix_command::prepare("")); + assert_eq!(format!("{cmd:?}"), "\"\""); + } #[test] fn single_and_multiple_arguments() { let cmd = std::process::Command::from(gix_command::prepare("ls").arg("first").args(["second", "third"])); assert_eq!(format!("{cmd:?}"), quoted(&["ls", "first", "second", "third"])); } + + #[test] + fn single_and_multiple_arguments_as_part_of_command() { + let cmd = std::process::Command::from(gix_command::prepare("ls first second third")); + assert_eq!( + format!("{cmd:?}"), + quoted(&["ls first second third"]), + "without shell, this is an invalid command" + ); + } + + #[test] + fn single_and_multiple_arguments_as_part_of_command_with_shell() { + let cmd = std::process::Command::from(gix_command::prepare("ls first second third").with_shell()); + assert_eq!( + format!("{cmd:?}"), + quoted(&[SH, "-c", "ls first second third", "--"]), + "with shell, this works as it performs word splitting" + ); + } + + #[test] + fn single_and_complex_arguments_as_part_of_command_with_shell() { + let cmd = std::process::Command::from(gix_command::prepare("ls --foo \"a b\"").arg("additional").with_shell()); + assert_eq!( + format!("{cmd:?}"), + format!("\"{SH}\" \"-c\" \"ls --foo \\\"a b\\\" \\\"$@\\\"\" \"--\" \"additional\""), + "with shell, this works as it performs word splitting" + ); + } + + #[test] + fn tilde_path_and_multiple_arguments_as_part_of_command_with_shell() { + let cmd = std::process::Command::from(gix_command::prepare("~/bin/exe --foo \"a b\"").with_shell()); + assert_eq!( + format!("{cmd:?}"), + format!("\"{SH}\" \"-c\" \"~/bin/exe --foo \\\"a b\\\"\" \"--\""), + "this always needs a shell as we need tilde expansion" + ); + } } mod spawn {