diff --git a/crates/nu-cli/src/commands/history/history_.rs b/crates/nu-cli/src/commands/history/history_.rs index 1f3d1082fa..c270cef003 100644 --- a/crates/nu-cli/src/commands/history/history_.rs +++ b/crates/nu-cli/src/commands/history/history_.rs @@ -67,7 +67,7 @@ impl Command for History { } else { let history_reader: Option> = match history.file_format { HistoryFileFormat::Sqlite => { - SqliteBackedHistory::with_file(history_path.clone(), None, None) + SqliteBackedHistory::with_file(history_path.clone().into(), None, None) .map(|inner| { let boxed: Box = Box::new(inner); boxed @@ -77,7 +77,7 @@ impl Command for History { HistoryFileFormat::PlainText => FileBackedHistory::with_file( history.max_size as usize, - history_path.clone(), + history_path.clone().into(), ) .map(|inner| { let boxed: Box = Box::new(inner); diff --git a/crates/nu-cli/src/completions/completion_common.rs b/crates/nu-cli/src/completions/completion_common.rs index d6882da57b..5469ba1326 100644 --- a/crates/nu-cli/src/completions/completion_common.rs +++ b/crates/nu-cli/src/completions/completion_common.rs @@ -176,7 +176,7 @@ pub fn complete_item( } Some(Component::Normal(home)) if home.to_string_lossy() == "~" => { components.next(); - cwd = home_dir().unwrap_or(cwd_pathbuf); + cwd = home_dir().map(Into::into).unwrap_or(cwd_pathbuf); prefix_len = 1; original_cwd = OriginalCwd::Home; } diff --git a/crates/nu-cli/src/config_files.rs b/crates/nu-cli/src/config_files.rs index 3a02f75e86..0a1226c304 100644 --- a/crates/nu-cli/src/config_files.rs +++ b/crates/nu-cli/src/config_files.rs @@ -192,7 +192,8 @@ pub fn add_plugin_file( } else if let Some(mut plugin_path) = nu_path::config_dir() { // Path to store plugins signatures plugin_path.push(storage_path); - let mut plugin_path = canonicalize_with(&plugin_path, &cwd).unwrap_or(plugin_path); + let mut plugin_path = + canonicalize_with(&plugin_path, &cwd).unwrap_or(plugin_path.into()); plugin_path.push(PLUGIN_FILE); let plugin_path = canonicalize_with(&plugin_path, &cwd).unwrap_or(plugin_path); engine_state.plugin_path = Some(plugin_path); @@ -247,7 +248,7 @@ pub(crate) fn get_history_path(storage_path: &str, mode: HistoryFileFormat) -> O HistoryFileFormat::PlainText => HISTORY_FILE_TXT, HistoryFileFormat::Sqlite => HISTORY_FILE_SQLITE, }); - history_path + history_path.into() }) } diff --git a/crates/nu-cmd-base/src/util.rs b/crates/nu-cmd-base/src/util.rs index e485243877..f778fe4679 100644 --- a/crates/nu-cmd-base/src/util.rs +++ b/crates/nu-cmd-base/src/util.rs @@ -3,21 +3,26 @@ use nu_protocol::{ engine::{EngineState, Stack}, Range, ShellError, Span, Value, }; -use std::{ops::Bound, path::PathBuf}; +use std::ops::Bound; -pub fn get_init_cwd() -> PathBuf { - std::env::current_dir().unwrap_or_else(|_| { - std::env::var("PWD") - .map(Into::into) - .unwrap_or_else(|_| nu_path::home_dir().unwrap_or_default()) - }) +pub fn get_init_cwd() -> AbsolutePathBuf { + std::env::current_dir() + .ok() + .and_then(|path| AbsolutePathBuf::try_from(path).ok()) + .or_else(|| { + std::env::var("PWD") + .ok() + .and_then(|path| AbsolutePathBuf::try_from(path).ok()) + }) + .or_else(nu_path::home_dir) + .expect("Failed to get current working directory") } -pub fn get_guaranteed_cwd(engine_state: &EngineState, stack: &Stack) -> PathBuf { +pub fn get_guaranteed_cwd(engine_state: &EngineState, stack: &Stack) -> AbsolutePathBuf { engine_state .cwd(Some(stack)) - .map(AbsolutePathBuf::into_std_path_buf) - .unwrap_or(crate::util::get_init_cwd()) + .ok() + .unwrap_or_else(get_init_cwd) } type MakeRangeError = fn(&str, Span) -> ShellError; diff --git a/crates/nu-command/src/filesystem/cd.rs b/crates/nu-command/src/filesystem/cd.rs index 23faf6f67b..ba91e6d0ca 100644 --- a/crates/nu-command/src/filesystem/cd.rs +++ b/crates/nu-command/src/filesystem/cd.rs @@ -1,6 +1,5 @@ use nu_cmd_base::util::get_init_cwd; use nu_engine::command_prelude::*; -use nu_path::AbsolutePathBuf; use nu_utils::filesystem::{have_permission, PermissionResult}; #[derive(Clone)] @@ -46,8 +45,8 @@ impl Command for Cd { // user can use `cd` to recover PWD to a good state. let cwd = engine_state .cwd(Some(stack)) - .map(AbsolutePathBuf::into_std_path_buf) - .unwrap_or(get_init_cwd()); + .ok() + .unwrap_or_else(get_init_cwd); let path_val = { if let Some(path) = path_val { @@ -66,7 +65,7 @@ impl Command for Cd { if let Some(oldpwd) = stack.get_env_var(engine_state, "OLDPWD") { oldpwd.to_path()? } else { - cwd + cwd.into() } } else { // Trim whitespace from the end of path. diff --git a/crates/nu-command/src/filesystem/rm.rs b/crates/nu-command/src/filesystem/rm.rs index 9eb4fabace..9e879cb2ad 100644 --- a/crates/nu-command/src/filesystem/rm.rs +++ b/crates/nu-command/src/filesystem/rm.rs @@ -135,12 +135,9 @@ fn rm( let home: Option = nu_path::home_dir().map(|path| { { if path.exists() { - match nu_path::canonicalize_with(&path, ¤tdir_path) { - Ok(canon_path) => canon_path, - Err(_) => path, - } + nu_path::canonicalize_with(&path, ¤tdir_path).unwrap_or(path.into()) } else { - path + path.into() } } .to_string_lossy() diff --git a/crates/nu-path/src/dots.rs b/crates/nu-path/src/dots.rs index 53330eec1d..6f46bb09c3 100644 --- a/crates/nu-path/src/dots.rs +++ b/crates/nu-path/src/dots.rs @@ -1,4 +1,5 @@ -use super::helpers; +#[cfg(windows)] +use omnipath::WinPathExt; use std::path::{Component, Path, PathBuf}; /// Normalize the path, expanding occurrences of n-dots. @@ -63,7 +64,18 @@ pub fn expand_dots(path: impl AsRef) -> PathBuf { } } - helpers::simiplified(&result) + simiplified(&result) +} + +#[cfg(windows)] +fn simiplified(path: &std::path::Path) -> PathBuf { + path.to_winuser_path() + .unwrap_or_else(|_| path.to_path_buf()) +} + +#[cfg(not(windows))] +fn simiplified(path: &std::path::Path) -> PathBuf { + path.to_path_buf() } #[cfg(test)] diff --git a/crates/nu-path/src/expansions.rs b/crates/nu-path/src/expansions.rs index 8e99b84092..44e2d12503 100644 --- a/crates/nu-path/src/expansions.rs +++ b/crates/nu-path/src/expansions.rs @@ -1,8 +1,9 @@ +#[cfg(windows)] +use omnipath::WinPathExt; use std::io; use std::path::{Path, PathBuf}; use super::dots::{expand_dots, expand_ndots}; -use super::helpers; use super::tilde::expand_tilde; // Join a path relative to another path. Paths starting with tilde are considered as absolute. @@ -30,8 +31,17 @@ where fn canonicalize(path: impl AsRef) -> io::Result { let path = expand_tilde(path); let path = expand_ndots(path); + canonicalize_path(&path) +} - helpers::canonicalize(&path) +#[cfg(windows)] +fn canonicalize_path(path: &std::path::Path) -> std::io::Result { + path.canonicalize()?.to_winuser_path() +} + +#[cfg(not(windows))] +fn canonicalize_path(path: &std::path::Path) -> std::io::Result { + path.canonicalize() } /// Resolve all symbolic links and all components (tilde, ., .., ...+) and return the path in its diff --git a/crates/nu-path/src/helpers.rs b/crates/nu-path/src/helpers.rs index a6e35bddfe..b36d59971e 100644 --- a/crates/nu-path/src/helpers.rs +++ b/crates/nu-path/src/helpers.rs @@ -1,59 +1,32 @@ -#[cfg(windows)] -use omnipath::WinPathExt; -use std::path::PathBuf; +use crate::AbsolutePathBuf; -pub fn home_dir() -> Option { - dirs::home_dir() +pub fn home_dir() -> Option { + dirs::home_dir().and_then(|home| AbsolutePathBuf::try_from(home).ok()) } /// Return the data directory for the current platform or XDG_DATA_HOME if specified. -pub fn data_dir() -> Option { - match std::env::var("XDG_DATA_HOME").map(PathBuf::from) { - Ok(xdg_data) if xdg_data.is_absolute() => Some(canonicalize(&xdg_data).unwrap_or(xdg_data)), - _ => get_canonicalized_path(dirs::data_dir()), - } +pub fn data_dir() -> Option { + std::env::var("XDG_DATA_HOME") + .ok() + .and_then(|path| AbsolutePathBuf::try_from(path).ok()) + .or_else(|| dirs::data_dir().and_then(|path| AbsolutePathBuf::try_from(path).ok())) + .map(|path| path.canonicalize().map(Into::into).unwrap_or(path)) } /// Return the cache directory for the current platform or XDG_CACHE_HOME if specified. -pub fn cache_dir() -> Option { - match std::env::var("XDG_CACHE_HOME").map(PathBuf::from) { - Ok(xdg_cache) if xdg_cache.is_absolute() => { - Some(canonicalize(&xdg_cache).unwrap_or(xdg_cache)) - } - _ => get_canonicalized_path(dirs::cache_dir()), - } +pub fn cache_dir() -> Option { + std::env::var("XDG_CACHE_HOME") + .ok() + .and_then(|path| AbsolutePathBuf::try_from(path).ok()) + .or_else(|| dirs::cache_dir().and_then(|path| AbsolutePathBuf::try_from(path).ok())) + .map(|path| path.canonicalize().map(Into::into).unwrap_or(path)) } /// Return the config directory for the current platform or XDG_CONFIG_HOME if specified. -pub fn config_dir() -> Option { - match std::env::var("XDG_CONFIG_HOME").map(PathBuf::from) { - Ok(xdg_config) if xdg_config.is_absolute() => { - Some(canonicalize(&xdg_config).unwrap_or(xdg_config)) - } - _ => get_canonicalized_path(dirs::config_dir()), - } -} - -pub fn get_canonicalized_path(path: Option) -> Option { - let path = path?; - Some(canonicalize(&path).unwrap_or(path)) -} - -#[cfg(windows)] -pub fn canonicalize(path: &std::path::Path) -> std::io::Result { - path.canonicalize()?.to_winuser_path() -} -#[cfg(not(windows))] -pub fn canonicalize(path: &std::path::Path) -> std::io::Result { - path.canonicalize() -} - -#[cfg(windows)] -pub fn simiplified(path: &std::path::Path) -> PathBuf { - path.to_winuser_path() - .unwrap_or_else(|_| path.to_path_buf()) -} -#[cfg(not(windows))] -pub fn simiplified(path: &std::path::Path) -> PathBuf { - path.to_path_buf() +pub fn config_dir() -> Option { + std::env::var("XDG_CONFIG_HOME") + .ok() + .and_then(|path| AbsolutePathBuf::try_from(path).ok()) + .or_else(|| dirs::config_dir().and_then(|path| AbsolutePathBuf::try_from(path).ok())) + .map(|path| path.canonicalize().map(Into::into).unwrap_or(path)) } diff --git a/crates/nu-path/src/lib.rs b/crates/nu-path/src/lib.rs index 2cb415264a..524a6aed4e 100644 --- a/crates/nu-path/src/lib.rs +++ b/crates/nu-path/src/lib.rs @@ -11,7 +11,7 @@ mod trailing_slash; pub use components::components; pub use expansions::{canonicalize_with, expand_path_with, expand_to_real_path, locate_in_dirs}; -pub use helpers::{cache_dir, config_dir, data_dir, get_canonicalized_path, home_dir}; +pub use helpers::{cache_dir, config_dir, data_dir, home_dir}; pub use path::*; pub use tilde::expand_tilde; pub use trailing_slash::{has_trailing_slash, strip_trailing_slash}; diff --git a/crates/nu-protocol/src/eval_const.rs b/crates/nu-protocol/src/eval_const.rs index 4cb5ccc0f5..1ee7802799 100644 --- a/crates/nu-protocol/src/eval_const.rs +++ b/crates/nu-protocol/src/eval_const.rs @@ -36,7 +36,7 @@ pub(crate) fn create_nu_constant(engine_state: &EngineState, span: Span) -> Valu let config_path = match nu_path::config_dir() { Some(mut path) => { path.push("nushell"); - Ok(canonicalize_path(engine_state, &path)) + Ok(canonicalize_path(engine_state, path.as_ref())) } None => Err(Value::error( ShellError::ConfigDirNotFound { span: Some(span) }, @@ -141,7 +141,7 @@ pub(crate) fn create_nu_constant(engine_state: &EngineState, span: Span) -> Valu record.push( "home-path", if let Some(path) = nu_path::home_dir() { - let canon_home_path = canonicalize_path(engine_state, &path); + let canon_home_path = canonicalize_path(engine_state, path.as_ref()); Value::string(canon_home_path.to_string_lossy(), span) } else { Value::error( @@ -156,7 +156,7 @@ pub(crate) fn create_nu_constant(engine_state: &EngineState, span: Span) -> Valu record.push( "data-dir", if let Some(path) = nu_path::data_dir() { - let mut canon_data_path = canonicalize_path(engine_state, &path); + let mut canon_data_path = canonicalize_path(engine_state, path.as_ref()); canon_data_path.push("nushell"); Value::string(canon_data_path.to_string_lossy(), span) } else { @@ -172,7 +172,7 @@ pub(crate) fn create_nu_constant(engine_state: &EngineState, span: Span) -> Valu record.push( "cache-dir", if let Some(path) = nu_path::cache_dir() { - let mut canon_cache_path = canonicalize_path(engine_state, &path); + let mut canon_cache_path = canonicalize_path(engine_state, path.as_ref()); canon_cache_path.push("nushell"); Value::string(canon_cache_path.to_string_lossy(), span) } else { diff --git a/src/config_files.rs b/src/config_files.rs index cf72819600..1f9e4e9433 100644 --- a/src/config_files.rs +++ b/src/config_files.rs @@ -121,7 +121,7 @@ pub(crate) fn read_config_file( } } - eval_config_contents(config_path, engine_state, stack); + eval_config_contents(config_path.into(), engine_state, stack); } } @@ -141,7 +141,7 @@ pub(crate) fn read_loginshell_file(engine_state: &mut EngineState, stack: &mut S warn!("loginshell_file: {}", config_path.display()); if config_path.exists() { - eval_config_contents(config_path, engine_state, stack); + eval_config_contents(config_path.into(), engine_state, stack); } } } @@ -302,7 +302,7 @@ pub(crate) fn set_config_path( Some(s) => canonicalize_with(&s.item, cwd).ok(), None => nu_path::config_dir().map(|mut p| { p.push(NUSHELL_FOLDER); - let mut p = canonicalize_with(&p, cwd).unwrap_or(p); + let mut p = canonicalize_with(&p, cwd).unwrap_or(p.into()); p.push(default_config_name); canonicalize_with(&p, cwd).unwrap_or(p) }), diff --git a/src/main.rs b/src/main.rs index f220731d1d..a5c5c5d8ef 100644 --- a/src/main.rs +++ b/src/main.rs @@ -79,7 +79,7 @@ fn main() -> Result<()> { // there is an error reading it, these values will be used. let nushell_config_path = if let Some(mut path) = nu_path::config_dir() { path.push("nushell"); - path + path.into() } else { // Not really sure what to default this to if nu_path::config_dir() returns None std::path::PathBuf::new() @@ -99,8 +99,9 @@ fn main() -> Result<()> { default: nushell_config_path.display().to_string(), }, ); - } else if let Some(old_config) = - nu_path::get_canonicalized_path(dirs::config_dir()).map(|p| p.join("nushell")) + } else if let Some(old_config) = dirs::config_dir() + .and_then(|p| p.canonicalize().ok()) + .map(|p| p.join("nushell")) { let xdg_config_empty = nushell_config_path .read_dir() @@ -125,7 +126,7 @@ fn main() -> Result<()> { let default_nushell_completions_path = if let Some(mut path) = nu_path::data_dir() { path.push("nushell"); path.push("completions"); - path + path.into() } else { std::path::PathBuf::new() }; @@ -220,7 +221,7 @@ fn main() -> Result<()> { start_time = std::time::Instant::now(); set_config_path( &mut engine_state, - &init_cwd, + init_cwd.as_ref(), "config.nu", "config-path", parsed_nu_cli_args.config_file.as_ref(), @@ -228,7 +229,7 @@ fn main() -> Result<()> { set_config_path( &mut engine_state, - &init_cwd, + init_cwd.as_ref(), "env.nu", "env-path", parsed_nu_cli_args.env_file.as_ref(), @@ -257,7 +258,7 @@ fn main() -> Result<()> { start_time = std::time::Instant::now(); // First, set up env vars as strings only - gather_parent_env_vars(&mut engine_state, &init_cwd); + gather_parent_env_vars(&mut engine_state, init_cwd.as_ref()); perf!("gather env vars", start_time, use_color); engine_state.add_env_var( diff --git a/tests/repl/test_config_path.rs b/tests/repl/test_config_path.rs index 895b1bd8bf..b66633c879 100644 --- a/tests/repl/test_config_path.rs +++ b/tests/repl/test_config_path.rs @@ -129,7 +129,7 @@ fn test_config_path_helper(playground: &mut Playground, config_dir_nushell: Path fn test_default_config_path() { Playground::setup("default_config_path", |_, playground| { let config_dir = nu_path::config_dir().expect("Could not get config directory"); - test_config_path_helper(playground, config_dir.join("nushell")); + test_config_path_helper(playground, config_dir.join("nushell").into()); }); }