1use crate::Result;
2use git2::Repository;
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct CommitInfo {
7 pub id: String,
8 pub short_id: String,
9 pub message: String,
10 pub author: String,
11 pub email: String,
12 pub timestamp: i64,
13}
14
15impl CommitInfo {
16 pub fn head(repo: &Repository) -> Result<Option<Self>> {
17 let head = match repo.head() {
18 Ok(h) => h,
19 Err(_) => return Ok(None),
20 };
21
22 let commit = match head.peel_to_commit() {
23 Ok(c) => c,
24 Err(_) => return Ok(None),
25 };
26
27 Ok(Some(Self::from_commit(&commit)?))
28 }
29
30 pub fn recent(repo: &Repository, count: usize) -> Result<Vec<Self>> {
31 let mut commits = Vec::new();
32
33 let head = match repo.head() {
34 Ok(h) => h,
35 Err(_) => return Ok(commits),
36 };
37
38 let commit = match head.peel_to_commit() {
39 Ok(c) => c,
40 Err(_) => return Ok(commits),
41 };
42
43 let mut current = Some(commit);
44 let mut remaining = count;
45
46 while let Some(c) = current {
47 if remaining == 0 {
48 break;
49 }
50
51 commits.push(Self::from_commit(&c)?);
52 remaining -= 1;
53
54 current = c.parent(0).ok();
55 }
56
57 Ok(commits)
58 }
59
60 fn from_commit(commit: &git2::Commit) -> Result<Self> {
61 let id = commit.id().to_string();
62 let short_id = id.chars().take(7).collect();
63
64 let message = commit.message().map(|m| m.to_string()).unwrap_or_default();
65
66 let author = commit.author();
67 let name = author.name().unwrap_or("").to_string();
68 let email = author.email().unwrap_or("").to_string();
69 let timestamp = author.when().seconds();
70
71 Ok(Self {
72 id,
73 short_id,
74 message,
75 author: name,
76 email,
77 timestamp,
78 })
79 }
80}