use std::path::Path;
use std::error::Error;
use git2::{ObjectType, Repository};
pub(crate) fn get_commit_messages<P: AsRef<Path>>(repo_path: P, refspecs: Vec<String>) -> Result<Vec<String>, Box<dyn Error>> {
let repo = Repository::discover(repo_path)?;
let mut revwalk = repo.revwalk()?;
for commit in refspecs {
if let Some(stripped) = commit.strip_prefix('^') {
let obj = repo.revparse_single(stripped)?;
revwalk.hide(obj.id())?;
continue;
}
let revspec = repo.revparse(commit.as_str())?;
if revspec.mode().contains(git2::RevparseMode::SINGLE) {
revwalk.push(revspec.from().unwrap().id())?;
} else {
let from = revspec.from().unwrap().id();
let to = revspec.to().unwrap().id();
revwalk.push(to)?;
if revspec.mode().contains(git2::RevparseMode::MERGE_BASE) {
let base = repo.merge_base(from, to)?;
let o = repo.find_object(base, Some(ObjectType::Commit))?;
revwalk.push(o.id())?;
}
revwalk.hide(from)?;
}
}
let mut messages: Vec<String> = Vec::new();
for object_id in revwalk {
let commit = repo.find_commit(object_id?)?;
messages.push(String::from(commit.message().unwrap()));
}
Result::Ok(messages)
}