Skip to content

Commit 30ae7e5

Browse files
committed
fix(interpreter): preserve stdout from if/elif condition commands
execute_if only used condition_result.exit_code, discarding stdout/stderr. Patterns like `if echo "hello"; then ...` or `if ! cmd | jq; then ...` lost the condition's output. Now condition output is prepended to the branch result.
1 parent 9e7f605 commit 30ae7e5

File tree

2 files changed

+52
-5
lines changed

2 files changed

+52
-5
lines changed

crates/bashkit/src/interpreter/mod.rs

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1432,29 +1432,52 @@ impl Interpreter {
14321432

14331433
/// Execute an if statement
14341434
async fn execute_if(&mut self, if_cmd: &IfCommand) -> Result<ExecResult> {
1435+
// Accumulate stdout/stderr from all condition evaluations
1436+
let mut cond_stdout = String::new();
1437+
let mut cond_stderr = String::new();
1438+
14351439
// Execute condition (no errexit checking - conditions are expected to fail)
14361440
let condition_result = self.execute_condition_sequence(&if_cmd.condition).await?;
1441+
cond_stdout.push_str(&condition_result.stdout);
1442+
cond_stderr.push_str(&condition_result.stderr);
14371443

14381444
if condition_result.exit_code == 0 {
14391445
// Condition succeeded, execute then branch
1440-
return self.execute_command_sequence(&if_cmd.then_branch).await;
1446+
let mut result = self.execute_command_sequence(&if_cmd.then_branch).await?;
1447+
result.stdout = cond_stdout + &result.stdout;
1448+
result.stderr = cond_stderr + &result.stderr;
1449+
return Ok(result);
14411450
}
14421451

14431452
// Check elif branches
14441453
for (elif_condition, elif_body) in &if_cmd.elif_branches {
14451454
let elif_result = self.execute_condition_sequence(elif_condition).await?;
1455+
cond_stdout.push_str(&elif_result.stdout);
1456+
cond_stderr.push_str(&elif_result.stderr);
1457+
14461458
if elif_result.exit_code == 0 {
1447-
return self.execute_command_sequence(elif_body).await;
1459+
let mut result = self.execute_command_sequence(elif_body).await?;
1460+
result.stdout = cond_stdout + &result.stdout;
1461+
result.stderr = cond_stderr + &result.stderr;
1462+
return Ok(result);
14481463
}
14491464
}
14501465

14511466
// Execute else branch if present
14521467
if let Some(else_branch) = &if_cmd.else_branch {
1453-
return self.execute_command_sequence(else_branch).await;
1468+
let mut result = self.execute_command_sequence(else_branch).await?;
1469+
result.stdout = cond_stdout + &result.stdout;
1470+
result.stderr = cond_stderr + &result.stderr;
1471+
return Ok(result);
14541472
}
14551473

1456-
// No branch executed, return success
1457-
Ok(ExecResult::ok(String::new()))
1474+
// No branch executed, return condition output with success exit code
1475+
Ok(ExecResult {
1476+
stdout: cond_stdout,
1477+
stderr: cond_stderr,
1478+
exit_code: 0,
1479+
..Default::default()
1480+
})
14581481
}
14591482

14601483
/// Execute a for loop

crates/bashkit/tests/spec_cases/bash/exit-status.test.sh

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,3 +239,27 @@ echo SHOULD_NOT_REACH
239239
### expect
240240
in_func
241241
### end
242+
243+
### if_condition_stdout
244+
# stdout from if condition is preserved
245+
if echo "from_condition"; then echo "from_body"; fi
246+
### expect
247+
from_condition
248+
from_body
249+
### end
250+
251+
### if_negated_condition_stdout
252+
# stdout from negated if condition
253+
if ! echo "negated"; then echo "no"; else echo "yes"; fi
254+
### expect
255+
negated
256+
yes
257+
### end
258+
259+
### if_condition_pipeline_stdout
260+
# stdout from pipeline in if condition
261+
if echo "hello" | cat; then echo "ok"; fi
262+
### expect
263+
hello
264+
ok
265+
### end

0 commit comments

Comments
 (0)