diff --git a/crates/nu-command/src/system/run_external.rs b/crates/nu-command/src/system/run_external.rs index af597d459ccc9..e4ac0ea88f677 100644 --- a/crates/nu-command/src/system/run_external.rs +++ b/crates/nu-command/src/system/run_external.rs @@ -1,6 +1,6 @@ use nu_cmd_base::hook::eval_hook; use nu_engine::{command_prelude::*, env_to_strings}; -use nu_path::{dots::expand_ndots, expand_tilde, AbsolutePath}; +use nu_path::{dots::expand_ndots_safe, expand_tilde, AbsolutePath}; use nu_protocol::{ did_you_mean, process::ChildProcess, ByteStream, NuGlob, OutDest, Signals, UseAnsiColoring, }; @@ -639,21 +639,6 @@ fn escape_cmd_argument(arg: &Spanned) -> Result, ShellE } } -/// Expand ndots, but only if it looks like it probably contains them, because there is some lossy -/// path normalization that happens. -fn expand_ndots_safe(path: impl AsRef) -> PathBuf { - let string = path.as_ref().to_string_lossy(); - - // Use ndots if it contains at least `...`, since that's the minimum trigger point, and don't - // use it if it contains ://, because that looks like a URL scheme and the path normalization - // will mess with that. - if string.contains("...") && !string.contains("://") { - expand_ndots(path) - } else { - path.as_ref().to_owned() - } -} - #[cfg(test)] mod test { use super::*; diff --git a/crates/nu-command/tests/commands/run_external.rs b/crates/nu-command/tests/commands/run_external.rs index 8a797300f130e..856214456ca62 100644 --- a/crates/nu-command/tests/commands/run_external.rs +++ b/crates/nu-command/tests/commands/run_external.rs @@ -247,6 +247,16 @@ fn external_command_ndots_args() { ); } +#[test] +fn external_command_ndots_leading_dot_slash() { + // Don't expand ndots with a leading `./` + let actual = nu!(r#" + nu --testbin cococo ./... ./.... + "#); + + assert_eq!(actual.out, "./... ./...."); +} + #[test] fn external_command_url_args() { // If ndots is not handled correctly, we can lose the double forward slashes that are needed diff --git a/crates/nu-path/src/dots.rs b/crates/nu-path/src/dots.rs index c001451c68aba..97a7deac020bc 100644 --- a/crates/nu-path/src/dots.rs +++ b/crates/nu-path/src/dots.rs @@ -73,6 +73,23 @@ pub fn expand_dots(path: impl AsRef) -> PathBuf { simiplified(&result) } +/// Expand ndots, but only if it looks like it probably contains them, because there is some lossy +/// path normalization that happens. +pub fn expand_ndots_safe(path: impl AsRef) -> PathBuf { + let string = path.as_ref().to_string_lossy(); + + // Use ndots if it contains at least `...`, since that's the minimum trigger point. + // Don't use it if it contains ://, because that looks like a URL scheme and the path normalization + // will mess with that. + // Don't use it if it starts with `./`, as to not break golang wildcard syntax + // (since generally you're probably not using `./` with ndots) + if string.contains("...") && !string.contains("://") && !string.starts_with("./") { + expand_ndots(path) + } else { + path.as_ref().to_owned() + } +} + #[cfg(windows)] fn simiplified(path: &std::path::Path) -> PathBuf { path.to_winuser_path() @@ -169,6 +186,12 @@ mod test_expand_ndots { }; assert_path_eq!(expand_ndots(path), expected); } + + #[test] + fn leading_dot_slash() { + let path = Path::new("./..."); + assert_path_eq!(expand_ndots_safe(path), "./..."); + } } #[cfg(test)] diff --git a/crates/nu-path/src/tilde.rs b/crates/nu-path/src/tilde.rs index 2420c8c17e030..638a7797b61ac 100644 --- a/crates/nu-path/src/tilde.rs +++ b/crates/nu-path/src/tilde.rs @@ -152,7 +152,6 @@ fn expand_tilde_with_another_user_home(path: &Path) -> PathBuf { /// Expand tilde ("~") into a home directory if it is the first path component pub fn expand_tilde(path: impl AsRef) -> PathBuf { - // TODO: Extend this to work with "~user" style of home paths expand_tilde_with_home(path, dirs::home_dir()) }