use std::process::ExitCode;
use crate::architect::{self, Reviewed};
use crate::config::{self, UserConfig};
use crate::failed_run::FailedRun;
use crate::interrupt;
use crate::issue::IssueUrl;
use crate::logs::{self, Begin};
use crate::notification::{About, NotificationAsk, RunNotification};
use crate::pickup;
use crate::progress;
use crate::run::Ended;
use crate::run_ending;
pub enum Ending {
Run(Ended),
Architect {
review: Result<Reviewed, FailedRun>,
dispatched: Option<Ended>,
},
Skipped(Skip),
}
pub struct Skip {
pub reason: String,
pub urls: Vec<String>,
}
impl From<architect::Skipped> for Skip {
fn from(skipped: architect::Skipped) -> Self {
Skip {
reason: skipped.to_string(),
urls: skipped.urls().into_iter().map(String::from).collect(),
}
}
}
impl From<pickup::Skipped> for Skip {
fn from(skipped: pickup::Skipped) -> Self {
Skip {
reason: skipped.to_string(),
urls: Vec::new(),
}
}
}
pub struct Started {
notification: Option<RunNotification>,
}
pub fn start(
begin: Begin,
ask: impl FnOnce(&UserConfig) -> NotificationAsk,
about: About,
) -> Result<(UserConfig, Started), ExitCode> {
logs::begin(begin);
let config = config::offer_setup()
.and_then(|()| UserConfig::load())
.map_err(|error| failure(&error))?;
logs::configured(&config);
interrupt::install().map_err(|error| failure(&error))?;
let notification = match ask(&config) {
NotificationAsk::Send(to) => {
Some(RunNotification::new(to, &config.email, about).map_err(|error| failure(&error))?)
}
NotificationAsk::Skip => None,
};
Ok((config, Started { notification }))
}
impl Started {
pub fn took(&mut self, issue: &IssueUrl, title: String) {
if let Some(notification) = &mut self.notification {
notification.took(issue, title);
}
}
pub fn finish(self, ending: Ending) -> ExitCode {
if matches!(ending, Ending::Skipped(_)) {
return run_ending::show(&ending);
}
logs::ended(run_ending::summary(&ending));
let code = run_ending::show(&ending);
if let Some(notification) = self.notification {
notification.send(&ending);
}
code
}
}
pub fn failure(error: &anyhow::Error) -> ExitCode {
logs::show_held();
progress::step(format_args!("{error:#}"));
ExitCode::FAILURE
}