use std::fmt;
use std::num::NonZeroUsize;
use anyhow::Result;
use crate::claim;
use crate::issue::{IssueUrl, Repo};
use crate::launch::{self, AlreadyRunning, Launch, Start};
use crate::progress;
use crate::ready::{self, ReadyIssue};
pub enum Outcome {
Taken(Taken),
Skipped(Skipped),
}
pub struct Taken {
pub issue: IssueUrl,
pub title: String,
pub base: String,
pub is_spec: bool,
}
pub enum Skipped {
AlreadyRunning(AlreadyRunning),
AtClaimLimit {
repo: Repo,
claimed: usize,
limit: NonZeroUsize,
},
NoReadyIssue(Repo),
}
impl Skipped {
pub fn repo(&self) -> &Repo {
match self {
Self::AlreadyRunning(AlreadyRunning(repo))
| Self::AtClaimLimit { repo, .. }
| Self::NoReadyIssue(repo) => repo,
}
}
}
impl fmt::Display for Skipped {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::AlreadyRunning(running) => running.fmt(f),
Self::AtClaimLimit {
repo,
claimed,
limit,
} => write!(
f,
"at the Claim limit on {}: {claimed} open issue(s) labelled {}, \
pickup.limit is {limit}",
repo.slug(),
claim::IN_PROGRESS
),
Self::NoReadyIssue(repo) => write!(f, "no Ready issue on {}", repo.slug()),
}
}
}
pub fn run(base: Option<&str>, limit: NonZeroUsize) -> Result<Outcome> {
let Launch {
git, repo, base, ..
} = match launch::start(base)? {
Start::Clear(launch) => launch,
Start::AlreadyRunning(running) => {
return Ok(Outcome::Skipped(Skipped::AlreadyRunning(running)));
}
};
claim::sweep(&repo);
let claimed = claim::open_count(&repo)?;
if claimed >= limit.get() {
return Ok(Outcome::Skipped(Skipped::AtClaimLimit {
repo,
claimed,
limit,
}));
}
let Some(ReadyIssue { listed, is_spec }) = ready::first(&git, &repo)? else {
return Ok(Outcome::Skipped(Skipped::NoReadyIssue(repo)));
};
progress::step(format_args!(
"taking Ready issue #{} \"{}\", as thirdshift {} would",
listed.issue.number, listed.title, listed.issue.url
));
Ok(Outcome::Taken(Taken {
issue: listed.issue,
title: listed.title,
base,
is_spec,
}))
}