forked from extern/nushell
Autoenv fix: Exitscripts incorrectly running when visiting a subdirectory (#2326)
* Add test case for issue * Preliminary fix * fmt * Reorder asserts * move insertion * Touch nu-env.toml * Cleanup * touch nu-env toml * Remove touch * Change feature flags
This commit is contained in:
parent
43e9c89125
commit
3c18169f63
@ -12,6 +12,8 @@ use std::{
|
|||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//Tests reside in /nushell/tests/shell/pipeline/commands/internal.rs
|
||||||
|
|
||||||
type EnvKey = String;
|
type EnvKey = String;
|
||||||
type EnvVal = OsString;
|
type EnvVal = OsString;
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
@ -82,14 +84,11 @@ impl DirectorySpecificEnvironment {
|
|||||||
//We track which keys we set as we go up the directory hierarchy, so that we don't overwrite a value we set in a subdir.
|
//We track which keys we set as we go up the directory hierarchy, so that we don't overwrite a value we set in a subdir.
|
||||||
let mut added_keys = IndexSet::new();
|
let mut added_keys = IndexSet::new();
|
||||||
|
|
||||||
//We note which directories we pass so we can clear unvisited dirs later.
|
let mut new_visited_dirs = IndexSet::new();
|
||||||
let mut seen_directories = IndexSet::new();
|
|
||||||
|
|
||||||
//Add all .nu-envs until we reach a dir which we have already added, or we reached the root.
|
|
||||||
let mut popped = true;
|
let mut popped = true;
|
||||||
while popped && !self.visited_dirs.contains(&dir) {
|
while popped {
|
||||||
let nu_env_file = dir.join(".nu-env");
|
let nu_env_file = dir.join(".nu-env");
|
||||||
if nu_env_file.exists() {
|
if nu_env_file.exists() && !self.visited_dirs.contains(&dir) {
|
||||||
let nu_env_doc = self.toml_if_trusted(&nu_env_file)?;
|
let nu_env_doc = self.toml_if_trusted(&nu_env_file)?;
|
||||||
|
|
||||||
//add regular variables from the [env section]
|
//add regular variables from the [env section]
|
||||||
@ -98,7 +97,6 @@ impl DirectorySpecificEnvironment {
|
|||||||
self.maybe_add_key(&mut added_keys, &dir, &env_key, &env_val);
|
self.maybe_add_key(&mut added_keys, &dir, &env_key, &env_val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.visited_dirs.insert(dir.clone());
|
|
||||||
|
|
||||||
//Add variables that need to evaluate scripts to run, from [scriptvars] section
|
//Add variables that need to evaluate scripts to run, from [scriptvars] section
|
||||||
if let Some(sv) = nu_env_doc.scriptvars {
|
if let Some(sv) = nu_env_doc.scriptvars {
|
||||||
@ -122,14 +120,14 @@ impl DirectorySpecificEnvironment {
|
|||||||
self.exitscripts.insert(dir.clone(), es);
|
self.exitscripts.insert(dir.clone(), es);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
seen_directories.insert(dir.clone());
|
new_visited_dirs.insert(dir.clone());
|
||||||
popped = dir.pop();
|
popped = dir.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Time to clear out vars set by directories that we have left.
|
//Time to clear out vars set by directories that we have left.
|
||||||
let mut new_vars = IndexMap::new();
|
let mut new_vars = IndexMap::new();
|
||||||
for (dir, dirmap) in self.added_vars.drain(..) {
|
for (dir, dirmap) in self.added_vars.drain(..) {
|
||||||
if seen_directories.contains(&dir) {
|
if new_visited_dirs.contains(&dir) {
|
||||||
new_vars.insert(dir, dirmap);
|
new_vars.insert(dir, dirmap);
|
||||||
} else {
|
} else {
|
||||||
for (k, v) in dirmap {
|
for (k, v) in dirmap {
|
||||||
@ -142,17 +140,10 @@ impl DirectorySpecificEnvironment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut new_visited = IndexSet::new();
|
|
||||||
for dir in self.visited_dirs.drain(..) {
|
|
||||||
if seen_directories.contains(&dir) {
|
|
||||||
new_visited.insert(dir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Run exitscripts, can not be done in same loop as new vars as some files can contain only exitscripts
|
//Run exitscripts, can not be done in same loop as new vars as some files can contain only exitscripts
|
||||||
let mut new_exitscripts = IndexMap::new();
|
let mut new_exitscripts = IndexMap::new();
|
||||||
for (dir, scripts) in self.exitscripts.drain(..) {
|
for (dir, scripts) in self.exitscripts.drain(..) {
|
||||||
if seen_directories.contains(&dir) {
|
if new_visited_dirs.contains(&dir) {
|
||||||
new_exitscripts.insert(dir, scripts);
|
new_exitscripts.insert(dir, scripts);
|
||||||
} else {
|
} else {
|
||||||
for s in scripts {
|
for s in scripts {
|
||||||
@ -161,7 +152,7 @@ impl DirectorySpecificEnvironment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.visited_dirs = new_visited;
|
self.visited_dirs = new_visited_dirs;
|
||||||
self.exitscripts = new_exitscripts;
|
self.exitscripts = new_exitscripts;
|
||||||
self.added_vars = new_vars;
|
self.added_vars = new_vars;
|
||||||
self.last_seen_directory = current_dir()?;
|
self.last_seen_directory = current_dir()?;
|
||||||
|
@ -38,9 +38,11 @@ fn takes_rows_of_nu_value_strings_and_pipes_it_to_stdin_of_external() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "which")]
|
#[cfg(feature = "directories-support")]
|
||||||
|
#[cfg(feature = "which-support")]
|
||||||
#[test]
|
#[test]
|
||||||
fn autoenv() {
|
fn autoenv() {
|
||||||
|
use nu_test_support::fs::Stub::FileWithContent;
|
||||||
Playground::setup("autoenv_test", |dirs, sandbox| {
|
Playground::setup("autoenv_test", |dirs, sandbox| {
|
||||||
sandbox.mkdir("foo/bar");
|
sandbox.mkdir("foo/bar");
|
||||||
sandbox.mkdir("bizz/buzz");
|
sandbox.mkdir("bizz/buzz");
|
||||||
@ -105,6 +107,15 @@ fn autoenv() {
|
|||||||
);
|
);
|
||||||
assert!(actual.out.contains("hello.txt"));
|
assert!(actual.out.contains("hello.txt"));
|
||||||
|
|
||||||
|
// If inside a directory with exitscripts, entering a subdirectory should not trigger the exitscripts.
|
||||||
|
let actual = nu!(
|
||||||
|
cwd: dirs.test(),
|
||||||
|
r#"autoenv trust
|
||||||
|
cd foob
|
||||||
|
ls | where name == "bye.txt" | get name"#
|
||||||
|
);
|
||||||
|
assert!(!actual.out.contains("bye.txt"));
|
||||||
|
|
||||||
// Make sure entry scripts are run when re-visiting a directory
|
// Make sure entry scripts are run when re-visiting a directory
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: dirs.test(),
|
cwd: dirs.test(),
|
||||||
|
Loading…
Reference in New Issue
Block a user