use miette::Result;
use rand::seq::SliceRandom;
use crate::external::Vcs;
use crate::mit::cmd::set_commit_authors::{remove_coauthors, set_vcs_coauthor, set_vcs_user};
use crate::mit::{cmd::vcs::get_vcs_coauthors_config, Author};
pub fn rotate_authors(config: &mut dyn Vcs, strategy: crate::mit::RotationOption) -> Result<()> {
let primary_name = config.get_str("user.name")?.map(String::from);
let primary_email = config.get_str("user.email")?.map(String::from);
let primary_signingkey = config.get_str("user.signingkey")?.map(String::from);
let primary = match (primary_name, primary_email, primary_signingkey) {
(Some(name), Some(email), signingkey) => Some(Author::new(
name.into(),
email.into(),
signingkey.map(Into::into),
)),
_ => return Ok(()), };
let coauthor_emails: Vec<String> = get_vcs_coauthors_config(config, "email")?
.into_iter()
.filter_map(|x| x.map(|s| s.to_string()))
.collect();
let coauthors: Vec<Author> = get_vcs_coauthors_config(config, "name")?
.into_iter()
.filter_map(|x| x.map(|s| s.to_string()))
.zip(coauthor_emails)
.filter_map(|(name, email)| {
if name.is_empty() || email.is_empty() {
None
} else {
Some(Author::new(name.into(), email.into(), None))
}
})
.collect();
let mut all_authors: Vec<Author> = vec![primary.unwrap()];
all_authors.extend(coauthors);
if all_authors.len() <= 1 {
return Ok(());
}
match strategy {
crate::mit::RotationOption::Off => return Ok(()),
crate::mit::RotationOption::RoundRobin => {
all_authors.rotate_left(1);
}
crate::mit::RotationOption::Random => {
all_authors.shuffle(&mut rand::rng());
}
}
remove_coauthors(config)?;
set_vcs_user(config, &all_authors[0])?;
all_authors[1..]
.iter()
.enumerate()
.try_for_each(|(index, author)| set_vcs_coauthor(config, index, author))?;
Ok(())
}