From 82b206a802e8154ec99bf405e10bc5c28e3319bf Mon Sep 17 00:00:00 2001 From: WATANABE Yuki Date: Sun, 21 Apr 2024 14:18:58 +0900 Subject: [PATCH] Apply errexit in multi-command pipelines --- yash-cli/tests/scripted_test/errexit-p.sh | 1 - yash-semantics/CHANGELOG.md | 4 ++++ yash-semantics/src/command/pipeline.rs | 27 +++++++++++++++++++++-- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/yash-cli/tests/scripted_test/errexit-p.sh b/yash-cli/tests/scripted_test/errexit-p.sh index 1be605ae..5037c582 100644 --- a/yash-cli/tests/scripted_test/errexit-p.sh +++ b/yash-cli/tests/scripted_test/errexit-p.sh @@ -73,7 +73,6 @@ __IN__ reached __OUT__ -: TODO yash is broken <<\__IN__ test_O -e n 'errexit: last of pipeline' -e true | true | false echo not reached diff --git a/yash-semantics/CHANGELOG.md b/yash-semantics/CHANGELOG.md index d2423935..051699f4 100644 --- a/yash-semantics/CHANGELOG.md +++ b/yash-semantics/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.2.0] - Unreleased +### Added + +- Support for the `ErrExit` shell option in multi-command pipelines + ### Changed - `::handle` now returns `Divert::Exit` diff --git a/yash-semantics/src/command/pipeline.rs b/yash-semantics/src/command/pipeline.rs index 05f13804..a1c95812 100644 --- a/yash-semantics/src/command/pipeline.rs +++ b/yash-semantics/src/command/pipeline.rs @@ -112,9 +112,17 @@ async fn execute_commands_in_pipeline(env: &mut Env, commands: &[Rc commands[0].execute(env).await, - _ if env.controls_jobs() => execute_job_controlled_pipeline(env, commands).await, - _ => execute_multi_command_pipeline(env, commands).await, + + _ => { + if env.controls_jobs() { + execute_job_controlled_pipeline(env, commands).await? + } else { + execute_multi_command_pipeline(env, commands).await? + } + env.apply_errexit() + } } } @@ -322,6 +330,7 @@ mod tests { use yash_env::builtin::Builtin; use yash_env::builtin::Type::Special; use yash_env::job::ProcessState; + use yash_env::option::Option::ErrExit; use yash_env::option::Option::Monitor; use yash_env::option::State::On; use yash_env::semantics::Field; @@ -495,6 +504,20 @@ mod tests { assert_eq!(env.exit_status, ExitStatus::SUCCESS); } + #[test] + fn errexit_option() { + in_virtual_system(|mut env, _state| async move { + env.builtins.insert("return", return_builtin()); + env.options.set(ErrExit, On); + + let pipeline: syntax::Pipeline = "return -n 0 | return -n 93".parse().unwrap(); + let result = pipeline.execute(&mut env).await; + + assert_eq!(result, Break(Divert::Exit(None))); + assert_eq!(env.exit_status, ExitStatus(93)); + }); + } + #[test] fn stack_without_inversion() { fn stub_builtin(