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, author: CommitAuthor, time: i64, } pub fn get_git_log(path: String) -> eyre::Result { 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 = 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::>() .join("\n"); let message_content = message_content .clone() .skip(1) .collect::>() .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) }