From 34e2b49c3bd3a3ca9ac7fdebeade4aa97c048d38 Mon Sep 17 00:00:00 2001 From: prsabahrami Date: Fri, 14 Feb 2025 10:38:47 -0500 Subject: [PATCH 1/5] exit shell upon exit command --- crates/deno_task_shell/src/shell/types.rs | 7 +++++++ crates/shell/src/execute.rs | 19 ++++++++----------- crates/shell/src/main.rs | 19 +++++++++---------- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/crates/deno_task_shell/src/shell/types.rs b/crates/deno_task_shell/src/shell/types.rs index f56d199..472b365 100644 --- a/crates/deno_task_shell/src/shell/types.rs +++ b/crates/deno_task_shell/src/shell/types.rs @@ -428,6 +428,13 @@ impl ExecuteResult { ExecuteResult::Continue(_, changes, handles) => (handles, changes), } } + + pub fn exit_code(&self) -> i32 { + match self { + ExecuteResult::Exit(code, _) => *code, + ExecuteResult::Continue(code, _, _) => *code, + } + } } /// Reader side of a pipe. diff --git a/crates/shell/src/execute.rs b/crates/shell/src/execute.rs index 2683615..f45209a 100644 --- a/crates/shell/src/execute.rs +++ b/crates/shell/src/execute.rs @@ -41,18 +41,15 @@ pub async fn execute( text: &str, filename: Option, state: &mut ShellState, -) -> miette::Result { +) -> miette::Result { let result = execute_inner(text, filename, state.clone()).await?; - match result { - ExecuteResult::Continue(exit_code, changes, _) => { - // set CWD to the last command's CWD - state.apply_changes(&changes); - std::env::set_current_dir(state.cwd()) - .into_diagnostic() - .context("Failed to set CWD")?; - Ok(exit_code) - } - ExecuteResult::Exit(exit_code, _) => Ok(exit_code), + if let ExecuteResult::Continue(_, changes, _) = &result { + // set CWD to the last command's CWD + state.apply_changes(changes); + std::env::set_current_dir(state.cwd()) + .into_diagnostic() + .context("Failed to set CWD")?; } + Ok(result) } diff --git a/crates/shell/src/main.rs b/crates/shell/src/main.rs index 502b438..6439e7d 100644 --- a/crates/shell/src/main.rs +++ b/crates/shell/src/main.rs @@ -4,6 +4,7 @@ use std::path::PathBuf; use clap::Parser; use deno_task_shell::parser::debug_parse; +use deno_task_shell::ExecuteResult; use deno_task_shell::ShellState; use miette::Context; use miette::IntoDiagnostic; @@ -73,14 +74,14 @@ async fn init_state(norc: bool, var_args: &[String]) -> miette::Result, norc: bool, args: &[String]) -> rl.add_history_entry(line.as_str()).into_diagnostic()?; // Process the input (here we just echo it back) - let prev_exit_code = execute(&line, None, &mut state) + let result = execute(&line, None, &mut state) .await .context("Failed to execute")?; - state.set_last_command_exit_code(prev_exit_code); + state.set_last_command_exit_code(result.exit_code()); - // Check for exit command - if line.trim().eq_ignore_ascii_case("exit") { - println!("Exiting..."); - break; + if let ExecuteResult::Exit(exit_code, _) = result { + std::process::exit(exit_code); } } Err(ReadlineError::Interrupted) => { @@ -235,13 +234,13 @@ async fn main() -> miette::Result<()> { return Ok(()); } - let exit_code = execute(&script_text, filename, &mut state).await?; + let result = execute(&script_text, filename, &mut state).await?; if options.interact { interactive(Some(state), options.norc, &options.args).await?; } - std::process::exit(exit_code); + std::process::exit(result.exit_code()); } } } From b0155bd00400aeeae526420e972826451c84b981 Mon Sep 17 00:00:00 2001 From: prsabahrami Date: Fri, 14 Feb 2025 12:06:24 -0500 Subject: [PATCH 2/5] fix source issue with exit --- .../src/shell/commands/exit.rs | 4 +- crates/deno_task_shell/src/shell/execute.rs | 51 ++++++++++++------- crates/deno_task_shell/src/shell/types.rs | 12 ++--- crates/shell/src/commands/set.rs | 2 +- crates/shell/src/execute.rs | 19 ++++--- crates/shell/src/main.rs | 2 +- scripts/exit.sh | 2 + 7 files changed, 55 insertions(+), 37 deletions(-) create mode 100644 scripts/exit.sh diff --git a/crates/deno_task_shell/src/shell/commands/exit.rs b/crates/deno_task_shell/src/shell/commands/exit.rs index 44ab7fb..004f416 100644 --- a/crates/deno_task_shell/src/shell/commands/exit.rs +++ b/crates/deno_task_shell/src/shell/commands/exit.rs @@ -19,10 +19,10 @@ impl ShellCommand for ExitCommand { mut context: ShellCommandContext, ) -> LocalBoxFuture<'static, ExecuteResult> { let result = match execute_exit(context.args) { - Ok(code) => ExecuteResult::Exit(code, Vec::new()), + Ok(code) => ExecuteResult::Exit(code, Vec::new(), Vec::new()), Err(err) => { context.stderr.write_line(&format!("exit: {err}")).unwrap(); - ExecuteResult::Exit(2, Vec::new()) + ExecuteResult::Exit(2, Vec::new(), Vec::new()) } }; Box::pin(futures::future::ready(result)) diff --git a/crates/deno_task_shell/src/shell/execute.rs b/crates/deno_task_shell/src/shell/execute.rs index b13bf82..7db3330 100644 --- a/crates/deno_task_shell/src/shell/execute.rs +++ b/crates/deno_task_shell/src/shell/execute.rs @@ -135,7 +135,7 @@ pub async fn execute_with_pipes( .await; match result { - ExecuteResult::Exit(code, _) => code, + ExecuteResult::Exit(code, _, _) => code, ExecuteResult::Continue(exit_code, _, _) => exit_code, } } @@ -183,7 +183,10 @@ pub fn execute_sequential_list( ) .await; match result { - ExecuteResult::Exit(exit_code, handles) => { + ExecuteResult::Exit(exit_code, changes, handles) => { + state.apply_changes(&changes); + state.set_shell_var("?", &exit_code.to_string()); + final_changes.extend(changes); async_handles.extend(handles); final_exit_code = exit_code; was_exit = true; @@ -215,7 +218,7 @@ pub fn execute_sequential_list( } if was_exit { - ExecuteResult::Exit(final_exit_code, async_handles) + ExecuteResult::Exit(final_exit_code, final_changes, async_handles) } else { ExecuteResult::Continue(final_exit_code, final_changes, async_handles) } @@ -287,7 +290,7 @@ fn execute_sequence( ) .await; let (exit_code, mut async_handles) = match first_result { - ExecuteResult::Exit(_, _) => return first_result, + ExecuteResult::Exit(_, _, _) => return first_result, ExecuteResult::Continue(exit_code, sub_changes, async_handles) => { changes.extend(sub_changes); (exit_code, async_handles) @@ -317,9 +320,10 @@ fn execute_sequence( let next_result = execute_sequence(next, state, stdin, stdout, stderr).await; match next_result { - ExecuteResult::Exit(code, sub_handles) => { + ExecuteResult::Exit(code, sub_changes, sub_handles) => { + changes.extend(sub_changes); async_handles.extend(sub_handles); - ExecuteResult::Exit(code, async_handles) + ExecuteResult::Exit(code, changes, async_handles) } ExecuteResult::Continue(exit_code, sub_changes, sub_handles) => { changes.extend(sub_changes); @@ -350,7 +354,9 @@ async fn execute_pipeline( execute_pipeline_inner(pipeline.inner, state, stdin, stdout, stderr).await; if pipeline.negated { match result { - ExecuteResult::Exit(code, handles) => ExecuteResult::Exit(code, handles), + ExecuteResult::Exit(code, changes, handles) => { + ExecuteResult::Exit(code, changes, handles) + } ExecuteResult::Continue(code, changes, handles) => { let new_code = if code == 0 { 1 } else { 0 }; ExecuteResult::Continue(new_code, changes, handles) @@ -570,8 +576,8 @@ async fn execute_command( CommandInner::Subshell(list) => { // Here the state can be changed but we can not pass by reference match execute_subshell(list, state, stdin, stdout, stderr).await { - ExecuteResult::Exit(code, handles) => { - ExecuteResult::Exit(code, handles) + ExecuteResult::Exit(code, _, handles) => { + ExecuteResult::Exit(code, changes, handles) } ExecuteResult::Continue(code, _, handles) => { ExecuteResult::Continue(code, changes, handles) @@ -642,7 +648,8 @@ async fn execute_for_clause( .await; match result { - ExecuteResult::Exit(code, handles) => { + ExecuteResult::Exit(code, env_changes, handles) => { + changes.extend(env_changes); async_handles.extend(handles); last_exit_code = code; break; @@ -658,7 +665,7 @@ async fn execute_for_clause( state.apply_changes(&changes); if state.exit_on_error() && last_exit_code != 0 { - ExecuteResult::Exit(last_exit_code, async_handles) + ExecuteResult::Exit(last_exit_code, changes, async_handles) } else { ExecuteResult::Continue(last_exit_code, changes, async_handles) } @@ -910,7 +917,8 @@ async fn execute_pipe_sequence( let mut changes: Vec = changes.into_iter().flatten().collect(); match last_result { - ExecuteResult::Exit(code, mut handles) => { + ExecuteResult::Exit(code, env_changes, mut handles) => { + changes.extend(env_changes); handles.extend(all_handles); ExecuteResult::Continue(code, changes, handles) } @@ -941,9 +949,9 @@ async fn execute_subshell( .await; match result { - ExecuteResult::Exit(code, handles) => { + ExecuteResult::Exit(code, env_changes, handles) => { // sub shells do not cause an exit - ExecuteResult::Continue(code, Vec::new(), handles) + ExecuteResult::Continue(code, env_changes, handles) } ExecuteResult::Continue(code, env_changes, handles) => { // env changes are not propagated @@ -988,8 +996,9 @@ async fn execute_if_clause( ) .await; match exec_result { - ExecuteResult::Exit(code, handles) => { - return ExecuteResult::Exit(code, handles); + ExecuteResult::Exit(code, env_changes, handles) => { + changes.extend(env_changes); + return ExecuteResult::Exit(code, changes, handles); } ExecuteResult::Continue(code, env_changes, handles) => { changes.extend(env_changes); @@ -1019,8 +1028,9 @@ async fn execute_if_clause( ) .await; match exec_result { - ExecuteResult::Exit(code, handles) => { - return ExecuteResult::Exit(code, handles); + ExecuteResult::Exit(code, env_changes, handles) => { + changes.extend(env_changes); + return ExecuteResult::Exit(code, changes, handles); } ExecuteResult::Continue(code, env_changes, handles) => { changes.extend(env_changes); @@ -1216,7 +1226,10 @@ async fn execute_simple_command( let result = execute_command_args(args, state, stdin, stdout, stderr).await; match result { - ExecuteResult::Exit(code, handles) => ExecuteResult::Exit(code, handles), + ExecuteResult::Exit(code, env_changes, handles) => { + changes.extend(env_changes); + ExecuteResult::Exit(code, changes, handles) + } ExecuteResult::Continue(code, env_changes, handles) => { changes.extend(env_changes); ExecuteResult::Continue(code, changes, handles) diff --git a/crates/deno_task_shell/src/shell/types.rs b/crates/deno_task_shell/src/shell/types.rs index 472b365..e9b45cc 100644 --- a/crates/deno_task_shell/src/shell/types.rs +++ b/crates/deno_task_shell/src/shell/types.rs @@ -389,13 +389,13 @@ pub const CANCELLATION_EXIT_CODE: i32 = 130; #[derive(Debug)] pub enum ExecuteResult { - Exit(i32, Vec>), + Exit(i32, Vec, Vec>), Continue(i32, Vec, Vec>), } impl ExecuteResult { pub fn for_cancellation() -> ExecuteResult { - ExecuteResult::Exit(CANCELLATION_EXIT_CODE, Vec::new()) + ExecuteResult::Exit(CANCELLATION_EXIT_CODE, Vec::new(), Vec::new()) } pub fn from_exit_code(exit_code: i32) -> ExecuteResult { @@ -404,7 +404,7 @@ impl ExecuteResult { pub fn into_exit_code_and_handles(self) -> (i32, Vec>) { match self { - ExecuteResult::Exit(code, handles) => (code, handles), + ExecuteResult::Exit(code, _, handles) => (code, handles), ExecuteResult::Continue(code, _, handles) => (code, handles), } } @@ -415,7 +415,7 @@ impl ExecuteResult { pub fn into_changes(self) -> Vec { match self { - ExecuteResult::Exit(_, _) => Vec::new(), + ExecuteResult::Exit(_, changes, _) => changes, ExecuteResult::Continue(_, changes, _) => changes, } } @@ -424,14 +424,14 @@ impl ExecuteResult { self, ) -> (Vec>, Vec) { match self { - ExecuteResult::Exit(_, handles) => (handles, Vec::new()), + ExecuteResult::Exit(_, changes, handles) => (handles, changes), ExecuteResult::Continue(_, changes, handles) => (handles, changes), } } pub fn exit_code(&self) -> i32 { match self { - ExecuteResult::Exit(code, _) => *code, + ExecuteResult::Exit(code, _, _) => *code, ExecuteResult::Continue(code, _, _) => *code, } } diff --git a/crates/shell/src/commands/set.rs b/crates/shell/src/commands/set.rs index b6ffb09..0e01fb0 100644 --- a/crates/shell/src/commands/set.rs +++ b/crates/shell/src/commands/set.rs @@ -17,7 +17,7 @@ impl ShellCommand for SetCommand { Ok((code, env_changes)) => ExecuteResult::Continue(code, env_changes, Vec::new()), Err(err) => { context.stderr.write_line(&format!("set: {err}")).unwrap(); - ExecuteResult::Exit(2, Vec::new()) + ExecuteResult::Exit(2, Vec::new(), Vec::new()) } }; Box::pin(futures::future::ready(result)) diff --git a/crates/shell/src/execute.rs b/crates/shell/src/execute.rs index f45209a..5bbda7e 100644 --- a/crates/shell/src/execute.rs +++ b/crates/shell/src/execute.rs @@ -20,7 +20,7 @@ pub async fn execute_inner( stderr.write_all(format!("Filename: {:?}\n", filename).as_bytes())?; } stderr.write_all(format!("Syntax error: {:?}", e).as_bytes())?; - return Ok(ExecuteResult::Exit(1, vec![])); + return Ok(ExecuteResult::Exit(1, vec![], vec![])); } // spawn a sequential list and pipe its output to the environment @@ -44,12 +44,15 @@ pub async fn execute( ) -> miette::Result { let result = execute_inner(text, filename, state.clone()).await?; - if let ExecuteResult::Continue(_, changes, _) = &result { - // set CWD to the last command's CWD - state.apply_changes(changes); - std::env::set_current_dir(state.cwd()) - .into_diagnostic() - .context("Failed to set CWD")?; - } + let changes = match &result { + ExecuteResult::Exit(_, changes, _) => changes, + ExecuteResult::Continue(_, changes, _) => changes, + }; + // set CWD to the last command's CWD + state.apply_changes(changes); + std::env::set_current_dir(state.cwd()) + .into_diagnostic() + .context("Failed to set CWD")?; + Ok(result) } diff --git a/crates/shell/src/main.rs b/crates/shell/src/main.rs index 6439e7d..336fa86 100644 --- a/crates/shell/src/main.rs +++ b/crates/shell/src/main.rs @@ -189,7 +189,7 @@ async fn interactive(state: Option, norc: bool, args: &[String]) -> .context("Failed to execute")?; state.set_last_command_exit_code(result.exit_code()); - if let ExecuteResult::Exit(exit_code, _) = result { + if let ExecuteResult::Exit(exit_code, _, _) = result { std::process::exit(exit_code); } } diff --git a/scripts/exit.sh b/scripts/exit.sh new file mode 100644 index 0000000..80517f1 --- /dev/null +++ b/scripts/exit.sh @@ -0,0 +1,2 @@ +echo "Hello World" +exit \ No newline at end of file From 42e9240353798e4129785d409611c66b3255198b Mon Sep 17 00:00:00 2001 From: prsabahrami Date: Fri, 14 Feb 2025 22:56:02 -0500 Subject: [PATCH 3/5] update subshell behaviour --- crates/deno_task_shell/src/shell/execute.rs | 2 +- crates/tests/test-data/source.sh | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 crates/tests/test-data/source.sh diff --git a/crates/deno_task_shell/src/shell/execute.rs b/crates/deno_task_shell/src/shell/execute.rs index 7db3330..8f27d24 100644 --- a/crates/deno_task_shell/src/shell/execute.rs +++ b/crates/deno_task_shell/src/shell/execute.rs @@ -577,7 +577,7 @@ async fn execute_command( // Here the state can be changed but we can not pass by reference match execute_subshell(list, state, stdin, stdout, stderr).await { ExecuteResult::Exit(code, _, handles) => { - ExecuteResult::Exit(code, changes, handles) + ExecuteResult::Continue(code, changes, handles) } ExecuteResult::Continue(code, _, handles) => { ExecuteResult::Continue(code, changes, handles) diff --git a/crates/tests/test-data/source.sh b/crates/tests/test-data/source.sh new file mode 100644 index 0000000..64205e5 --- /dev/null +++ b/crates/tests/test-data/source.sh @@ -0,0 +1,2 @@ +> export FOO='TESTVALUE' && source $CARGO_MANIFEST_DIR/../../scripts/exit.sh && echo $FOO + From 97516cf0e9ae4a9bf1806996ea23a6c5cc79b641 Mon Sep 17 00:00:00 2001 From: prsabahrami Date: Fri, 14 Feb 2025 23:08:25 -0500 Subject: [PATCH 4/5] fix: update ExecuteResult handling in while loop and subshell execution --- crates/deno_task_shell/src/shell/execute.rs | 81 +-------------------- 1 file changed, 4 insertions(+), 77 deletions(-) diff --git a/crates/deno_task_shell/src/shell/execute.rs b/crates/deno_task_shell/src/shell/execute.rs index 6eb35ac..197eae2 100644 --- a/crates/deno_task_shell/src/shell/execute.rs +++ b/crates/deno_task_shell/src/shell/execute.rs @@ -617,8 +617,8 @@ async fn execute_command( CommandInner::Subshell(list) => { // Here the state can be changed but we can not pass by reference match execute_subshell(list, state, stdin, stdout, stderr).await { - ExecuteResult::Exit(code, handles) => { - ExecuteResult::Exit(code, handles) + ExecuteResult::Exit(code, _, handles) => { + ExecuteResult::Exit(code, changes, handles) } ExecuteResult::Continue(code, _, handles) => { ExecuteResult::Continue(code, changes, handles) @@ -703,84 +703,11 @@ async fn execute_while_clause( .await; match exec_result { - ExecuteResult::Exit(code, handles) => { - async_handles.extend(handles); - last_exit_code = code; - break; - } - ExecuteResult::Continue(code, env_changes, handles) => { + ExecuteResult::Exit(code, env_changes, handles) => { state.apply_changes(&env_changes); changes.extend(env_changes); async_handles.extend(handles); last_exit_code = code; - } - } - } else { - break; - } - } - Err(err) => { - return err.into_exit_code(&mut stderr); - } - } - } - - state.apply_changes(&changes); - - if state.exit_on_error() && last_exit_code != 0 { - ExecuteResult::Exit(last_exit_code, async_handles) - } else { - ExecuteResult::Continue(last_exit_code, changes, async_handles) - } -} - -async fn execute_while_clause( - while_clause: WhileLoop, - state: &mut ShellState, - stdin: ShellPipeReader, - stdout: ShellPipeWriter, - mut stderr: ShellPipeWriter, -) -> ExecuteResult { - let mut changes = Vec::new(); - let mut last_exit_code = 0; - let mut async_handles = Vec::new(); - - loop { - let condition_result = evaluate_condition( - while_clause.condition.clone(), - state, - stdin.clone(), - stderr.clone(), - ) - .await; - - match condition_result { - Ok(ConditionalResult { - value, - changes: env_changes, - }) => { - state.apply_changes(&env_changes); - changes.extend(env_changes); - - // For until loops, we invert the condition - let should_execute_body = - if while_clause.is_until { !value } else { value }; - - if should_execute_body { - let exec_result = execute_sequential_list( - while_clause.body.clone(), - state.clone(), - stdin.clone(), - stdout.clone(), - stderr.clone(), - AsyncCommandBehavior::Yield, - ) - .await; - - match exec_result { - ExecuteResult::Exit(code, handles) => { - async_handles.extend(handles); - last_exit_code = code; break; } ExecuteResult::Continue(code, env_changes, handles) => { @@ -803,7 +730,7 @@ async fn execute_while_clause( state.apply_changes(&changes); if state.exit_on_error() && last_exit_code != 0 { - ExecuteResult::Exit(last_exit_code, async_handles) + ExecuteResult::Exit(last_exit_code, changes, async_handles) } else { ExecuteResult::Continue(last_exit_code, changes, async_handles) } From 6505739118d60f5f330ba269c4f2539a2362b026 Mon Sep 17 00:00:00 2001 From: prsabahrami Date: Fri, 14 Feb 2025 23:08:44 -0500 Subject: [PATCH 5/5] run fmt --- .../src/shell/commands/exit.rs | 26 +-- crates/deno_task_shell/src/shell/execute.rs | 194 +++++++++--------- crates/deno_task_shell/src/shell/types.rs | 54 ++--- 3 files changed, 141 insertions(+), 133 deletions(-) diff --git a/crates/deno_task_shell/src/shell/commands/exit.rs b/crates/deno_task_shell/src/shell/commands/exit.rs index b4d9a9a..f8f0ee1 100644 --- a/crates/deno_task_shell/src/shell/commands/exit.rs +++ b/crates/deno_task_shell/src/shell/commands/exit.rs @@ -14,19 +14,19 @@ use super::ShellCommandContext; pub struct ExitCommand; impl ShellCommand for ExitCommand { - fn execute( - &self, - mut context: ShellCommandContext, - ) -> LocalBoxFuture<'static, ExecuteResult> { - let result = match execute_exit(context.args) { - Ok(code) => ExecuteResult::Exit(code, Vec::new(), Vec::new()), - Err(err) => { - context.stderr.write_line(&format!("exit: {err}")).unwrap(); - ExecuteResult::Exit(2, Vec::new(), Vec::new()) - } - }; - Box::pin(futures::future::ready(result)) - } + fn execute( + &self, + mut context: ShellCommandContext, + ) -> LocalBoxFuture<'static, ExecuteResult> { + let result = match execute_exit(context.args) { + Ok(code) => ExecuteResult::Exit(code, Vec::new(), Vec::new()), + Err(err) => { + context.stderr.write_line(&format!("exit: {err}")).unwrap(); + ExecuteResult::Exit(2, Vec::new(), Vec::new()) + } + }; + Box::pin(futures::future::ready(result)) + } } fn execute_exit(args: Vec) -> Result { diff --git a/crates/deno_task_shell/src/shell/execute.rs b/crates/deno_task_shell/src/shell/execute.rs index 197eae2..7f1aece 100644 --- a/crates/deno_task_shell/src/shell/execute.rs +++ b/crates/deno_task_shell/src/shell/execute.rs @@ -135,10 +135,10 @@ pub async fn execute_with_pipes( ) .await; - match result { - ExecuteResult::Exit(code, _, _) => code, - ExecuteResult::Continue(exit_code, _, _) => exit_code, - } + match result { + ExecuteResult::Exit(code, _, _) => code, + ExecuteResult::Continue(exit_code, _, _) => exit_code, + } } #[derive(Debug, PartialEq)] @@ -192,9 +192,9 @@ pub fn execute_sequential_list( .await; match result { ExecuteResult::Exit(exit_code, changes, handles) => { - state.apply_changes(&changes); - state.set_shell_var("?", &exit_code.to_string()); - final_changes.extend(changes); + state.apply_changes(&changes); + state.set_shell_var("?", &exit_code.to_string()); + final_changes.extend(changes); async_handles.extend(handles); final_exit_code = exit_code; was_exit = true; @@ -344,7 +344,7 @@ fn execute_sequence( .await; match next_result { ExecuteResult::Exit(code, sub_changes, sub_handles) => { - changes.extend(sub_changes); + changes.extend(sub_changes); async_handles.extend(sub_handles); ExecuteResult::Exit(code, changes, async_handles) } @@ -381,21 +381,22 @@ async fn execute_pipeline( stdout: ShellPipeWriter, stderr: ShellPipeWriter, ) -> ExecuteResult { - let result = - execute_pipeline_inner(pipeline.inner, state, stdin, stdout, stderr).await; - if pipeline.negated { - match result { - ExecuteResult::Exit(code, changes, handles) => { - ExecuteResult::Exit(code, changes, handles) - } - ExecuteResult::Continue(code, changes, handles) => { - let new_code = if code == 0 { 1 } else { 0 }; - ExecuteResult::Continue(new_code, changes, handles) - } + let result = + execute_pipeline_inner(pipeline.inner, state, stdin, stdout, stderr) + .await; + if pipeline.negated { + match result { + ExecuteResult::Exit(code, changes, handles) => { + ExecuteResult::Exit(code, changes, handles) + } + ExecuteResult::Continue(code, changes, handles) => { + let new_code = if code == 0 { 1 } else { 0 }; + ExecuteResult::Continue(new_code, changes, handles) + } + } + } else { + result } - } else { - result - } } async fn execute_pipeline_inner( @@ -595,68 +596,73 @@ async fn execute_command( let _ = stderr.write_line( "only redirecting to stdout (1) and stderr (2) is supported", ); - return ExecuteResult::from_exit_code(1); + return ExecuteResult::from_exit_code(1); + } + Some(RedirectFd::StdoutStderr) => { + (stdin, pipe.clone(), pipe, changes) + } + }, } - Some(RedirectFd::StdoutStderr) => (stdin, pipe.clone(), pipe, changes), - }, - } - } else { - (stdin, stdout, stderr, None) - }; - let mut changes = if let Some(changes) = changes { - state.apply_changes(&changes); - changes - } else { - Vec::new() - }; - match command.inner { - CommandInner::Simple(command) => { - // This can change the state, so we need to pass it by mutable reference - execute_simple_command(command, &mut state, stdin, stdout, stderr).await - } - CommandInner::Subshell(list) => { - // Here the state can be changed but we can not pass by reference - match execute_subshell(list, state, stdin, stdout, stderr).await { - ExecuteResult::Exit(code, _, handles) => { - ExecuteResult::Exit(code, changes, handles) + } else { + (stdin, stdout, stderr, None) + }; + let mut changes = if let Some(changes) = changes { + state.apply_changes(&changes); + changes + } else { + Vec::new() + }; + match command.inner { + CommandInner::Simple(command) => { + // This can change the state, so we need to pass it by mutable reference + execute_simple_command(command, &mut state, stdin, stdout, stderr) + .await } - ExecuteResult::Continue(code, _, handles) => { - ExecuteResult::Continue(code, changes, handles) + CommandInner::Subshell(list) => { + // Here the state can be changed but we can not pass by reference + match execute_subshell(list, state, stdin, stdout, stderr).await { + ExecuteResult::Exit(code, _, handles) => { + ExecuteResult::Exit(code, changes, handles) + } + ExecuteResult::Continue(code, _, handles) => { + ExecuteResult::Continue(code, changes, handles) + } + } } - } - } - CommandInner::If(if_clause) => { - // The state can be changed - execute_if_clause(if_clause, &mut state, stdin, stdout, stderr).await - } - CommandInner::For(for_clause) => { - // The state can be changed - execute_for_clause(for_clause, &mut state, stdin, stdout, stderr).await - } - CommandInner::While(while_clause) => { - execute_while_clause( - while_clause, - &mut state, - stdin, - stdout, - stderr, - ) - .await - } - CommandInner::ArithmeticExpression(arithmetic) => { - // The state can be changed - match execute_arithmetic_expression(arithmetic, &mut state).await { - Ok(result) => { - changes.extend(result.changes); - ExecuteResult::Continue(0, changes, Vec::new()) + CommandInner::If(if_clause) => { + // The state can be changed + execute_if_clause(if_clause, &mut state, stdin, stdout, stderr) + .await + } + CommandInner::For(for_clause) => { + // The state can be changed + execute_for_clause(for_clause, &mut state, stdin, stdout, stderr) + .await + } + CommandInner::While(while_clause) => { + execute_while_clause( + while_clause, + &mut state, + stdin, + stdout, + stderr, + ) + .await } - Err(e) => { - let _ = stderr.write_line(&e.to_string()); - ExecuteResult::Continue(2, changes, Vec::new()) + CommandInner::ArithmeticExpression(arithmetic) => { + // The state can be changed + match execute_arithmetic_expression(arithmetic, &mut state).await { + Ok(result) => { + changes.extend(result.changes); + ExecuteResult::Continue(0, changes, Vec::new()) + } + Err(e) => { + let _ = stderr.write_line(&e.to_string()); + ExecuteResult::Continue(2, changes, Vec::new()) + } + } } - } } - } } async fn execute_while_clause( @@ -777,7 +783,7 @@ async fn execute_for_clause( match result { ExecuteResult::Exit(code, env_changes, handles) => { - changes.extend(env_changes); + changes.extend(env_changes); async_handles.extend(handles); last_exit_code = code; break; @@ -1079,7 +1085,7 @@ async fn execute_pipe_sequence( match last_result { ExecuteResult::Exit(code, env_changes, mut handles) => { - changes.extend(env_changes); + changes.extend(env_changes); handles.extend(all_handles); ExecuteResult::Continue(code, changes, handles) } @@ -1158,7 +1164,7 @@ async fn execute_if_clause( .await; match exec_result { ExecuteResult::Exit(code, env_changes, handles) => { - changes.extend(env_changes); + changes.extend(env_changes); return ExecuteResult::Exit(code, changes, handles); } ExecuteResult::Continue(code, env_changes, handles) => { @@ -1190,8 +1196,10 @@ async fn execute_if_clause( .await; match exec_result { ExecuteResult::Exit(code, env_changes, handles) => { - changes.extend(env_changes); - return ExecuteResult::Exit(code, changes, handles); + changes.extend(env_changes); + return ExecuteResult::Exit( + code, changes, handles, + ); } ExecuteResult::Continue( code, @@ -1440,17 +1448,17 @@ async fn execute_simple_command( let _ = stdout.write_line(&format!("+ {:}", args.join(" "))); } - let result = execute_command_args(args, state, stdin, stdout, stderr).await; - match result { - ExecuteResult::Exit(code, env_changes, handles) => { - changes.extend(env_changes); - ExecuteResult::Exit(code, changes, handles) - } - ExecuteResult::Continue(code, env_changes, handles) => { - changes.extend(env_changes); - ExecuteResult::Continue(code, changes, handles) + let result = execute_command_args(args, state, stdin, stdout, stderr).await; + match result { + ExecuteResult::Exit(code, env_changes, handles) => { + changes.extend(env_changes); + ExecuteResult::Exit(code, changes, handles) + } + ExecuteResult::Continue(code, env_changes, handles) => { + changes.extend(env_changes); + ExecuteResult::Continue(code, changes, handles) + } } - } } fn execute_command_args( diff --git a/crates/deno_task_shell/src/shell/types.rs b/crates/deno_task_shell/src/shell/types.rs index 457c81c..aa4eb95 100644 --- a/crates/deno_task_shell/src/shell/types.rs +++ b/crates/deno_task_shell/src/shell/types.rs @@ -389,52 +389,52 @@ pub const CANCELLATION_EXIT_CODE: i32 = 130; #[derive(Debug)] pub enum ExecuteResult { - Exit(i32, Vec, Vec>), - Continue(i32, Vec, Vec>), + Exit(i32, Vec, Vec>), + Continue(i32, Vec, Vec>), } impl ExecuteResult { - pub fn for_cancellation() -> ExecuteResult { - ExecuteResult::Exit(CANCELLATION_EXIT_CODE, Vec::new(), Vec::new()) - } + pub fn for_cancellation() -> ExecuteResult { + ExecuteResult::Exit(CANCELLATION_EXIT_CODE, Vec::new(), Vec::new()) + } pub fn from_exit_code(exit_code: i32) -> ExecuteResult { ExecuteResult::Continue(exit_code, Vec::new(), Vec::new()) } - pub fn into_exit_code_and_handles(self) -> (i32, Vec>) { - match self { - ExecuteResult::Exit(code, _, handles) => (code, handles), - ExecuteResult::Continue(code, _, handles) => (code, handles), + pub fn into_exit_code_and_handles(self) -> (i32, Vec>) { + match self { + ExecuteResult::Exit(code, _, handles) => (code, handles), + ExecuteResult::Continue(code, _, handles) => (code, handles), + } } - } pub fn into_handles(self) -> Vec> { self.into_exit_code_and_handles().1 } - pub fn into_changes(self) -> Vec { - match self { - ExecuteResult::Exit(_, changes, _) => changes, - ExecuteResult::Continue(_, changes, _) => changes, + pub fn into_changes(self) -> Vec { + match self { + ExecuteResult::Exit(_, changes, _) => changes, + ExecuteResult::Continue(_, changes, _) => changes, + } } - } - pub fn into_handles_and_changes( - self, - ) -> (Vec>, Vec) { - match self { - ExecuteResult::Exit(_, changes, handles) => (handles, changes), - ExecuteResult::Continue(_, changes, handles) => (handles, changes), + pub fn into_handles_and_changes( + self, + ) -> (Vec>, Vec) { + match self { + ExecuteResult::Exit(_, changes, handles) => (handles, changes), + ExecuteResult::Continue(_, changes, handles) => (handles, changes), + } } - } - pub fn exit_code(&self) -> i32 { - match self { - ExecuteResult::Exit(code, _, _) => *code, - ExecuteResult::Continue(code, _, _) => *code, + pub fn exit_code(&self) -> i32 { + match self { + ExecuteResult::Exit(code, _, _) => *code, + ExecuteResult::Continue(code, _, _) => *code, + } } - } } /// Reader side of a pipe.