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 [
50 format!("mit.author.coauthors.{index}.name"),
51 format!("mit.author.coauthors.{index}.email"),
52 ]
53 })
54 .collect()
55}
56
57fn set_vcs_coauthors(config: &mut dyn Vcs, authors: &[&Author<'_>]) -> Result<()> {
58 authors
59 .iter()
60 .enumerate()
61 .try_for_each(|(index, author)| set_vcs_coauthor(config, index, author))
62}
63
64fn set_vcs_coauthor(config: &mut dyn Vcs, index: usize, author: &Author<'_>) -> Result<()> {
65 set_vcs_coauthor_name(config, index, author)?;
66 set_vcs_coauthor_email(config, index, author)?;
67
68 Ok(())
69}
70
71fn set_vcs_coauthor_name(config: &mut dyn Vcs, index: usize, author: &Author<'_>) -> Result<()> {
72 config.set_str(&format!("mit.author.coauthors.{index}.name"), author.name())?;
73 Ok(())
74}
75
76fn set_vcs_coauthor_email(config: &mut dyn Vcs, index: usize, author: &Author<'_>) -> Result<()> {
77 config.set_str(
78 &format!("mit.author.coauthors.{index}.email"),
79 author.email(),
80 )?;
81 Ok(())
82}
83
84fn set_vcs_user(config: &mut dyn Vcs, author: &Author<'_>) -> Result<()> {
85 config.set_str("user.name", author.name())?;
86 config.set_str("user.email", author.email())?;
87 set_author_signing_key(config, author)?;
88
89 Ok(())
90}
91
92fn set_author_signing_key(config: &mut dyn Vcs, author: &Author<'_>) -> Result<()> {
93 if let Some(key) = author.signingkey() {
94 config
95 .set_str("user.signingkey", key)
96 .wrap_err("failed to set git author's signing key ")
97 } else {
98 if config.get_str("user.signingkey")?.is_some() {
99 config
100 .remove("user.signingkey")
101 .wrap_err("failed to remove git author's signing key")?;
102 }
103 Ok(())
104 }
105}
106
107fn set_vcs_expires_time(config: &mut dyn Vcs, expires_in: Duration) -> Result<()> {
108 let now = SystemTime::now()
109 .duration_since(UNIX_EPOCH)
110 .into_diagnostic()?;
111 let expiry_time = now.add(expires_in).as_secs().try_into().into_diagnostic()?;
112 config
113 .set_i64(CONFIG_KEY_EXPIRES, expiry_time)
114 .wrap_err("failed to set author expiry time")
115}