From e7967ca0f9fec33f7423757f7d14ce164a41e88a Mon Sep 17 00:00:00 2001 From: zakstucke <44890343+zakstucke@users.noreply.github.com> Date: Fri, 26 Jan 2024 06:15:45 -0500 Subject: [PATCH] Exit code fix (#7) --- rust/bitbazaar/cli/bash.rs | 3 - rust/bitbazaar/cli/mod.rs | 1 + rust/bitbazaar/cli/runner.rs | 124 ++++++++++++++++++----------------- 3 files changed, 65 insertions(+), 63 deletions(-) diff --git a/rust/bitbazaar/cli/bash.rs b/rust/bitbazaar/cli/bash.rs index 59761e60..efe761ad 100644 --- a/rust/bitbazaar/cli/bash.rs +++ b/rust/bitbazaar/cli/bash.rs @@ -160,7 +160,6 @@ impl Shell { // Add the stderr to the current shell: self.stderr.push_str(&shell.stderr); - debug!("Compound cmd stdout: '{}'", shell.stdout); // Add the pre-computed stdout to be used as stdin to the next command in the outer runner: pipe_runner.add_piped_stdout(shell.stdout); } @@ -249,8 +248,6 @@ impl Shell { args.push(arg_str); } - debug!("Final command args: {:?}", args); - // Add the env vars to the current shell to in this command, later and parser expansions etc: for (name, val) in env.iter() { self.vars.insert(name.to_string(), val.to_string()); diff --git a/rust/bitbazaar/cli/mod.rs b/rust/bitbazaar/cli/mod.rs index 863ddfc3..82c3a83f 100644 --- a/rust/bitbazaar/cli/mod.rs +++ b/rust/bitbazaar/cli/mod.rs @@ -42,6 +42,7 @@ mod tests { // <-- basics: #[case::basic_1("echo 'hello world'", "hello world", 0, None, None, true)] #[case::basic_2("echo hello world", "hello world", 0, None, None, true)] + #[case::basic_3("./no_exist.sh", "", 2, None, None, true)] // <-- and: #[case::and_1("echo hello && echo world", "hello\nworld", 0, None, None, true)] #[case::and_2("echo hello && false && echo world", "hello", 1, None, None, true)] diff --git a/rust/bitbazaar/cli/runner.rs b/rust/bitbazaar/cli/runner.rs index 626a5336..7762794c 100644 --- a/rust/bitbazaar/cli/runner.rs +++ b/rust/bitbazaar/cli/runner.rs @@ -87,73 +87,77 @@ impl PipeRunner { }; } - // Spawn the new command, - // might fail if e.g. exit 1 in there - // so ignoring error case on this as still succeeds with non zero exit codes: - if let Ok(mut child) = command + // Spawn the new command: + match command .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() { - // If needed, manually passing stdin from a string: - if let Some(s) = str_stdin { - let mut stdin_handle = child.stdin.take().ok_or_else(|| { - err!(CmdErr::InternalError, "Couldn't access stdin handle.") - })?; - - stdin_handle - .write_all(s.as_bytes()) - .change_context(CmdErr::InternalError)?; - } - - // Not last command, need to pipe into next: - if !is_last { - let stdout_handle = child.stdout.ok_or_else(|| { - err!( - CmdErr::InternalError, - "No stdout handle from previous command." - ) - })?; - - let stderr_handle = child.stderr.ok_or_else(|| { - err!( - CmdErr::InternalError, - "No stderr handle from previous command." - ) - })?; - - self.stderrs.push(stderr_handle); - stdin = Some(VariStdin::Stdio(stdout_handle.into())); - } else { - // Last command, need to finalise all: - - // Wait for the output of the final command: - let output = child - .wait_with_output() - .change_context(CmdErr::InternalError)?; - - // Load in the stderrs from previous commands: - for mut stderr in std::mem::take(&mut self.stderrs) { - stderr - .read_to_string(&mut shell.stderr) + Ok(mut child) => { + // If needed, manually passing stdin from a string: + if let Some(s) = str_stdin { + let mut stdin_handle = child.stdin.take().ok_or_else(|| { + err!(CmdErr::InternalError, "Couldn't access stdin handle.") + })?; + + stdin_handle + .write_all(s.as_bytes()) .change_context(CmdErr::InternalError)?; } - // Add on the stderr from the final command: - shell.stderr.push_str( - str::from_utf8(&output.stderr) - .change_context(CmdErr::BashUTF8Error)? - .to_string() - .as_str(), - ); - - // Read the out from the final command: - shell.stdout.push_str( - str::from_utf8(&output.stdout) - .change_context(CmdErr::BashUTF8Error)?, - ); - - shell.code = output.status.code().unwrap_or(1); + // Not last command, need to pipe into next: + if !is_last { + let stdout_handle = child.stdout.ok_or_else(|| { + err!( + CmdErr::InternalError, + "No stdout handle from previous command." + ) + })?; + + let stderr_handle = child.stderr.ok_or_else(|| { + err!( + CmdErr::InternalError, + "No stderr handle from previous command." + ) + })?; + + self.stderrs.push(stderr_handle); + stdin = Some(VariStdin::Stdio(stdout_handle.into())); + } else { + // Last command, need to finalise all: + + // Wait for the output of the final command: + let output = child + .wait_with_output() + .change_context(CmdErr::InternalError)?; + + // Load in the stderrs from previous commands: + for mut stderr in std::mem::take(&mut self.stderrs) { + stderr + .read_to_string(&mut shell.stderr) + .change_context(CmdErr::InternalError)?; + } + + // Add on the stderr from the final command: + shell.stderr.push_str( + str::from_utf8(&output.stderr) + .change_context(CmdErr::BashUTF8Error)? + .to_string() + .as_str(), + ); + + // Read the out from the final command: + shell.stdout.push_str( + str::from_utf8(&output.stdout) + .change_context(CmdErr::BashUTF8Error)?, + ); + + shell.code = output.status.code().unwrap_or(1); + } + } + Err(e) => { + // If the spawn errored, something went wrong, so set the code: + shell.code = e.raw_os_error().unwrap_or(1); } } }