From d9d84103b491b1d3d69cfb333072525086ecf228 Mon Sep 17 00:00:00 2001 From: Darren Schroeder <343840+fdncred@users.noreply.github.com> Date: Fri, 4 Oct 2024 06:37:30 -0500 Subject: [PATCH] Revert "Set current working directory at startup (#12953)" This reverts commit 13df0af5140674e00980ff19843c9bf2e1aa36bb. --- crates/nu-cli/src/config_files.rs | 11 +++- crates/nu-cli/src/lib.rs | 1 + crates/nu-cli/src/repl.rs | 12 +++- crates/nu-cli/tests/completions/mod.rs | 59 +++++++++---------- .../support/completions_helpers.rs | 11 ++-- crates/nu-cmd-base/src/hook.rs | 4 +- crates/nu-cmd-base/src/util.rs | 21 +++++++ crates/nu-cmd-lang/src/example_support.rs | 2 +- crates/nu-command/src/filesystem/cd.rs | 11 ++-- crates/nu-command/src/filesystem/start.rs | 5 +- crates/nu-protocol/src/engine/engine_state.rs | 11 +++- crates/nu-std/src/lib.rs | 3 +- src/config_files.rs | 22 +++++-- src/main.rs | 33 +---------- src/test_bins.rs | 6 +- tests/shell/pipeline/commands/external.rs | 6 +- 16 files changed, 127 insertions(+), 91 deletions(-) diff --git a/crates/nu-cli/src/config_files.rs b/crates/nu-cli/src/config_files.rs index 998686d870..427f503a6f 100644 --- a/crates/nu-cli/src/config_files.rs +++ b/crates/nu-cli/src/config_files.rs @@ -228,8 +228,15 @@ pub fn eval_config_contents( engine_state.file = prev_file; // Merge the environment in case env vars changed in the config - if let Err(e) = engine_state.merge_env(stack) { - report_shell_error(engine_state, &e); + match engine_state.cwd(Some(stack)) { + Ok(cwd) => { + if let Err(e) = engine_state.merge_env(stack, cwd) { + report_shell_error(engine_state, &e); + } + } + Err(e) => { + report_shell_error(engine_state, &e); + } } } } diff --git a/crates/nu-cli/src/lib.rs b/crates/nu-cli/src/lib.rs index 3fe293a030..d584802cfb 100644 --- a/crates/nu-cli/src/lib.rs +++ b/crates/nu-cli/src/lib.rs @@ -21,6 +21,7 @@ pub use config_files::eval_config_contents; pub use eval_cmds::{evaluate_commands, EvaluateCommandsOpts}; pub use eval_file::evaluate_file; pub use menus::NuHelpCompleter; +pub use nu_cmd_base::util::get_init_cwd; pub use nu_highlight::NuHighlight; pub use print::Print; pub use prompt::NushellPrompt; diff --git a/crates/nu-cli/src/repl.rs b/crates/nu-cli/src/repl.rs index 4ea650074e..2cbbb4df4d 100644 --- a/crates/nu-cli/src/repl.rs +++ b/crates/nu-cli/src/repl.rs @@ -16,7 +16,10 @@ use crate::{ use crossterm::cursor::SetCursorStyle; use log::{error, trace, warn}; use miette::{ErrReport, IntoDiagnostic, Result}; -use nu_cmd_base::{hook::eval_hook, util::get_editor}; +use nu_cmd_base::{ + hook::eval_hook, + util::{get_editor, get_guaranteed_cwd}, +}; use nu_color_config::StyleComputer; #[allow(deprecated)] use nu_engine::{convert_env_values, current_dir_str, env_to_strings}; @@ -109,7 +112,8 @@ pub fn evaluate_repl( PipelineData::empty(), false, ); - engine_state.merge_env(&mut unique_stack)?; + let cwd = get_guaranteed_cwd(engine_state, &unique_stack); + engine_state.merge_env(&mut unique_stack, cwd)?; } let hostname = System::host_name(); @@ -276,10 +280,12 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) { hostname, } = ctx; + let cwd = get_guaranteed_cwd(engine_state, &stack); + let mut start_time = std::time::Instant::now(); // Before doing anything, merge the environment from the previous REPL iteration into the // permanent state. - if let Err(err) = engine_state.merge_env(&mut stack) { + if let Err(err) = engine_state.merge_env(&mut stack, cwd) { report_shell_error(engine_state, &err); } // Check whether $env.NU_DISABLE_IR is set, so that the user can change it in the REPL diff --git a/crates/nu-cli/tests/completions/mod.rs b/crates/nu-cli/tests/completions/mod.rs index 8e89239663..001a6c0599 100644 --- a/crates/nu-cli/tests/completions/mod.rs +++ b/crates/nu-cli/tests/completions/mod.rs @@ -18,11 +18,11 @@ use support::{ #[fixture] fn completer() -> NuCompleter { // Create a new engine - let (_, _, mut engine, mut stack) = new_engine(); + let (dir, _, mut engine, mut stack) = new_engine(); // Add record value as example let record = "def tst [--mod -s] {}"; - assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok()); // Instantiate a new completer NuCompleter::new(Arc::new(engine), Arc::new(stack)) @@ -31,12 +31,11 @@ fn completer() -> NuCompleter { #[fixture] fn completer_strings() -> NuCompleter { // Create a new engine - let (_, _, mut engine, mut stack) = new_engine(); - + let (dir, _, mut engine, mut stack) = new_engine(); // Add record value as example let record = r#"def animals [] { ["cat", "dog", "eel" ] } def my-command [animal: string@animals] { print $animal }"#; - assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok()); // Instantiate a new completer NuCompleter::new(Arc::new(engine), Arc::new(stack)) @@ -45,7 +44,7 @@ fn completer_strings() -> NuCompleter { #[fixture] fn extern_completer() -> NuCompleter { // Create a new engine - let (_, _, mut engine, mut stack) = new_engine(); + let (dir, _, mut engine, mut stack) = new_engine(); // Add record value as example let record = r#" @@ -56,7 +55,7 @@ fn extern_completer() -> NuCompleter { -b: string@animals ] "#; - assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok()); // Instantiate a new completer NuCompleter::new(Arc::new(engine), Arc::new(stack)) @@ -65,7 +64,7 @@ fn extern_completer() -> NuCompleter { #[fixture] fn completer_strings_with_options() -> NuCompleter { // Create a new engine - let (_, _, mut engine, mut stack) = new_engine(); + let (dir, _, mut engine, mut stack) = new_engine(); // Add record value as example let record = r#" # To test that the config setting has no effect on the custom completions @@ -82,7 +81,7 @@ fn completer_strings_with_options() -> NuCompleter { } } def my-command [animal: string@animals] { print $animal }"#; - assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok()); // Instantiate a new completer NuCompleter::new(Arc::new(engine), Arc::new(stack)) @@ -91,7 +90,7 @@ fn completer_strings_with_options() -> NuCompleter { #[fixture] fn custom_completer() -> NuCompleter { // Create a new engine - let (_, _, mut engine, mut stack) = new_engine(); + let (dir, _, mut engine, mut stack) = new_engine(); // Add record value as example let record = r#" @@ -105,7 +104,7 @@ fn custom_completer() -> NuCompleter { completer: $external_completer } "#; - assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok()); // Instantiate a new completer NuCompleter::new(Arc::new(engine), Arc::new(stack)) @@ -114,7 +113,7 @@ fn custom_completer() -> NuCompleter { #[fixture] fn subcommand_completer() -> NuCompleter { // Create a new engine - let (_, _, mut engine, mut stack) = new_engine(); + let (dir, _, mut engine, mut stack) = new_engine(); let commands = r#" $env.config.completions.algorithm = "fuzzy" @@ -124,7 +123,7 @@ fn subcommand_completer() -> NuCompleter { def "foo aabcrr" [] {} def food [] {} "#; - assert!(support::merge_input(commands.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(commands.as_bytes(), &mut engine, &mut stack, dir).is_ok()); // Instantiate a new completer NuCompleter::new(Arc::new(engine), Arc::new(stack)) @@ -134,13 +133,13 @@ fn subcommand_completer() -> NuCompleter { #[fixture] fn fuzzy_alpha_sort_completer() -> NuCompleter { // Create a new engine - let (_, _, mut engine, mut stack) = new_engine(); + let (dir, _, mut engine, mut stack) = new_engine(); let config = r#" $env.config.completions.algorithm = "fuzzy" $env.config.completions.sort = "alphabetical" "#; - assert!(support::merge_input(config.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(config.as_bytes(), &mut engine, &mut stack, dir).is_ok()); // Instantiate a new completer NuCompleter::new(Arc::new(engine), Arc::new(stack)) @@ -1197,11 +1196,11 @@ fn folder_with_directorycompletions_do_not_collapse_dots() { #[test] fn variables_completions() { // Create a new engine - let (_, _, mut engine, mut stack) = new_engine(); + let (dir, _, mut engine, mut stack) = new_engine(); // Add record value as example let record = "let actor = { name: 'Tom Hardy', age: 44 }"; - assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok()); // Instantiate a new completer let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack)); @@ -1312,11 +1311,11 @@ fn variables_completions() { #[test] fn alias_of_command_and_flags() { - let (_, _, mut engine, mut stack) = new_engine(); + let (dir, _, mut engine, mut stack) = new_engine(); // Create an alias let alias = r#"alias ll = ls -l"#; - assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok()); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack)); @@ -1331,11 +1330,11 @@ fn alias_of_command_and_flags() { #[test] fn alias_of_basic_command() { - let (_, _, mut engine, mut stack) = new_engine(); + let (dir, _, mut engine, mut stack) = new_engine(); // Create an alias let alias = r#"alias ll = ls "#; - assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok()); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack)); @@ -1350,14 +1349,14 @@ fn alias_of_basic_command() { #[test] fn alias_of_another_alias() { - let (_, _, mut engine, mut stack) = new_engine(); + let (dir, _, mut engine, mut stack) = new_engine(); // Create an alias let alias = r#"alias ll = ls -la"#; - assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir.clone()).is_ok()); // Create the second alias let alias = r#"alias lf = ll -f"#; - assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok()); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack)); @@ -1374,7 +1373,7 @@ fn run_external_completion(completer: &str, input: &str) -> Vec { let completer = format!("$env.config.completions.external.completer = {completer}"); // Create a new engine - let (_, _, mut engine_state, mut stack) = new_engine(); + let (dir, _, mut engine_state, mut stack) = new_engine(); let (block, delta) = { let mut working_set = StateWorkingSet::new(&engine_state); let block = parse(&mut working_set, None, completer.as_bytes(), false); @@ -1390,7 +1389,7 @@ fn run_external_completion(completer: &str, input: &str) -> Vec { ); // Merge environment into the permanent state - assert!(engine_state.merge_env(&mut stack).is_ok()); + assert!(engine_state.merge_env(&mut stack, &dir).is_ok()); // Instantiate a new completer let mut completer = NuCompleter::new(Arc::new(engine_state), Arc::new(stack)); @@ -1579,11 +1578,11 @@ fn sort_fuzzy_completions_in_alphabetical_order(mut fuzzy_alpha_sort_completer: #[ignore = "was reverted, still needs fixing"] #[rstest] fn alias_offset_bug_7648() { - let (_, _, mut engine, mut stack) = new_engine(); + let (dir, _, mut engine, mut stack) = new_engine(); // Create an alias let alias = r#"alias ea = ^$env.EDITOR /tmp/test.s"#; - assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok()); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack)); @@ -1598,11 +1597,11 @@ fn alias_offset_bug_7648() { #[ignore = "was reverted, still needs fixing"] #[rstest] fn alias_offset_bug_7754() { - let (_, _, mut engine, mut stack) = new_engine(); + let (dir, _, mut engine, mut stack) = new_engine(); // Create an alias let alias = r#"alias ll = ls -l"#; - assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack).is_ok()); + assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok()); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack)); diff --git a/crates/nu-cli/tests/completions/support/completions_helpers.rs b/crates/nu-cli/tests/completions/support/completions_helpers.rs index 983dd778d2..c6c2cba2a8 100644 --- a/crates/nu-cli/tests/completions/support/completions_helpers.rs +++ b/crates/nu-cli/tests/completions/support/completions_helpers.rs @@ -63,7 +63,7 @@ pub fn new_engine() -> (AbsolutePathBuf, String, EngineState, Stack) { ); // Merge environment into the permanent state - let merge_result = engine_state.merge_env(&mut stack); + let merge_result = engine_state.merge_env(&mut stack, &dir); assert!(merge_result.is_ok()); (dir, dir_str, engine_state, stack) @@ -109,7 +109,7 @@ pub fn new_dotnu_engine() -> (AbsolutePathBuf, String, EngineState, Stack) { ); // Merge environment into the permanent state - let merge_result = engine_state.merge_env(&mut stack); + let merge_result = engine_state.merge_env(&mut stack, &dir); assert!(merge_result.is_ok()); (dir, dir_str, engine_state, stack) @@ -144,7 +144,7 @@ pub fn new_quote_engine() -> (AbsolutePathBuf, String, EngineState, Stack) { ); // Merge environment into the permanent state - let merge_result = engine_state.merge_env(&mut stack); + let merge_result = engine_state.merge_env(&mut stack, &dir); assert!(merge_result.is_ok()); (dir, dir_str, engine_state, stack) @@ -179,7 +179,7 @@ pub fn new_partial_engine() -> (AbsolutePathBuf, String, EngineState, Stack) { ); // Merge environment into the permanent state - let merge_result = engine_state.merge_env(&mut stack); + let merge_result = engine_state.merge_env(&mut stack, &dir); assert!(merge_result.is_ok()); (dir, dir_str, engine_state, stack) @@ -223,6 +223,7 @@ pub fn merge_input( input: &[u8], engine_state: &mut EngineState, stack: &mut Stack, + dir: AbsolutePathBuf, ) -> Result<(), ShellError> { let (block, delta) = { let mut working_set = StateWorkingSet::new(engine_state); @@ -245,5 +246,5 @@ pub fn merge_input( .is_ok()); // Merge environment into the permanent state - engine_state.merge_env(stack) + engine_state.merge_env(stack, &dir) } diff --git a/crates/nu-cmd-base/src/hook.rs b/crates/nu-cmd-base/src/hook.rs index e9637d16ad..3fd3eab84f 100644 --- a/crates/nu-cmd-base/src/hook.rs +++ b/crates/nu-cmd-base/src/hook.rs @@ -1,3 +1,4 @@ +use crate::util::get_guaranteed_cwd; use miette::Result; use nu_engine::{eval_block, eval_block_with_early_return}; use nu_parser::parse; @@ -278,7 +279,8 @@ pub fn eval_hook( } } - engine_state.merge_env(stack)?; + let cwd = get_guaranteed_cwd(engine_state, stack); + engine_state.merge_env(stack, cwd)?; Ok(output) } diff --git a/crates/nu-cmd-base/src/util.rs b/crates/nu-cmd-base/src/util.rs index a2af4d4773..f778fe4679 100644 --- a/crates/nu-cmd-base/src/util.rs +++ b/crates/nu-cmd-base/src/util.rs @@ -1,9 +1,30 @@ +use nu_path::AbsolutePathBuf; use nu_protocol::{ engine::{EngineState, Stack}, Range, ShellError, Span, Value, }; use std::ops::Bound; +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) -> AbsolutePathBuf { + engine_state + .cwd(Some(stack)) + .ok() + .unwrap_or_else(get_init_cwd) +} + type MakeRangeError = fn(&str, Span) -> ShellError; /// Returns a inclusive pair of boundary in given `range`. diff --git a/crates/nu-cmd-lang/src/example_support.rs b/crates/nu-cmd-lang/src/example_support.rs index c4d532058a..e430c35c43 100644 --- a/crates/nu-cmd-lang/src/example_support.rs +++ b/crates/nu-cmd-lang/src/example_support.rs @@ -149,7 +149,7 @@ pub fn check_example_evaluates_to_expected_output( stack.add_env_var("PWD".to_string(), Value::test_string(cwd.to_string_lossy())); engine_state - .merge_env(&mut stack) + .merge_env(&mut stack, cwd) .expect("Error merging environment"); let empty_input = PipelineData::empty(); diff --git a/crates/nu-command/src/filesystem/cd.rs b/crates/nu-command/src/filesystem/cd.rs index 2af932bcb4..84f6f3d6bd 100644 --- a/crates/nu-command/src/filesystem/cd.rs +++ b/crates/nu-command/src/filesystem/cd.rs @@ -1,3 +1,4 @@ +use nu_cmd_base::util::get_init_cwd; use nu_engine::command_prelude::*; use nu_utils::filesystem::{have_permission, PermissionResult}; @@ -40,14 +41,12 @@ impl Command for Cd { let physical = call.has_flag(engine_state, stack, "physical")?; let path_val: Option> = call.opt(engine_state, stack, 0)?; - // If getting PWD failed, default to the home directory. The user can - // use `cd` to reset PWD to a good state. + // If getting PWD failed, default to the initial directory. This way, the + // user can use `cd` to recover PWD to a good state. let cwd = engine_state .cwd(Some(stack)) .ok() - .or_else(nu_path::home_dir) - .map(|path| path.into_std_path_buf()) - .unwrap_or_default(); + .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/start.rs b/crates/nu-command/src/filesystem/start.rs index b295b5f368..577fe128ba 100644 --- a/crates/nu-command/src/filesystem/start.rs +++ b/crates/nu-command/src/filesystem/start.rs @@ -58,8 +58,9 @@ impl Command for Start { open_path(url.as_str(), engine_state, stack, path.span)?; } else { // try to distinguish between file not found and opening url without prefix - let cwd = engine_state.cwd(Some(stack))?; - if let Ok(canon_path) = canonicalize_with(path_no_whitespace, cwd) { + if let Ok(canon_path) = + canonicalize_with(path_no_whitespace, std::env::current_dir()?.as_path()) + { open_path(canon_path, engine_state, stack, path.span)?; } else { // open crate does not allow opening URL without prefix diff --git a/crates/nu-protocol/src/engine/engine_state.rs b/crates/nu-protocol/src/engine/engine_state.rs index ec616c3403..ab850b0d27 100644 --- a/crates/nu-protocol/src/engine/engine_state.rs +++ b/crates/nu-protocol/src/engine/engine_state.rs @@ -17,7 +17,7 @@ use nu_path::AbsolutePathBuf; use std::{ collections::HashMap, num::NonZeroUsize, - path::PathBuf, + path::{Path, PathBuf}, sync::{ atomic::{AtomicBool, AtomicU32, Ordering}, Arc, Mutex, MutexGuard, PoisonError, @@ -307,7 +307,11 @@ impl EngineState { } /// Merge the environment from the runtime Stack into the engine state - pub fn merge_env(&mut self, stack: &mut Stack) -> Result<(), ShellError> { + pub fn merge_env( + &mut self, + stack: &mut Stack, + cwd: impl AsRef, + ) -> Result<(), ShellError> { for mut scope in stack.env_vars.drain(..) { for (overlay_name, mut env) in Arc::make_mut(&mut scope).drain() { if let Some(env_vars) = Arc::make_mut(&mut self.env_vars).get_mut(&overlay_name) { @@ -320,6 +324,9 @@ impl EngineState { } } + // TODO: better error + std::env::set_current_dir(cwd)?; + if let Some(config) = stack.config.take() { // If config was updated in the stack, replace it. self.config = config; diff --git a/crates/nu-std/src/lib.rs b/crates/nu-std/src/lib.rs index ec5ced55ec..695786b8e8 100644 --- a/crates/nu-std/src/lib.rs +++ b/crates/nu-std/src/lib.rs @@ -99,7 +99,8 @@ use std/deprecated_dirs [ eval_block::(engine_state, &mut stack, &block, pipeline_data)?; - engine_state.merge_env(&mut stack)?; + let cwd = engine_state.cwd(Some(&stack))?; + engine_state.merge_env(&mut stack, cwd)?; Ok(()) } diff --git a/src/config_files.rs b/src/config_files.rs index 1dd2a4b66d..47d1c2d2fb 100644 --- a/src/config_files.rs +++ b/src/config_files.rs @@ -172,8 +172,15 @@ pub(crate) fn read_default_env_file(engine_state: &mut EngineState, stack: &mut ); // Merge the environment in case env vars changed in the config - if let Err(e) = engine_state.merge_env(stack) { - report_shell_error(engine_state, &e); + match engine_state.cwd(Some(stack)) { + Ok(cwd) => { + if let Err(e) = engine_state.merge_env(stack, cwd) { + report_shell_error(engine_state, &e); + } + } + Err(e) => { + report_shell_error(engine_state, &e); + } } } @@ -250,8 +257,15 @@ fn eval_default_config( ); // Merge the environment in case env vars changed in the config - if let Err(e) = engine_state.merge_env(stack) { - report_shell_error(engine_state, &e); + match engine_state.cwd(Some(stack)) { + Ok(cwd) => { + if let Err(e) = engine_state.merge_env(stack, cwd) { + report_shell_error(engine_state, &e); + } + } + Err(e) => { + report_shell_error(engine_state, &e); + } } } diff --git a/src/main.rs b/src/main.rs index 839c32b66a..303fb50e9f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,6 +21,7 @@ use command::gather_commandline_args; use log::{trace, Level}; use miette::Result; use nu_cli::gather_parent_env_vars; +use nu_cmd_base::util::get_init_cwd; use nu_lsp::LanguageServer; use nu_path::canonicalize_with; use nu_protocol::{ @@ -43,27 +44,6 @@ fn get_engine_state() -> EngineState { nu_explore::add_explore_context(engine_state) } -/// Get the directory where the Nushell executable is located. -fn current_exe_directory() -> PathBuf { - let mut path = std::env::current_exe().expect("current_exe() should succeed"); - path.pop(); - path -} - -/// Get the current working directory from the environment. -fn current_dir_from_environment() -> PathBuf { - if let Ok(cwd) = std::env::current_dir() { - return cwd; - } - if let Ok(cwd) = std::env::var("PWD") { - return cwd.into(); - } - if let Some(home) = nu_path::home_dir() { - return home.into_std_path_buf(); - } - current_exe_directory() -} - fn main() -> Result<()> { let entire_start_time = std::time::Instant::now(); let mut start_time = std::time::Instant::now(); @@ -74,11 +54,10 @@ fn main() -> Result<()> { miette_hook(x); })); + // Get initial current working directory. + let init_cwd = get_init_cwd(); let mut engine_state = get_engine_state(); - // Get the current working directory from the environment. - let init_cwd = current_dir_from_environment(); - // Custom additions let delta = { let mut working_set = nu_protocol::engine::StateWorkingSet::new(&engine_state); @@ -340,12 +319,6 @@ fn main() -> Result<()> { _ => std::process::exit(1), } std::process::exit(0) - } else { - // If we're not running a testbin, set the current working directory to - // the location of the Nushell executable. This prevents the OS from - // locking the directory where the user launched Nushell. - std::env::set_current_dir(current_exe_directory()) - .expect("set_current_dir() should succeed"); } perf!("run test_bins", start_time, use_color); diff --git a/src/test_bins.rs b/src/test_bins.rs index c4ba37ed8e..fe1f46f79a 100644 --- a/src/test_bins.rs +++ b/src/test_bins.rs @@ -256,9 +256,13 @@ pub fn nu_repl() { for (i, line) in source_lines.iter().enumerate() { let mut stack = Stack::with_parent(top_stack.clone()); + let cwd = engine_state + .cwd(Some(&stack)) + .unwrap_or_else(|err| outcome_err(&engine_state, &err)); + // Before doing anything, merge the environment from the previous REPL iteration into the // permanent state. - if let Err(err) = engine_state.merge_env(&mut stack) { + if let Err(err) = engine_state.merge_env(&mut stack, &cwd) { outcome_err(&engine_state, &err); } diff --git a/tests/shell/pipeline/commands/external.rs b/tests/shell/pipeline/commands/external.rs index 461cd1638b..9a19f4b3a7 100644 --- a/tests/shell/pipeline/commands/external.rs +++ b/tests/shell/pipeline/commands/external.rs @@ -131,9 +131,9 @@ fn command_not_found_error_suggests_typo_fix() { #[test] fn command_not_found_error_recognizes_non_executable_file() { let actual = nu!("./Cargo.toml"); - assert!(actual - .err - .contains("is neither a Nushell built-in or a known external command")); + assert!(actual.err.contains( + "refers to a file that is not executable. Did you forget to to set execute permissions?" + )); } #[test]