use std::process::ExitCode;
use crate::architect::{self, Reviewed};
use crate::config::UserConfig;
use crate::failed_run::FailedRun;
use crate::harness::Choice;
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;
use crate::setup;
use crate::skills;
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 = setup::offer()
.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 built_with(&mut self, harness: &Choice) {
if let Some(notification) = &mut self.notification {
notification.built_with(harness);
}
}
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 {
skills::remove_written();
let account = match run_ending::read(&ending) {
Ok(account) => account,
Err(skip) => return run_ending::show_skip(skip),
};
logs::ended(account.summary());
let code = account.show();
if let Some(notification) = self.notification {
notification.send(&account);
}
code
}
}
pub fn failure(error: &anyhow::Error) -> ExitCode {
logs::show_held();
progress::step(format_args!("{error:#}"));
ExitCode::FAILURE
}