use super::{CONFIG_REF_PREFIX, governing_config, repo_git};
use crate::template::GitRunner;
use std::io;
use std::path::Path;
#[derive(Debug, PartialEq, Eq)]
pub enum Resolution {
Tip(String),
ForkCommit { commit: String, tips: usize },
}
impl Resolution {
pub fn commit(&self) -> &str {
match self {
Resolution::Tip(commit) | Resolution::ForkCommit { commit, .. } => commit,
}
}
pub fn held(&self) -> Option<usize> {
match self {
Resolution::Tip(_) => None,
Resolution::ForkCommit { tips, .. } => Some(*tips),
}
}
}
pub fn current_config(workspace: &Path, rev: &str, git: &dyn GitRunner) -> io::Result<Resolution> {
let governing = governing_config(workspace, rev, git)?;
let repo = repo_git(workspace);
let heads = git.run_capture(
&repo,
&[
"for-each-ref",
"--format=%(objectname)",
&format!("refs/heads/{CONFIG_REF_PREFIX}"),
],
)?;
let mut tips: Vec<String> = heads
.lines()
.map(str::trim)
.filter(|tip| !tip.is_empty())
.filter(|tip| {
git.run(&repo, &["merge-base", "--is-ancestor", &governing, tip])
.is_ok()
})
.map(str::to_owned)
.collect();
tips.sort();
tips.dedup();
match tips.len() {
1 => Ok(Resolution::Tip(tips.remove(0))),
n => Ok(Resolution::ForkCommit {
commit: governing,
tips: n,
}),
}
}
#[cfg(test)]
mod tests;