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