diff --git a/crates/nu-cli/src/cli.rs b/crates/nu-cli/src/cli.rs index cd14373b71..bd5097812e 100644 --- a/crates/nu-cli/src/cli.rs +++ b/crates/nu-cli/src/cli.rs @@ -889,7 +889,6 @@ async fn process_line( trace!("{:#?}", classified_block); let env = ctx.get_env(); - match run_block( &classified_block.block, ctx, diff --git a/crates/nu-cli/src/env/directory_specific_environment.rs b/crates/nu-cli/src/env/directory_specific_environment.rs index 0a7f054e61..b213809060 100644 --- a/crates/nu-cli/src/env/directory_specific_environment.rs +++ b/crates/nu-cli/src/env/directory_specific_environment.rs @@ -120,4 +120,31 @@ impl DirectorySpecificEnvironment { Ok(vars_to_add) } + + //If the user has left directories which added env vars through .nu, we clear those vars + pub fn env_vars_to_delete(&mut self) -> std::io::Result> { + let current_dir = std::env::current_dir()?; + + //Gather up all environment variables that should be deleted. + //If we are not in a directory or one of its subdirectories, mark the env_vals it maps to for removal. + let vars_to_delete = self.added_env_vars.iter().fold( + Vec::new(), + |mut vars_to_delete, (directory, env_vars)| { + let mut working_dir = Some(current_dir.as_path()); + + while let Some(wdir) = working_dir { + if &wdir == directory { + return vars_to_delete; + } else { + working_dir = working_dir.unwrap().parent(); + } + } + //only delete vars from directories we are not in + vars_to_delete.extend(env_vars.clone()); + vars_to_delete + }, + ); + + Ok(vars_to_delete) + } } diff --git a/crates/nu-cli/src/env/environment.rs b/crates/nu-cli/src/env/environment.rs index 99e6f998be..a32735cdf4 100644 --- a/crates/nu-cli/src/env/environment.rs +++ b/crates/nu-cli/src/env/environment.rs @@ -59,18 +59,33 @@ impl Environment { } pub fn maintain_directory_environment(&mut self) -> std::io::Result<()> { + self.direnv.env_vars_to_delete()?.iter().for_each(|k| { + self.remove_env(&k); + }); self.direnv.env_vars_to_add()?.iter().for_each(|(k, v)| { self.add_env(&k, &v, true); }); - - self.direnv.overwritten_values_to_restore()?.iter().for_each(|(k, v)| { - self.add_env(&k, &v, true); - }); + self.direnv + .overwritten_values_to_restore()? + .iter() + .for_each(|(k, v)| { + self.add_env(&k, &v, true); + }); Ok(()) } + fn remove_env(&mut self, key: &str) { + if let Some(Value { + value: UntaggedValue::Row(ref mut envs), + tag: _, + }) = self.environment_vars + { + envs.entries.remove(key); + }; + } + pub fn morph(&mut self, configuration: &T) { self.environment_vars = configuration.env(); self.path_vars = configuration.path(); diff --git a/post.org b/post.org index 26c20dab63..96bea39dbc 100644 --- a/post.org +++ b/post.org @@ -13,22 +13,16 @@ In order for a .nu-file to be read, the directory it is in must be listed in the nu_env_dirs = ["/home/sam", "/home/sam/github", "/home/sam/github/test"] ``` This was implemented for the sake of security. I do not believe that it is appropiate for nushell to pick up random .nu-files unless -the user has explicitly said that it's alright. An adversary could hide a .nu-file in an otherwise unsuspicous folder that you download, +the user has explicitly said that it's alright. An adversary could hide a .nu-file in an otherwise unsuspicious folder that you download, and now you suddenly have nushell picking up whatever environment variables they set. This meant that the code necessarily become more involved than just looking for a .nu-file in the current directory and applying its variables, but this extra code also allowed for some other nice features and behavior which is listed below. Behavior: -- If you are in a subdirectory to a directory with a .nu-file, the vars in that .nu-file are applied. +- If you are in a directory, or a subdirectory to a directory with a .nu-file, the vars in that .nu-file are applied. - If you leave a directory which set some variables, the variables are unset. - If a directory contains a .nu with an environment variable already set, the old value will be overwritten with the value from the .nu. This holds even if the old value was set by a .nu in a parent directory. - The overwritten value is restored when you leave the directory. - - TODO: What happens if you overwrite twice? - -Questions: -`remove_env()` accesses the environment directly to remove variables. -Just using what I think was expected, envs.entries.remove(key), does not work. -If this is a problem, how can I make it work better with existing code? ----