diff --git a/crates/bsnext_dto/src/lib.rs b/crates/bsnext_dto/src/lib.rs index ad74d89..36a2caf 100644 --- a/crates/bsnext_dto/src/lib.rs +++ b/crates/bsnext_dto/src/lib.rs @@ -108,6 +108,9 @@ impl From<&StartupEvent> for StartupEventDTO { StartupEvent::FailedStartup(StartupError::InputError(err)) => { StartupEventDTO::FailedStartup(err.to_string()) } + StartupEvent::FailedStartup(StartupError::Other(err)) => { + StartupEventDTO::FailedStartup(err.to_string()) + } } } } diff --git a/crates/bsnext_dto/src/startup_events.rs b/crates/bsnext_dto/src/startup_events.rs index 1ef4e98..100736b 100644 --- a/crates/bsnext_dto/src/startup_events.rs +++ b/crates/bsnext_dto/src/startup_events.rs @@ -30,6 +30,9 @@ impl OutputWriterTrait for StartupEvent { StartupError::InputError(err) => { writeln!(sink, "{}", err)?; } + StartupError::Other(e) => { + writeln!(sink, "{}", e)?; + } } } } diff --git a/crates/bsnext_input/src/startup.rs b/crates/bsnext_input/src/startup.rs index 037b47a..dee7fc5 100644 --- a/crates/bsnext_input/src/startup.rs +++ b/crates/bsnext_input/src/startup.rs @@ -62,6 +62,8 @@ pub enum DidStart { pub enum StartupError { #[error("{0}")] InputError(#[from] InputError), + #[error("{0}")] + Other(String), } pub enum StartupTask {} diff --git a/crates/bsnext_output/src/lib.rs b/crates/bsnext_output/src/lib.rs index 125c7ae..feab708 100644 --- a/crates/bsnext_output/src/lib.rs +++ b/crates/bsnext_output/src/lib.rs @@ -30,7 +30,7 @@ pub trait OutputWriterTrait { impl OutputWriters { pub fn write_evt( &self, - evt: impl OutputWriterTrait, + evt: &impl OutputWriterTrait, sink: &mut W, ) -> anyhow::Result<()> { match self { diff --git a/crates/bsnext_output/src/stdout.rs b/crates/bsnext_output/src/stdout.rs index 5deb3ff..374eddd 100644 --- a/crates/bsnext_output/src/stdout.rs +++ b/crates/bsnext_output/src/stdout.rs @@ -43,15 +43,24 @@ pub fn completion_writer( match result { Ok(events) => { for export_event in events { - writer.write_evt(export_event, &mut sink.output())?; + writer.write_evt(&export_event, &mut sink.output())?; } sink.flush(); Ok(()) } Err(err) => { - writer.write_evt(err, &mut sink.error())?; + writer.write_evt(&err, &mut sink.error())?; sink.flush(); - Err(anyhow::anyhow!("export failed")) + Err(anyhow::anyhow!("exit")) } } } + +pub fn write_one_err(writer: OutputWriters, err: impl OutputWriterTrait) -> anyhow::Result<()> { + let stdout = &mut std::io::stdout(); + let stderr = &mut std::io::stderr(); + let mut sink = StdoutTarget::new(stdout, stderr); + writer.write_evt(&err, &mut sink.error())?; + sink.flush(); + Err(anyhow::anyhow!("exit")) +} diff --git a/crates/bsnext_system/src/cli.rs b/crates/bsnext_system/src/cli.rs index 0d5669f..3c4f4ab 100644 --- a/crates/bsnext_system/src/cli.rs +++ b/crates/bsnext_system/src/cli.rs @@ -1,7 +1,8 @@ use crate::args::{Args, SubCommands}; use crate::commands::{export_cmd, start_command}; -use bsnext_tracing::{init_tracing, WriteOption}; +use bsnext_output::OutputWriters; +use bsnext_tracing::{init_tracing, OutputFormat, WriteOption}; use clap::Parser; use std::env::current_dir; use std::ffi::OsString; @@ -16,20 +17,43 @@ where std::env::set_var("RUST_LIB_BACKTRACE", "0"); let cwd = PathBuf::from(current_dir().unwrap().to_string_lossy().to_string()); let args = Args::parse_from(itr); - let write_opt = if args.write_log { + + let write_log_opt = if args.write_log { WriteOption::File } else { WriteOption::None }; - init_tracing(args.log_level, args.format, write_opt); + init_tracing(args.log_level, args.format, write_log_opt); tracing::debug!("{:#?}", args); + let format_clone = args.format; + + let writer = match format_clone { + OutputFormat::Tui => OutputWriters::Pretty, + OutputFormat::Normal => OutputWriters::Pretty, + OutputFormat::Json => OutputWriters::Json, + }; + + tracing::debug!("printer: {}", writer); + match &args.command { - None => start_command::start_cmd(cwd, args).await, + None => { + let result = start_command::start_cmd(cwd, args).await; + match result { + Ok(_) => { + // noop + Ok(()) + } + Err(err) => bsnext_output::stdout::write_one_err(writer, err), + } + } Some(command) => match command { - SubCommands::Export(cmd) => export_cmd::export_cmd(&cwd, cmd, &args).await, + SubCommands::Export(cmd) => { + let result = export_cmd::export_cmd(&cwd, cmd, &args).await; + bsnext_output::stdout::completion_writer(writer, result) + } }, } } diff --git a/crates/bsnext_system/src/commands/export_cmd.rs b/crates/bsnext_system/src/commands/export_cmd.rs index c7f7105..17c136a 100644 --- a/crates/bsnext_system/src/commands/export_cmd.rs +++ b/crates/bsnext_system/src/commands/export_cmd.rs @@ -3,31 +3,21 @@ use crate::start_kind::StartKind; use bsnext_core::export::{export_one_server, ExportCommand}; use bsnext_fs_helpers::WriteMode; use bsnext_input::startup::{StartupContext, SystemStart, SystemStartArgs}; -use bsnext_output::OutputWriters; -use bsnext_tracing::OutputFormat; +use bsnext_output::OutputWriterTrait; use std::path::PathBuf; pub async fn export_cmd( cwd: &PathBuf, cmd: &ExportCommand, args: &Args, -) -> Result<(), anyhow::Error> { - let format_clone = args.format; - - let writer = match format_clone { - OutputFormat::Tui => OutputWriters::Pretty, - OutputFormat::Normal => OutputWriters::Pretty, - OutputFormat::Json => OutputWriters::Json, - }; - tracing::debug!("printer: {}", writer); - +) -> Result, impl OutputWriterTrait> { let ctx = StartupContext::from_cwd(Some(cwd)); tracing::debug!("StartupContext: {:?}", ctx); let start_kind = StartKind::from_args(args).input(&ctx); match start_kind { - Err(e) => eprintln!("an error occured here?, {}", e), + Err(e) => todo!("handle an error here: {:?}", e), Ok(SystemStartArgs::InputOnly { input: _ }) => todo!("handle InputOnly?"), Ok(SystemStartArgs::PathWithInput { path: _, input }) if input.servers.len() == 1 => { let first = &input.servers[0]; @@ -38,9 +28,7 @@ pub async fn export_cmd( WriteMode::Safe }; - let results = export_one_server(cwd, first.clone(), cmd, fs_write_mode).await; - - bsnext_output::stdout::completion_writer(writer, results)?; + export_one_server(cwd, first.clone(), cmd, fs_write_mode).await } Ok(SystemStartArgs::PathWithInput { path: _, input: _ }) => { // let first = @@ -49,5 +37,4 @@ pub async fn export_cmd( } Ok(SystemStartArgs::PathWithInvalidInput { .. }) => todo!("handle PathWithInvalidInput?"), } - Ok(()) } diff --git a/crates/bsnext_system/src/commands/start_command.rs b/crates/bsnext_system/src/commands/start_command.rs index 62e7e52..b8aa799 100644 --- a/crates/bsnext_system/src/commands/start_command.rs +++ b/crates/bsnext_system/src/commands/start_command.rs @@ -3,29 +3,21 @@ use crate::start_kind::StartKind; use crate::{BsSystem, Start}; use actix::Actor; use bsnext_dto::internal::{AnyEvent, StartupEvent}; -use bsnext_input::startup::DidStart; +use bsnext_input::startup::{DidStart, StartupError}; use bsnext_output::stdout::StdoutTarget; -use bsnext_output::OutputWriters; +use bsnext_output::{OutputWriterTrait, OutputWriters}; use bsnext_tracing::OutputFormat; use std::path::PathBuf; use tokio::sync::{mpsc, oneshot}; use tracing::debug_span; -pub async fn start_cmd(cwd: PathBuf, args: Args) -> Result<(), anyhow::Error> { +pub async fn start_cmd(cwd: PathBuf, args: Args) -> Result<(), impl OutputWriterTrait> { let (tx, rx) = oneshot::channel(); let (events_sender, mut events_receiver) = mpsc::channel::(1); let system = BsSystem::new(); let sys_addr = system.start(); let format_clone = args.format; - - // for the startup message, don't allow a TUI yet - let start_printer = match format_clone { - OutputFormat::Tui => OutputWriters::Pretty, - OutputFormat::Json => OutputWriters::Json, - OutputFormat::Normal => OutputWriters::Pretty, - }; - let start_kind = StartKind::from_args(&args); tracing::debug!(?start_kind); @@ -37,44 +29,31 @@ pub async fn start_cmd(cwd: PathBuf, args: Args) -> Result<(), anyhow::Error> { events_sender, }; - // let stdout = &mut std::io::stdout(); - let stdout = &mut std::io::stdout(); - let stderr = &mut std::io::stderr(); - let mut sink = StdoutTarget::new(stdout, stderr); - - match sys_addr.send(start).await? { - Ok(DidStart::Started) => { - let evt = StartupEvent::Started; - match start_printer.write_evt(evt, &mut sink.output()) { - Ok(_) => {} - Err(e) => tracing::error!(?e), - }; - sink.flush(); + match sys_addr.send(start).await { + Ok(Ok(DidStart::Started)) => { + // everything good here, continue... } - Err(e) => { - let evt = StartupEvent::FailedStartup(e); - match start_printer.write_evt(evt, &mut sink.error()) { - Ok(_) => {} - Err(e) => tracing::error!(?e), - }; - sink.flush(); - return Err(anyhow::anyhow!("could not flush")); + Ok(Err(e)) => { + return Err(StartupEvent::FailedStartup(e)); } - }; - - // at this point, we started, so we can choose a TUI - let printer = match format_clone { - OutputFormat::Tui => { - // let rr = Ratatui::try_new().expect("test"); - // let (sender, _ui_handle, _other) = rr.install().expect("thread install"); - // Writers::Ratatui(sender) - todo!("re-implement ratatui") + Err(e) => { + let message = e.to_string(); + return Err(StartupEvent::FailedStartup(StartupError::Other(message))); } - OutputFormat::Json => OutputWriters::Json, - OutputFormat::Normal => OutputWriters::Pretty, }; let events_handler = tokio::spawn(async move { + // at this point, we started, so we can choose a TUI + let printer = match format_clone { + OutputFormat::Tui => { + // let rr = Ratatui::try_new().expect("test"); + // let (sender, _ui_handle, _other) = rr.install().expect("thread install"); + // Writers::Ratatui(sender) + todo!("re-implement ratatui") + } + OutputFormat::Json => OutputWriters::Json, + OutputFormat::Normal => OutputWriters::Pretty, + }; // let events = vec![]; let stdout = &mut std::io::stdout(); let stderr = &mut std::io::stderr(); @@ -85,8 +64,8 @@ pub async fn start_cmd(cwd: PathBuf, args: Args) -> Result<(), anyhow::Error> { let _g2 = span.enter(); tracing::debug!(external_event = ?evt); let result = match evt { - AnyEvent::Internal(int) => printer.write_evt(int, &mut sink.output()), - AnyEvent::External(ext) => printer.write_evt(ext, &mut sink.output()), + AnyEvent::Internal(int) => printer.write_evt(&int, &mut sink.output()), + AnyEvent::External(ext) => printer.write_evt(&ext, &mut sink.output()), }; match result { Ok(_) => {}