mit_commit_message_lints/mit/cmd/
rotate_authors.rs1use miette::Result;
2use rand::seq::SliceRandom;
3
4use crate::external::Vcs;
5use crate::mit::cmd::set_commit_authors::{remove_coauthors, set_vcs_coauthor, set_vcs_user};
6use crate::mit::{cmd::vcs::get_vcs_coauthors_config, Author};
7
8pub fn rotate_authors(config: &mut dyn Vcs, strategy: crate::mit::RotationOption) -> Result<()> {
29 let primary_name = config.get_str("user.name")?.map(String::from);
31 let primary_email = config.get_str("user.email")?.map(String::from);
32 let primary_signingkey = config.get_str("user.signingkey")?.map(String::from);
33
34 let primary = match (primary_name, primary_email, primary_signingkey) {
35 (Some(name), Some(email), signingkey) => Some(Author::new(
36 name.into(),
37 email.into(),
38 signingkey.map(Into::into),
39 )),
40 _ => return Ok(()), };
42
43 let coauthor_emails: Vec<String> = get_vcs_coauthors_config(config, "email")?
45 .into_iter()
46 .filter_map(|x| x.map(|s| s.to_string()))
47 .collect();
48
49 let coauthors: Vec<Author> = get_vcs_coauthors_config(config, "name")?
50 .into_iter()
51 .filter_map(|x| x.map(|s| s.to_string()))
52 .zip(coauthor_emails)
53 .filter_map(|(name, email)| {
54 if name.is_empty() || email.is_empty() {
55 None
56 } else {
57 Some(Author::new(name.into(), email.into(), None))
58 }
59 })
60 .collect();
61
62 let mut all_authors: Vec<Author> = vec![primary.unwrap()];
64 all_authors.extend(coauthors);
65
66 if all_authors.len() <= 1 {
68 return Ok(());
69 }
70
71 match strategy {
73 crate::mit::RotationOption::Off => return Ok(()),
74 crate::mit::RotationOption::RoundRobin => {
75 all_authors.rotate_left(1);
76 }
77 crate::mit::RotationOption::Random => {
78 all_authors.shuffle(&mut rand::rng());
79 }
80 }
81
82 remove_coauthors(config)?;
84 set_vcs_user(config, &all_authors[0])?;
85 all_authors[1..]
86 .iter()
87 .enumerate()
88 .try_for_each(|(index, author)| set_vcs_coauthor(config, index, author))?;
89
90 Ok(())
91}