mit_commit_message_lints/mit/cmd/
set_commit_authors.rs1use std::{
2 convert::TryInto,
3 ops::Add,
4 time::{Duration, SystemTime, UNIX_EPOCH},
5};
6
7use miette::{IntoDiagnostic, Result, WrapErr};
8
9use crate::{
10 external::Vcs,
11 mit::{
12 cmd::{errors::Error::NoAuthorsToSet, vcs::has_vcs_coauthor, CONFIG_KEY_EXPIRES},
13 Author,
14 },
15};
16
17pub fn set_commit_authors(
22 config: &mut dyn Vcs,
23 authors: &[&Author<'_>],
24 expires_in: Duration,
25) -> Result<()> {
26 let (first_author, others) = authors.split_first().ok_or(NoAuthorsToSet)?;
27
28 remove_coauthors(config)?;
29 set_vcs_user(config, first_author)?;
30 set_vcs_coauthors(config, others)?;
31 set_vcs_expires_time(config, expires_in)?;
32
33 Ok(())
34}
35
36fn remove_coauthors(config: &mut dyn Vcs) -> Result<()> {
37 get_defined_vcs_coauthor_keys(config)
38 .into_iter()
39 .try_for_each(|key| config.remove(&key))?;
40
41 Ok(())
42}
43
44#[allow(clippy::maybe_infinite_iter)]
45fn get_defined_vcs_coauthor_keys(config: &dyn Vcs) -> Vec<String> {
46 (0..)
47 .take_while(|index| has_vcs_coauthor(config, *index))
48 .flat_map(|index| {
49 vec![
50 format!("mit.author.coauthors.{index}.name"),
51 format!("mit.author.coauthors.{index}.email"),
52 ]
53 .into_iter()
54 })
55 .collect()
56}
57
58fn set_vcs_coauthors(config: &mut dyn Vcs, authors: &[&Author<'_>]) -> Result<()> {
59 authors
60 .iter()
61 .enumerate()
62 .try_for_each(|(index, author)| set_vcs_coauthor(config, index, author))
63}
64
65fn set_vcs_coauthor(config: &mut dyn Vcs, index: usize, author: &Author<'_>) -> Result<()> {
66 set_vcs_coauthor_name(config, index, author)?;
67 set_vcs_coauthor_email(config, index, author)?;
68
69 Ok(())
70}
71
72fn set_vcs_coauthor_name(config: &mut dyn Vcs, index: usize, author: &Author<'_>) -> Result<()> {
73 config.set_str(&format!("mit.author.coauthors.{index}.name"), author.name())?;
74 Ok(())
75}
76
77fn set_vcs_coauthor_email(config: &mut dyn Vcs, index: usize, author: &Author<'_>) -> Result<()> {
78 config.set_str(
79 &format!("mit.author.coauthors.{index}.email"),
80 author.email(),
81 )?;
82 Ok(())
83}
84
85fn set_vcs_user(config: &mut dyn Vcs, author: &Author<'_>) -> Result<()> {
86 config.set_str("user.name", author.name())?;
87 config.set_str("user.email", author.email())?;
88 set_author_signing_key(config, author)?;
89
90 Ok(())
91}
92
93fn set_author_signing_key(config: &mut dyn Vcs, author: &Author<'_>) -> Result<()> {
94 match author.signingkey() {
95 Some(key) => config
96 .set_str("user.signingkey", key)
97 .wrap_err("failed to set git author's signing key "),
98 None => config.remove("user.signingkey").or_else(|_| Ok(())),
99 }
100}
101
102fn set_vcs_expires_time(config: &mut dyn Vcs, expires_in: Duration) -> Result<()> {
103 let now = SystemTime::now()
104 .duration_since(UNIX_EPOCH)
105 .into_diagnostic()?;
106 let expiry_time = now.add(expires_in).as_secs().try_into().into_diagnostic()?;
107 config
108 .set_i64(CONFIG_KEY_EXPIRES, expiry_time)
109 .wrap_err("failed to set author expiry name")
110}