use crate::{FileTree, HashId}; use git2::Repository; use std::sync::Arc; /// Represent a commit on a repository /// /// When creating a commit object, it is guaranteed that it exists in /// the repository. #[derive(Clone)] pub struct Commit { pub id: HashId, repo: Arc, } impl Commit { /// Create a commit object and check if it exists in the repo pub(crate) fn new(r: &Arc, id: HashId) -> Option { r.find_commit(id.to_oid()).ok().map(|_| Self { id, repo: Arc::clone(r), }) } /// Get a utf-8 string representation of the commit ID pub fn id_str(&self) -> String { self.id.to_string() } /// Get the summary line as a utf-7 string pub fn summary(&self) -> String { self.find().summary().unwrap().into() } /// Get the number of parents pub fn parent_count(&self) -> usize { self.repo .find_commit(self.id.to_oid()) .unwrap() .parent_count() } /// Return the first parent, if it exists pub fn first_parent(&self) -> Option { self.find() .parent(0) .ok() .and_then(|c| Self::new(&self.repo, c.id().into())) } /// Get a specific parent, if it exists pub fn parent(&self, num: usize) -> Option { self.find() .parent(num) .ok() .and_then(|c| Self::new(&self.repo, c.id().into())) } pub fn parents(&self) -> Vec { self.find() .parents() .map(|c| Self::new(&self.repo, c.id().into()).unwrap()) .collect() } /// Get the file tree for this commit pub fn get_tree(&self) -> Arc { FileTree::new(&self.repo, self.id.clone()) } fn find(&self) -> git2::Commit { self.repo.find_commit(self.id.to_oid()).unwrap() } }