diff --git a/crates/vite_task/src/session/mod.rs b/crates/vite_task/src/session/mod.rs index eb9ca6411..c5aea1a1b 100644 --- a/crates/vite_task/src/session/mod.rs +++ b/crates/vite_task/src/session/mod.rs @@ -244,15 +244,20 @@ impl<'a> Session<'a> { /// Primary entry point for CLI usage. Plans and executes the given command. /// - /// # Errors - /// - /// Returns an error if planning or execution fails. + /// This function prints user-facing errors itself and returns an exit status + /// code only. This allows downstream CLIs (like `vp run`) to simply + /// `std::process::exit(i32::from(status.0))` without duplicating error + /// reporting. #[tracing::instrument(level = "debug", skip_all)] - pub async fn main(mut self, command: Command) -> anyhow::Result { + pub async fn main(mut self, command: Command) -> ExitStatus { match self.main_inner(command).await { - Ok(()) => Ok(ExitStatus::SUCCESS), - Err(SessionError::EarlyExit(status)) => Ok(status), - Err(SessionError::Anyhow(err)) => Err(err), + Ok(()) => ExitStatus::SUCCESS, + Err(SessionError::EarlyExit(status)) => status, + #[expect(clippy::print_stderr, reason = "top-level error reporting")] + Err(SessionError::Anyhow(err)) => { + eprintln!("Error: {err:?}"); + ExitStatus::FAILURE + } } } diff --git a/crates/vite_task_bin/src/main.rs b/crates/vite_task_bin/src/main.rs index d627e2c32..626c4acfd 100644 --- a/crates/vite_task_bin/src/main.rs +++ b/crates/vite_task_bin/src/main.rs @@ -3,24 +3,24 @@ use vite_task::{Command, ExitStatus, Session}; use vite_task_bin::OwnedSessionConfig; fn main() -> ! { - let exit_code: i32 = - tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap().block_on(async { - match run().await { - Ok(status) => i32::from(status.0), - #[expect(clippy::print_stderr, reason = "top-level error reporting")] - Err(err) => { - eprintln!("Error: {err:?}"); - 1 - } - } - }); + let exit_code: i32 = tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build() + .unwrap() + .block_on(async { i32::from(run().await.0) }); std::process::exit(exit_code); } -async fn run() -> anyhow::Result { +async fn run() -> ExitStatus { let args = Command::parse(); let mut owned_config = OwnedSessionConfig::default(); - let session = Session::init(owned_config.as_config())?; - session.main(args).await + match Session::init(owned_config.as_config()) { + Ok(session) => session.main(args).await, + #[expect(clippy::print_stderr, reason = "top-level error reporting")] + Err(err) => { + eprintln!("Error: {err:?}"); + ExitStatus::FAILURE + } + } }