git-log/crates/gitlog_core/src/lib.rs
2022-11-06 16:08:01 +01:00

79 lines
2.1 KiB
Rust

use git2::Repository;
use serde::Serialize;
#[allow(dead_code)]
#[derive(Debug, Serialize)]
struct CommitAuthor {
email: String,
name: String,
}
#[allow(dead_code)]
#[derive(Debug, Serialize)]
struct Commit {
title: String,
#[serde(skip_serializing_if = "Option::is_none")]
message: Option<String>,
author: CommitAuthor,
time: i64,
}
pub fn get_git_log(path: String) -> eyre::Result<String> {
let repo = Repository::open(path)?;
let mut revwalk = repo.revwalk()?;
revwalk.set_sorting(git2::Sort::TIME)?;
let revspec = repo.revparse("HEAD")?;
let from = revspec.from().ok_or(eyre::anyhow!("could not get HEAD"))?;
revwalk.push(from.id())?;
let mut commits: Vec<Commit> = Vec::new();
for rev in revwalk.enumerate() {
let oid = rev.1?;
let commit = repo.find_commit(oid)?;
let message = commit
.message()
.ok_or(eyre::anyhow!("could not find message from commit"))?;
let timestamp = commit.time();
let author = commit.author();
let message_content = message.split("\n");
let message_heading = message_content
.clone()
.take(1)
.collect::<Vec<&str>>()
.join("\n");
let message_content = message_content
.clone()
.skip(1)
.collect::<Vec<&str>>()
.join("\n");
let commit = Commit {
title: message_heading,
message: if message_content == "" {
None
} else {
Some(message_content)
},
author: CommitAuthor {
email: author
.email()
.ok_or(eyre::anyhow!("could not get authors email"))?
.to_string(),
name: author
.name()
.ok_or(eyre::anyhow!("could not get authors name"))?
.to_string(),
},
time: timestamp.seconds(),
};
commits.push(commit);
}
let commits_str = serde_json::to_string(&commits)?;
Ok(commits_str)
}