redirect_env

This commit is contained in:
Devyn Cairns 2024-07-04 17:16:58 -07:00
parent 49f93470a1
commit c92de3a242
No known key found for this signature in database

View File

@ -814,7 +814,7 @@ fn eval_call<D: DebugContext>(
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let EvalContext { let EvalContext {
engine_state, engine_state,
stack, stack: caller_stack,
args_base, args_base,
callee_stack, callee_stack,
redirect_out, redirect_out,
@ -822,7 +822,7 @@ fn eval_call<D: DebugContext>(
.. ..
} = ctx; } = ctx;
let stack = callee_stack.as_deref_mut().unwrap_or(stack); let stack = callee_stack.as_deref_mut().unwrap_or(caller_stack);
let args_len = stack.arguments.get_len(*args_base); let args_len = stack.arguments.get_len(*args_base);
let decl = engine_state.get_decl(decl_id); let decl = engine_state.get_decl(decl_id);
@ -830,7 +830,9 @@ fn eval_call<D: DebugContext>(
// Set up redirect modes // Set up redirect modes
let mut stack = stack.push_redirection(redirect_out.take(), redirect_err.take()); let mut stack = stack.push_redirection(redirect_out.take(), redirect_err.take());
let result = if let Some(block_id) = decl.block_id() { let result;
if let Some(block_id) = decl.block_id() {
// If the decl is a custom command, we assume that we have set up the arguments using // If the decl is a custom command, we assume that we have set up the arguments using
// new-callee-stack and push-variable instead of stack.arguments // new-callee-stack and push-variable instead of stack.arguments
// //
@ -838,7 +840,15 @@ fn eval_call<D: DebugContext>(
// what to put where. // what to put where.
let block = engine_state.get_block(block_id); let block = engine_state.get_block(block_id);
eval_block_with_early_return::<D>(engine_state, &mut stack, block, input) result = eval_block_with_early_return::<D>(engine_state, &mut stack, block, input);
drop(stack);
if block.redirect_env {
if let Some(callee_stack) = callee_stack {
redirect_env(engine_state, caller_stack, callee_stack);
}
}
} else { } else {
// should this be precalculated? ideally we just use the call builder... // should this be precalculated? ideally we just use the call builder...
let span = Span::merge_many( let span = Span::merge_many(
@ -860,15 +870,15 @@ fn eval_call<D: DebugContext>(
}; };
// Run the call // Run the call
decl.run(engine_state, &mut stack, &(&call).into(), input) result = decl.run(engine_state, &mut stack, &(&call).into(), input);
drop(stack);
}; };
// Important that this runs, to reset state post-call: // Important that this runs, to reset state post-call:
stack.arguments.leave_frame(ctx.args_base); ctx.stack.arguments.leave_frame(ctx.args_base);
*redirect_out = None; ctx.redirect_out = None;
*redirect_err = None; ctx.redirect_err = None;
drop(stack);
ctx.drop_callee_stack(); ctx.drop_callee_stack();
result result
@ -971,3 +981,22 @@ fn eval_iterate(
eval_iterate(ctx, dst, stream, end_index) eval_iterate(ctx, dst, stream, end_index)
} }
} }
/// Redirect environment from the callee stack to the caller stack
fn redirect_env(engine_state: &EngineState, caller_stack: &mut Stack, callee_stack: &Stack) {
// Grab all environment variables from the callee
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 (var, value) in callee_stack.get_stack_env_vars() {
caller_stack.add_env_var(var, value);
}
}