mit_commit_message_lints/relates/cmd/
set_relates_to.rs1use std::{convert::TryInto, time::Duration};
2
3use miette::{Result, WrapErr, miette};
4use time::OffsetDateTime;
5
6use crate::{external::Vcs, relates::RelateTo};
7const CONFIG_KEY_EXPIRES: &str = "mit.relate.expires";
8
9pub fn set_relates_to(
13 config: &mut dyn Vcs,
14 relates: &RelateTo<'_>,
15 expires_in: Duration,
16) -> Result<()> {
17 set_vcs_relates_to(config, relates)?;
18 set_vcs_expires_time(config, expires_in)?;
19
20 Ok(())
21}
22
23fn set_vcs_relates_to(config: &mut dyn Vcs, relates: &RelateTo<'_>) -> Result<()> {
24 config.set_str("mit.relate.to", relates.to())?;
25 Ok(())
26}
27
28fn set_vcs_expires_time(config: &mut dyn Vcs, expires_in: Duration) -> Result<()> {
29 let now = OffsetDateTime::now_utc().unix_timestamp();
30 let expires_in_secs: i64 = expires_in
31 .as_secs()
32 .try_into()
33 .map_err(|_| miette!("Expiration time exceeds maximum supported value"))?;
34
35 let expiry_time = now
36 .checked_add(expires_in_secs)
37 .ok_or_else(|| miette!("Expiration time overflow"))?;
38
39 config
40 .set_i64(CONFIG_KEY_EXPIRES, expiry_time)
41 .wrap_err("failed to update the expiry time mit-relates-to")
42}
43
44#[cfg(test)]
45mod tests {
46 use std::{
47 collections::BTreeMap,
48 convert::TryFrom,
49 error::Error,
50 ops::Add,
51 time::{Duration, SystemTime, UNIX_EPOCH},
52 };
53
54 use crate::{
55 external::InMemory,
56 relates::{RelateTo, set_relates_to},
57 };
58
59 #[test]
60 fn the_first_initial_becomes_the_relates() {
61 let mut buffer = BTreeMap::new();
62
63 let mut vcs_config = InMemory::new(&mut buffer);
64
65 let relates_to = RelateTo::from("[#12345678]");
66 let actual = set_relates_to(&mut vcs_config, &relates_to, Duration::from_hours(1));
67
68 actual.unwrap();
69 assert_eq!(
70 Some(&"[#12345678]".to_string()),
71 buffer.get("mit.relate.to"),
72 "Expected the relates-to config to be set to the provided value"
73 );
74 }
75
76 #[test]
77 fn sets_the_expiry_time() {
78 let mut buffer = BTreeMap::new();
79 let mut vcs_config = InMemory::new(&mut buffer);
80
81 let relates = RelateTo::from("[#12345678]");
82 let actual = set_relates_to(&mut vcs_config, &relates, Duration::from_hours(1));
83
84 actual.unwrap();
85
86 let sec59min = SystemTime::now()
87 .duration_since(UNIX_EPOCH)
88 .map(|x| x.add(Duration::from_mins(59)))
89 .map_err(|x| -> Box<dyn Error> { Box::from(x) })
90 .map(|x| x.as_secs())
91 .and_then(|x| i64::try_from(x).map_err(Box::from))
92 .unwrap();
93
94 let sec61min = SystemTime::now()
95 .duration_since(UNIX_EPOCH)
96 .map(|x| x.add(Duration::from_mins(61)))
97 .map_err(|x| -> Box<dyn Error> { Box::from(x) })
98 .map(|x| x.as_secs())
99 .and_then(|x| i64::try_from(x).map_err(Box::from))
100 .unwrap();
101
102 let actual_expire_time: i64 = buffer
103 .get("mit.relate.expires")
104 .and_then(|x| x.parse().ok())
105 .expect("Failed to read expire");
106
107 assert!(
108 actual_expire_time < sec61min,
109 "Expected less than {}, found {}",
110 sec61min,
111 actual_expire_time
112 );
113 assert!(
114 actual_expire_time > sec59min,
115 "Expected more than {}, found {}",
116 sec59min,
117 actual_expire_time,
118 );
119 }
120}