//! Tree query operations. use std::path::Path; use crate::commit::types::CommitOid; use crate::tree::types::{TreeEntry, TreeInfo}; use crate::{GitDomain, GitError, GitResult}; impl GitDomain { pub fn tree_get(&self, oid: &CommitOid) -> GitResult { let oid = oid .to_oid() .map_err(|_| GitError::InvalidOid(oid.to_string()))?; let tree = self .repo() .find_tree(oid) .map_err(|_| GitError::ObjectNotFound(oid.to_string()))?; Ok(TreeInfo::from_git2(&tree)) } pub fn tree_exists(&self, oid: &CommitOid) -> bool { oid.to_oid() .ok() .and_then(|oid| self.repo.find_tree(oid).ok()) .is_some() } pub fn tree_entry(&self, oid: &CommitOid, index: usize) -> GitResult { let oid = oid .to_oid() .map_err(|_| GitError::InvalidOid(oid.to_string()))?; let tree = self .repo() .find_tree(oid) .map_err(|_| GitError::ObjectNotFound(oid.to_string()))?; let entry = tree .get(index) .ok_or_else(|| GitError::Internal("tree entry not found".to_string()))?; Ok(TreeEntry::from_git2(entry, self.repo())) } pub fn tree_list(&self, oid: &CommitOid) -> GitResult> { let oid = oid .to_oid() .map_err(|_| GitError::InvalidOid(oid.to_string()))?; let tree = self .repo() .find_tree(oid) .map_err(|_| GitError::ObjectNotFound(oid.to_string()))?; let repo = self.repo(); let entries: Vec = tree .iter() .map(|entry| TreeEntry::from_git2(entry, repo)) .collect(); Ok(entries) } pub fn tree_entry_count(&self, oid: &CommitOid) -> GitResult { let info = self.tree_get(oid)?; Ok(info.entry_count) } pub fn tree_entry_by_path(&self, tree_oid: &CommitOid, path: &str) -> GitResult { let oid = tree_oid .to_oid() .map_err(|_| GitError::InvalidOid(tree_oid.to_string()))?; let tree = self .repo() .find_tree(oid) .map_err(|_| GitError::ObjectNotFound(tree_oid.to_string()))?; let entry = tree .get_path(Path::new(path)) .map_err(|e| GitError::Internal(format!("path '{}': {}", path, e)))?; Ok(TreeEntry::from_git2(entry, self.repo())) } pub fn tree_entry_by_path_from_commit( &self, commit_oid: &CommitOid, path: &str, ) -> GitResult { let oid = commit_oid .to_oid() .map_err(|_| GitError::InvalidOid(commit_oid.to_string()))?; let commit = self .repo() .find_commit(oid) .map_err(|_| GitError::ObjectNotFound(commit_oid.to_string()))?; let tree = self .repo() .find_tree(commit.tree_id()) .map_err(|e| GitError::Internal(e.to_string()))?; let entry = tree .get_path(Path::new(path)) .map_err(|e| GitError::Internal(format!("path '{}': {}", path, e)))?; Ok(TreeEntry::from_git2(entry, self.repo())) } pub fn tree_is_empty(&self, oid: &CommitOid) -> GitResult { let info = self.tree_get(oid)?; Ok(info.is_empty) } pub fn tree_diffstats( &self, old_tree: &CommitOid, new_tree: &CommitOid, ) -> GitResult { use crate::diff::types::DiffStats; let old_oid = old_tree .to_oid() .map_err(|_| GitError::InvalidOid(old_tree.to_string()))?; let new_oid = new_tree .to_oid() .map_err(|_| GitError::InvalidOid(new_tree.to_string()))?; let old_tree = self .repo() .find_tree(old_oid) .map_err(|e| GitError::Internal(e.to_string()))?; let new_tree = self .repo() .find_tree(new_oid) .map_err(|e| GitError::Internal(e.to_string()))?; let diff = self .repo() .diff_tree_to_tree(Some(&old_tree), Some(&new_tree), None) .map_err(|e| GitError::Internal(e.to_string()))?; let stats = diff .stats() .map_err(|e| GitError::Internal(e.to_string()))?; Ok(DiffStats::from_git2(&stats)) } }