Allow def-env to hide environment variables (#921)

This commit is contained in:
Jakub Žádník 2022-02-04 20:02:03 +02:00 committed by GitHub
parent dd2d601471
commit fefd5fef12
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 1 deletions

View file

@ -133,14 +133,28 @@ fn eval_call(
}
}
}
let result = eval_block(engine_state, &mut callee_stack, block, input);
if block.redirect_env {
let caller_env_vars = caller_stack.get_env_var_names(engine_state);
// remove env vars that are present in the caller but not in the callee
// (the callee hid them)
for var in caller_env_vars.iter() {
if !callee_stack.has_env_var(engine_state, var) {
caller_stack.remove_env_var(engine_state, var);
}
}
// add new env vars from callee to caller
for env_vars in callee_stack.env_vars {
for (var, value) in env_vars {
caller_stack.add_env_var(var, value)
caller_stack.add_env_var(var, value);
}
}
}
result
} else {
// We pass caller_stack here with the knowledge that internal commands

View file

@ -140,6 +140,23 @@ impl Stack {
result
}
/// Same as get_env_vars, but returns only the names as a HashSet
pub fn get_env_var_names(&self, engine_state: &EngineState) -> HashSet<String> {
let mut result: HashSet<String> = engine_state
.env_vars
.keys()
.filter(|k| !self.env_hidden.contains(*k))
.cloned()
.collect();
for scope in &self.env_vars {
let scope_keys: HashSet<String> = scope.keys().cloned().collect();
result.extend(scope_keys);
}
result
}
pub fn get_env_var(&self, engine_state: &EngineState, name: &str) -> Option<Value> {
for scope in self.env_vars.iter().rev() {
if let Some(v) = scope.get(name) {
@ -154,6 +171,20 @@ impl Stack {
}
}
pub fn has_env_var(&self, engine_state: &EngineState, name: &str) -> bool {
for scope in self.env_vars.iter().rev() {
if scope.contains_key(name) {
return true;
}
}
if self.env_hidden.contains(name) {
false
} else {
engine_state.env_vars.contains_key(name)
}
}
pub fn remove_env_var(&mut self, engine_state: &EngineState, name: &str) -> Option<Value> {
for scope in self.env_vars.iter_mut().rev() {
if let Some(v) = scope.remove(name) {

View file

@ -207,6 +207,22 @@ fn not_def_env() -> TestResult {
)
}
#[test]
fn def_env_hiding_something() -> TestResult {
fail_test(
r#"let-env FOO = "foo"; def-env bob [] { hide FOO }; bob; $env.FOO"#,
"did you mean",
)
}
#[test]
fn def_env_then_hide() -> TestResult {
fail_test(
r#"def-env bob [] { let-env BOB = "bob" }; def-env un-bob [] { hide BOB }; bob; un-bob; $env.BOB"#,
"did you mean",
)
}
#[test]
fn export_def_env() -> TestResult {
run_test(