use crate::Result;
use git2::Repository;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CommitInfo {
pub id: String,
pub short_id: String,
pub message: String,
pub author: String,
pub email: String,
pub timestamp: i64,
}
impl CommitInfo {
pub fn head(repo: &Repository) -> Result<Option<Self>> {
let head = match repo.head() {
Ok(h) => h,
Err(_) => return Ok(None),
};
let commit = match head.peel_to_commit() {
Ok(c) => c,
Err(_) => return Ok(None),
};
Ok(Some(Self::from_commit(&commit)?))
}
pub fn recent(repo: &Repository, count: usize) -> Result<Vec<Self>> {
let mut commits = Vec::new();
let head = match repo.head() {
Ok(h) => h,
Err(_) => return Ok(commits),
};
let commit = match head.peel_to_commit() {
Ok(c) => c,
Err(_) => return Ok(commits),
};
let mut current = Some(commit);
let mut remaining = count;
while let Some(c) = current {
if remaining == 0 {
break;
}
commits.push(Self::from_commit(&c)?);
remaining -= 1;
current = c.parent(0).ok();
}
Ok(commits)
}
fn from_commit(commit: &git2::Commit) -> Result<Self> {
let id = commit.id().to_string();
let short_id = id.chars().take(7).collect();
let message = commit.message().map(|m| m.to_string()).unwrap_or_default();
let author = commit.author();
let name = author.name().unwrap_or("").to_string();
let email = author.email().unwrap_or("").to_string();
let timestamp = author.when().seconds();
Ok(Self {
id,
short_id,
message,
author: name,
email,
timestamp,
})
}
}