Skip to main content

stratum/domain/
actor.rs

1use chrono::{DateTime, Utc};
2use git2::Signature;
3use std::str::FromStr;
4
5use crate::Error;
6
7/// A git actor who exists for the inspected repository
8pub struct Actor {
9    inner: Signature<'static>,
10}
11
12impl FromStr for Actor {
13    type Err = Error;
14
15    /// Instantiate an Actor from an author string
16    ///
17    /// Input is expected to be of the form "name <email>", as no time
18    /// information necassarily exists, the actors signature is instantiated
19    /// to have been created at epoch i.e. the unix timestamp. This is done as
20    /// the probability of an actors signature being valid within a repository
21    /// at the time of the unix time stamp is extremely unlikely  
22    fn from_str(s: &str) -> Result<Self, Self::Err> {
23        let name = s.split('<').next().unwrap().trim();
24        let email = s.split('<').nth(1).unwrap().trim_end_matches('>');
25        // As time is unknown but required, generate the UNIX timestamp and flag
26        // in the documentation.
27        let time = git2::Time::new(0, 0);
28
29        let sig = Signature::new(name, email, &time).map_err(Error::Git)?;
30        Ok(Self::new(sig))
31    }
32}
33
34impl Actor {
35    /// Instantiate a new Actor from their signature
36    pub fn new(signature: Signature<'_>) -> Self {
37        Self {
38            inner: signature.to_owned(),
39        }
40    }
41
42    /// Return the actors name if it exists
43    pub fn name(&self) -> Option<String> {
44        self.inner.name().map(|s| s.to_string())
45    }
46
47    /// Return the actors email if it exists
48    pub fn email(&self) -> Option<String> {
49        self.inner.email().map(|s| s.to_string())
50    }
51
52    /// Return the timestamp of actor action if it exists
53    pub fn timestamp(&self) -> Option<DateTime<Utc>> {
54        DateTime::from_timestamp_secs(self.inner.when().seconds())
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61
62    #[test]
63    fn test_actor() {
64        let sig = Signature::new(
65            "test",
66            "test@example.com",
67            &git2::Time::new(1_600_000_000, 0),
68        )
69        .unwrap();
70
71        let actor = Actor::new(sig);
72
73        assert_eq!(actor.name(), Some("test".to_string()));
74        assert_eq!(actor.email(), Some("test@example.com".to_string()));
75        assert_eq!(actor.timestamp().unwrap().timestamp(), 1_600_000_000);
76    }
77}