Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions crates/bashkit/src/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1152,8 +1152,7 @@ impl Interpreter {
// errexit (set -e): stop on non-zero exit for top-level simple commands.
// List commands handle errexit internally (with && / || chain awareness).
// Negated pipelines (! cmd) explicitly handle the exit code.
// Compound commands (for/while/until) propagate errexit_suppressed when
// their body ends with an AND-OR chain failure.
// Compound commands propagate errexit_suppressed from inner AND-OR chains.
if self.is_errexit_enabled() && exit_code != 0 {
let suppressed = matches!(command, Command::List(_))
|| matches!(command, Command::Pipeline(p) if p.negated)
Comment on lines 1152 to 1158
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description says execute_script_body was updated to check result.errexit_suppressed for both errexit and ERR-trap suppression, but this hunk only changes a comment. If additional logic changes are intended here, they may be missing from the diff (or the description may need updating).

Copilot uses AI. Check for mistakes.
Expand Down
24 changes: 24 additions & 0 deletions crates/bashkit/tests/set_e_and_or_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,30 @@ echo "SHOULD NOT APPEAR"
assert!(!result.stdout.contains("SHOULD NOT APPEAR"));
}

/// set -e: && chain failure at end of for loop body should NOT exit (issue #873)
#[tokio::test]
async fn set_e_and_chain_at_end_of_for_body() {
let mut bash = Bash::new();
let result = bash
.exec(
r#"
set -euo pipefail
result=""
for src in yes no; do
[[ "${src}" == "yes" ]] && result="${src}"
done
echo "result: ${result}"
"#,
)
.await
.unwrap();
assert!(
result.stdout.contains("result: yes"),
"should print 'result: yes' but got: {:?}",
result.stdout
);
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test verifies stdout, but it would also be useful to assert exit_code == 0 (since the last command is echo). That helps catch cases where errexit is suppressed correctly but the interpreter still reports the loop’s non-zero status as the script’s final exit code.

Suggested change
);
);
assert_eq!(
result.exit_code, 0,
"script should exit successfully but exit_code was {}",
result.exit_code
);

Copilot uses AI. Check for mistakes.
}

/// set -e should still exit on non-AND-OR failures
#[tokio::test]
async fn set_e_exits_on_plain_failure() {
Expand Down
Loading