## Summary Enables shell_command for windows users, and starts adding some basic command parsing here, to at least remove powershell prefixes. We'll follow this up with command parsing but I wanted to land this change separately with some basic UX. **NOTE**: This implementation parses bash and powershell on both platforms. In theory this is possible, since you can use git bash on windows or powershell on linux. In practice, this may not be worth the complexity of supporting, so I don't feel strongly about the current approach vs. platform-specific branching. ## Testing - [x] Added a bunch of tests - [x] Ran on both windows and os x
70 lines
2.2 KiB
Rust
70 lines
2.2 KiB
Rust
use std::path::Path;
|
||
use std::path::PathBuf;
|
||
|
||
use codex_core::parse_command::extract_shell_command;
|
||
use dirs::home_dir;
|
||
use shlex::try_join;
|
||
|
||
pub(crate) fn escape_command(command: &[String]) -> String {
|
||
try_join(command.iter().map(String::as_str)).unwrap_or_else(|_| command.join(" "))
|
||
}
|
||
|
||
pub(crate) fn strip_bash_lc_and_escape(command: &[String]) -> String {
|
||
if let Some((_, script)) = extract_shell_command(command) {
|
||
return script.to_string();
|
||
}
|
||
escape_command(command)
|
||
}
|
||
|
||
/// If `path` is absolute and inside $HOME, return the part *after* the home
|
||
/// directory; otherwise, return the path as-is. Note if `path` is the homedir,
|
||
/// this will return and empty path.
|
||
pub(crate) fn relativize_to_home<P>(path: P) -> Option<PathBuf>
|
||
where
|
||
P: AsRef<Path>,
|
||
{
|
||
let path = path.as_ref();
|
||
if !path.is_absolute() {
|
||
// If the path is not absolute, we can’t do anything with it.
|
||
return None;
|
||
}
|
||
|
||
let home_dir = home_dir()?;
|
||
let rel = path.strip_prefix(&home_dir).ok()?;
|
||
Some(rel.to_path_buf())
|
||
}
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
#[test]
|
||
fn test_escape_command() {
|
||
let args = vec!["foo".into(), "bar baz".into(), "weird&stuff".into()];
|
||
let cmdline = escape_command(&args);
|
||
assert_eq!(cmdline, "foo 'bar baz' 'weird&stuff'");
|
||
}
|
||
|
||
#[test]
|
||
fn test_strip_bash_lc_and_escape() {
|
||
// Test bash
|
||
let args = vec!["bash".into(), "-lc".into(), "echo hello".into()];
|
||
let cmdline = strip_bash_lc_and_escape(&args);
|
||
assert_eq!(cmdline, "echo hello");
|
||
|
||
// Test zsh
|
||
let args = vec!["zsh".into(), "-lc".into(), "echo hello".into()];
|
||
let cmdline = strip_bash_lc_and_escape(&args);
|
||
assert_eq!(cmdline, "echo hello");
|
||
|
||
// Test absolute path to zsh
|
||
let args = vec!["/usr/bin/zsh".into(), "-lc".into(), "echo hello".into()];
|
||
let cmdline = strip_bash_lc_and_escape(&args);
|
||
assert_eq!(cmdline, "echo hello");
|
||
|
||
// Test absolute path to bash
|
||
let args = vec!["/bin/bash".into(), "-lc".into(), "echo hello".into()];
|
||
let cmdline = strip_bash_lc_and_escape(&args);
|
||
assert_eq!(cmdline, "echo hello");
|
||
}
|
||
}
|