use chrono::{DateTime, Utc};
use git2::Signature;
use std::str::FromStr;
use crate::Error;
pub struct Actor {
inner: Signature<'static>,
}
impl FromStr for Actor {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let start_idx = s.find('<').unwrap_or_default();
let end_idx = s.find('>').unwrap_or_default();
let time = git2::Time::new(0, 0);
let sig = Signature::new(&s[..start_idx], &s[start_idx + 1..end_idx], &time)
.map_err(Error::Git)?;
Ok(Self::new(sig))
}
}
impl Actor {
pub fn new(signature: Signature<'_>) -> Self {
Self {
inner: signature.to_owned(),
}
}
pub fn name(&self) -> Option<&str> {
self.inner.name()
}
pub fn email(&self) -> Option<&str> {
self.inner.email()
}
pub fn timestamp(&self) -> Option<DateTime<Utc>> {
DateTime::from_timestamp_secs(self.inner.when().seconds())
}
pub fn offset(&self) -> i32 {
self.inner.when().offset_minutes()
}
}
#[cfg(test)]
mod tests {
use super::*;
fn actor_factory() -> Actor {
let sig = Signature::new(
"test",
"test@example.com",
&git2::Time::new(1_600_000_000, -60),
)
.unwrap();
Actor::new(sig)
}
#[test]
fn test_name() {
let actor = actor_factory();
assert_eq!(actor.name(), Some("test"));
}
#[test]
fn test_email() {
let actor = actor_factory();
assert_eq!(actor.email(), Some("test@example.com"));
}
#[test]
fn test_time() {
let actor = actor_factory();
assert_eq!(actor.timestamp().unwrap().timestamp(), 1_600_000_000);
}
#[test]
fn test_offset() {
let actor = actor_factory();
assert_eq!(actor.offset(), -60);
}
#[test]
fn test_from_str() {
let actor = Actor::from_str("test <test@example.com>").unwrap();
assert_eq!(actor.name(), Some("test"));
assert_eq!(actor.email(), Some("test@example.com"));
assert_eq!(actor.timestamp().unwrap().timestamp(), 0);
assert_eq!(actor.offset(), 0);
}
#[test]
fn test_malformed_from_str() {
let result = Actor::from_str("some nonsense <>");
assert!(result.is_err())
}
#[test]
fn test_extended_from_str() {
let actor = Actor::from_str("test <test@example.com> nonsense").unwrap();
assert_eq!(actor.name(), Some("test"));
assert_eq!(actor.email(), Some("test@example.com"));
}
#[test]
fn test_surname() {
let actor = Actor::from_str("test surname <email>").unwrap();
assert_eq!(actor.name(), Some("test surname"));
}
}