mod branch_sync;
pub(crate) mod cache;
mod ci_checks;
pub(super) mod errors;
mod merge_ready;
mod pr_state;
pub(crate) mod prompt;
mod review;
use crate::domain::{
branch_sync::BranchSyncRepository, ci_checks::CiChecksRepository,
merge_ready::MergeReadinessRepository, pr_state::PrStateRepository, review::ReviewRepository,
};
use errors::{ErrorLogger, ErrorPresenter};
pub enum OutputToken {
Conflict,
UpdateBranch,
SyncUnknown,
CiFail,
CiAction,
ReviewRequested,
MergeReady,
}
pub fn run<C, L, P>(client: &C, err_logger: &L, err_presenter: &P) -> Vec<OutputToken>
where
C: PrStateRepository
+ BranchSyncRepository
+ CiChecksRepository
+ ReviewRepository
+ MergeReadinessRepository
+ Sync,
L: ErrorLogger + Sync,
P: ErrorPresenter + Sync,
{
let Some(lifecycle) = pr_state::fetch(client, err_logger, err_presenter) else {
return vec![];
};
if !pr_state::is_open(&lifecycle) {
return vec![];
}
let (sync_result, ci_result) = std::thread::scope(|s| {
let sync_handle = s.spawn(|| branch_sync::fetch(client));
let ci_handle = s.spawn(|| ci_checks::fetch(client));
(
sync_handle.join().expect("branch_sync thread panicked"),
ci_handle.join().expect("ci_checks thread panicked"),
)
});
let (sync_status, buckets) = match (sync_result, ci_result) {
(Ok(s), Ok(b)) => (s, b),
(Err(e), _) | (_, Err(e)) => {
errors::handle(e, err_logger, err_presenter);
return vec![];
}
};
let Some(review_status) = review::fetch(client, err_logger, err_presenter) else {
return vec![];
};
let Some(readiness) = merge_ready::fetch(client, err_logger, err_presenter) else {
return vec![];
};
let mut tokens: Vec<OutputToken> = Vec::new();
if let Some(t) = branch_sync::check(&sync_status) {
tokens.push(t);
}
if let Some(t) = ci_checks::check(&buckets) {
tokens.push(t);
}
if let Some(t) = review::check(&review_status) {
tokens.push(t);
}
if tokens.is_empty()
&& let Some(t) = merge_ready::check(&readiness)
{
tokens.push(t);
}
tokens
}