diff --git a/crates/nu-cli/src/env/directory_specific_environment.rs b/crates/nu-cli/src/env/directory_specific_environment.rs index 602c7437b2..ced1c78f1d 100644 --- a/crates/nu-cli/src/env/directory_specific_environment.rs +++ b/crates/nu-cli/src/env/directory_specific_environment.rs @@ -58,21 +58,20 @@ impl DirectorySpecificEnvironment { } pub fn env_vars_to_add(&mut self) -> Result, ShellError> { - let current_dir = std::env::current_dir()?; - let mut working_dir = Some(current_dir.as_path()); + let mut working_dir = std::env::current_dir()?; let mut vars_to_add = IndexMap::new(); //If we are in the last seen directory, do nothing //If we are in a parent directory to last_seen_directory, just return without applying .nu-env in the parent directory - they were already applied earlier. //If current dir is parent to last_seen_directory, current.cmp(last) returns less //if current dir is the same as last_seen, current.cmp(last) returns equal - if current_dir.cmp(&self.last_seen_directory) != std::cmp::Ordering::Greater { + + if working_dir.cmp(&self.last_seen_directory) != std::cmp::Ordering::Greater { return Ok(vars_to_add); } - //Start in the current directory, then traverse towards the root with working_dir to see if we are in a subdirectory of a valid directory. - while let Some(wdir) = working_dir { - let wdirenv = wdir.join(".nu-env"); + while working_dir != self.last_seen_directory { + let wdirenv = working_dir.join(".nu-env"); if wdirenv.exists() { let toml_doc = self.toml_if_directory_is_trusted(&wdirenv)?; toml_doc @@ -92,76 +91,49 @@ impl DirectorySpecificEnvironment { })? .iter() .for_each(|(dir_env_key, dir_env_val)| { - if let Some(existing_val) = std::env::var_os(dir_env_key) { - let mut file = OpenOptions::new() - .write(true) - .append(true) - .create(true) - .open("toadd.txt") - .unwrap(); - - write!(&mut file, "{:?} = {:?}\n", dir_env_key, existing_val).unwrap(); - } - let dir_env_val: EnvVal = dir_env_val.as_str().unwrap_or("").into(); //This condition is to make sure variables in parent directories don't overwrite variables set by subdirectories. if !vars_to_add.contains_key(dir_env_key) { vars_to_add.insert(dir_env_key.clone(), dir_env_val); - let existing_val = std::env::var_os(dir_env_key); self.added_env_vars - .entry(wdir.to_path_buf()) + .entry(working_dir.clone()) .or_insert(IndexMap::new()) - .insert(dir_env_key.clone(), existing_val); + .insert(dir_env_key.clone(), std::env::var_os(dir_env_key)); } }); } - - //If we are in a subdirectory to last_seen_directory, we should apply all .nu-envs up until last_seen_directory - if wdir == self.last_seen_directory { - self.last_seen_directory = current_dir; - return Ok(vars_to_add); - } - - working_dir = working_dir //Keep going up in the directory structure with .parent() - .expect("This should not be None because of the while condition") - .parent(); + working_dir.pop(); } Ok(vars_to_add) } - //If the user has left directories which added env vars through .nu, we clear those vars - //once they are marked for deletion, remove them from added_env_vars pub fn cleanup_after_dir_exit( &mut self, - ) -> Result<(IndexSet, IndexMap), ShellError> { + ) -> Result>, ShellError> { let current_dir = std::env::current_dir()?; - let mut vars_to_delete = IndexSet::new(); - let mut vars_to_restore = IndexMap::new(); + let mut vars_to_cleanup = IndexMap::new(); //If we are in the same directory as last_seen, or a subdirectory to it, do nothing //If we are in a subdirectory to last seen, do nothing //If we are in a parent directory to last seen, exit .nu-envs from last seen to parent and restore old vals if self.last_seen_directory.cmp(¤t_dir) != std::cmp::Ordering::Greater { - return Ok((vars_to_delete, vars_to_restore)); + return Ok(vars_to_cleanup); } let mut working_dir = self.last_seen_directory.clone(); while working_dir != current_dir { if let Some(vars_added_by_this_directory) = self.added_env_vars.get(&working_dir) { - for (k, v) in vars_added_by_this_directory { - if let Some(v) = v { - vars_to_restore.insert(k.clone(), v.clone()); - } else { - vars_to_delete.insert(k.clone()); - } + vars_to_cleanup.insert(k.clone(), v.clone()); } + + self.added_env_vars.remove(&working_dir); } working_dir.pop(); } - Ok((vars_to_delete, vars_to_restore)) + Ok(vars_to_cleanup) } } diff --git a/crates/nu-cli/src/env/environment.rs b/crates/nu-cli/src/env/environment.rs index 52e0c6e5e6..d9b2d3ca92 100644 --- a/crates/nu-cli/src/env/environment.rs +++ b/crates/nu-cli/src/env/environment.rs @@ -60,46 +60,34 @@ impl Environment { } pub fn autoenv(&mut self) -> Result<(), ShellError> { - let (to_delete, to_restore) = self.autoenv.cleanup_after_dir_exit()?; - - - let mut file = OpenOptions::new() - .write(true) - .append(true) - .create(true) - .open("cleanup.txt") - .unwrap( - ); - - write!(&mut file, "delete {:?}\n", to_delete).unwrap(); - - for k in to_delete { - self.remove_env(&k); - } - - for (k, v) in to_restore { - self.add_env(&k, &v.to_string_lossy(), true); - } - for (k, v) in self.autoenv.env_vars_to_add()? { - self.add_env(&k, &v.to_string_lossy(), true); + std::env::set_var(&k, OsString::from(v.to_string_lossy().to_string())); + } + + let cleanup = self.autoenv.cleanup_after_dir_exit()?; + + // let mut file = OpenOptions::new() + // .write(true) + // .append(true) + // .create(true) + // .open("cleanup.txt") + // .unwrap( + // ); + + // write!(&mut file, "{:?}\n", cleanup).unwrap(); + + for (k, v) in cleanup { + if let Some(v) = v { + std::env::set_var(k, v); + } else { + std::env::remove_var(k); + } } self.autoenv.last_seen_directory = std::env::current_dir()?; Ok(()) } - fn remove_env(&mut self, key: &str) { - if let Some(Value { - value: UntaggedValue::Row(ref mut envs), - .. - }) = self.environment_vars - { - envs.entries.remove(key); - std::env::remove_var(key); - }; - } - pub fn morph(&mut self, configuration: &T) { self.environment_vars = configuration.env(); self.path_vars = configuration.path(); diff --git a/crates/nu-cli/src/env/environment_syncer.rs b/crates/nu-cli/src/env/environment_syncer.rs index 9510b96ed5..842fc49a78 100644 --- a/crates/nu-cli/src/env/environment_syncer.rs +++ b/crates/nu-cli/src/env/environment_syncer.rs @@ -1,9 +1,10 @@ use crate::context::Context; use crate::data::config::{Conf, NuConfig}; +use std::io::Write; use crate::env::environment::{Env, Environment}; use nu_source::Text; use parking_lot::Mutex; -use std::sync::Arc; +use std::{fs::OpenOptions, sync::Arc}; pub struct EnvironmentSyncer { pub env: Arc>>, @@ -53,7 +54,7 @@ impl EnvironmentSyncer { if name != "path" && name != "PATH" { // account for new env vars present in the current session // that aren't loaded from config. - environment.add_env(&name, &value, false); + environment.add_env(&name, &value, true); // clear the env var from the session // we are about to replace them