Fix merging child stack into parent (#12426)

# Description
Fixes #12423 where changes to mutable variables are not properly
persisted after a REPL entry.
This commit is contained in:
Ian Manske 2024-04-06 15:03:22 +00:00 committed by GitHub
parent eb36dbb091
commit 03667bdf8c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 33 additions and 19 deletions

View File

@ -337,12 +337,6 @@ impl PluginTest {
// All equal, and same length
Ok(true)
}
(Value::Range { val: a_rng, .. }, Value::Range { val: b_rng, .. }) => {
Ok(a_rng.inclusion == b_rng.inclusion
&& self.value_eq(&a_rng.from, &b_rng.from)?
&& self.value_eq(&a_rng.to, &b_rng.to)?
&& self.value_eq(&a_rng.incr, &b_rng.incr)?)
}
// Must collect lazy records to compare.
(Value::LazyRecord { val: a_val, .. }, _) => self.value_eq(&a_val.collect()?, b),
(_, Value::LazyRecord { val: b_val, .. }) => self.value_eq(a, &b_val.collect()?),

View File

@ -112,7 +112,7 @@ impl Stack {
///
/// Here it is assumed that child was created with a call to Stack::with_parent
/// with parent
pub fn with_changes_from_child(parent: Arc<Stack>, mut child: Stack) -> Stack {
pub fn with_changes_from_child(parent: Arc<Stack>, child: Stack) -> Stack {
// we're going to drop the link to the parent stack on our new stack
// so that we can unwrap the Arc as a unique reference
//
@ -121,15 +121,18 @@ impl Stack {
drop(child.parent_stack);
let mut unique_stack = Stack::unwrap_unique(parent);
unique_stack.vars.append(&mut child.vars);
unique_stack
.vars
.retain(|(var, _)| !child.parent_deletions.contains(var));
for (var, value) in child.vars {
unique_stack.add_var(var, value);
}
unique_stack.env_vars = child.env_vars;
unique_stack.env_hidden = child.env_hidden;
unique_stack.active_overlays = child.active_overlays;
unique_stack
.vars
.retain(|(var, _)| !child.parent_deletions.contains(var));
unique_stack
}
pub fn with_env(
&mut self,
env_vars: &[EnvVars],

View File

@ -8,7 +8,10 @@ use nu_protocol::{
PipelineData, Value,
};
use nu_std::load_standard_library;
use std::io::{self, BufRead, Read, Write};
use std::{
io::{self, BufRead, Read, Write},
sync::Arc,
};
/// Echo's value of env keys from args
/// Example: nu --testbin env_echo FOO BAR
@ -236,7 +239,7 @@ pub fn nu_repl() {
let source_lines = args();
let mut engine_state = get_engine_state();
let mut stack = Stack::new();
let mut top_stack = Arc::new(Stack::new());
engine_state.add_env_var("PWD".into(), Value::test_string(cwd.to_string_lossy()));
@ -245,6 +248,7 @@ pub fn nu_repl() {
load_standard_library(&mut engine_state).expect("Could not load the standard library.");
for (i, line) in source_lines.iter().enumerate() {
let mut stack = Stack::with_parent(top_stack.clone());
let cwd = nu_engine::env::current_dir(&engine_state, &stack)
.unwrap_or_else(|err| outcome_err(&engine_state, &err));
@ -324,13 +328,15 @@ pub fn nu_repl() {
let input = PipelineData::empty();
let config = engine_state.get_config();
let stack = &mut stack.start_capture();
match eval_block::<WithoutDebug>(&engine_state, stack, &block, input) {
Ok(pipeline_data) => match pipeline_data.collect_string("", config) {
Ok(s) => last_output = s,
{
let stack = &mut stack.start_capture();
match eval_block::<WithoutDebug>(&engine_state, stack, &block, input) {
Ok(pipeline_data) => match pipeline_data.collect_string("", config) {
Ok(s) => last_output = s,
Err(err) => outcome_err(&engine_state, &err),
},
Err(err) => outcome_err(&engine_state, &err),
},
Err(err) => outcome_err(&engine_state, &err),
}
}
if let Some(cwd) = stack.get_env_var(&engine_state, "PWD") {
@ -340,6 +346,7 @@ pub fn nu_repl() {
let _ = std::env::set_current_dir(path.as_ref());
engine_state.add_env_var("PWD".into(), cwd);
}
top_stack = Arc::new(Stack::with_changes_from_child(top_stack, stack));
}
outcome_ok(last_output)

View File

@ -7,6 +7,7 @@ use pretty_assertions::assert_eq;
mod environment;
mod pipeline;
mod repl;
//FIXME: jt: we need to focus some fixes on wix as the plugins will differ
#[ignore]

9
tests/shell/repl.rs Normal file
View File

@ -0,0 +1,9 @@
use nu_test_support::{nu, nu_repl_code};
use pretty_assertions::assert_eq;
#[test]
fn mut_variable() {
let lines = &["mut x = 0", "$x = 1", "$x"];
let actual = nu!(nu_repl_code(lines));
assert_eq!(actual.out, "1");
}