gitdataai/libs/git/tree/query.rs
2026-04-14 19:02:01 +08:00

134 lines
4.4 KiB
Rust

//! 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<TreeInfo> {
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<TreeEntry> {
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<Vec<TreeEntry>> {
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<TreeEntry> = tree
.iter()
.map(|entry| TreeEntry::from_git2(entry, repo))
.collect();
Ok(entries)
}
pub fn tree_entry_count(&self, oid: &CommitOid) -> GitResult<usize> {
let info = self.tree_get(oid)?;
Ok(info.entry_count)
}
pub fn tree_entry_by_path(&self, tree_oid: &CommitOid, path: &str) -> GitResult<TreeEntry> {
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<TreeEntry> {
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<bool> {
let info = self.tree_get(oid)?;
Ok(info.is_empty)
}
pub fn tree_diffstats(
&self,
old_tree: &CommitOid,
new_tree: &CommitOid,
) -> GitResult<crate::diff::types::DiffStats> {
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))
}
}