232 lines
7.7 KiB
Rust
232 lines
7.7 KiB
Rust
//! Commit querying operations.
|
|
|
|
use crate::commit::types::*;
|
|
use crate::{GitDomain, GitError, GitResult};
|
|
|
|
impl GitDomain {
|
|
pub fn commit_get(&self, oid: &CommitOid) -> GitResult<CommitMeta> {
|
|
let commit = self
|
|
.repo()
|
|
.find_commit(oid.to_oid()?)
|
|
.map_err(|_e| GitError::ObjectNotFound(oid.to_string()))?;
|
|
Ok(CommitMeta::from_git2(&commit))
|
|
}
|
|
|
|
pub fn commit_get_prefix(&self, prefix: &str) -> GitResult<CommitMeta> {
|
|
let commit = self
|
|
.repo()
|
|
.find_commit_by_prefix(prefix)
|
|
.map_err(|_e| GitError::InvalidOid(format!("prefix: {}", prefix)))?;
|
|
Ok(CommitMeta::from_git2(&commit))
|
|
}
|
|
|
|
pub fn commit_exists(&self, oid: &CommitOid) -> bool {
|
|
match oid.to_oid() {
|
|
Ok(oid) => self.repo.find_commit(oid).is_ok(),
|
|
Err(_) => false,
|
|
}
|
|
}
|
|
|
|
pub fn commit_is_commit(&self, oid: &CommitOid) -> bool {
|
|
match oid.to_oid() {
|
|
Ok(oid) => match self.repo.find_object(oid, None) {
|
|
Ok(obj) => obj.kind() == Some(git2::ObjectType::Commit),
|
|
Err(_) => false,
|
|
},
|
|
Err(_) => false,
|
|
}
|
|
}
|
|
|
|
pub fn commit_message(&self, oid: &CommitOid) -> GitResult<String> {
|
|
let commit = self
|
|
.repo()
|
|
.find_commit(oid.to_oid()?)
|
|
.map_err(|_e| GitError::ObjectNotFound(oid.to_string()))?;
|
|
Ok(commit.message().unwrap_or("").to_string())
|
|
}
|
|
|
|
pub fn commit_summary(&self, oid: &CommitOid) -> GitResult<String> {
|
|
let commit = self
|
|
.repo()
|
|
.find_commit(oid.to_oid()?)
|
|
.map_err(|_e| GitError::ObjectNotFound(oid.to_string()))?;
|
|
Ok(commit.summary().unwrap_or("").to_string())
|
|
}
|
|
|
|
pub fn commit_short_id(&self, oid: &CommitOid) -> GitResult<String> {
|
|
let _ = self
|
|
.repo()
|
|
.find_commit(oid.to_oid()?)
|
|
.map_err(|_e| GitError::ObjectNotFound(oid.to_string()))?;
|
|
let len = oid.0.len();
|
|
if len < 7 {
|
|
return Err(GitError::InvalidOid(oid.to_string()));
|
|
}
|
|
Ok(oid.0[..7].to_string())
|
|
}
|
|
|
|
pub fn commit_author(&self, oid: &CommitOid) -> GitResult<CommitSignature> {
|
|
let commit = self
|
|
.repo()
|
|
.find_commit(oid.to_oid()?)
|
|
.map_err(|_e| GitError::ObjectNotFound(oid.to_string()))?;
|
|
Ok(CommitSignature::from_git2(commit.author()))
|
|
}
|
|
|
|
pub fn commit_committer(&self, oid: &CommitOid) -> GitResult<CommitSignature> {
|
|
let commit = self
|
|
.repo()
|
|
.find_commit(oid.to_oid()?)
|
|
.map_err(|_e| GitError::ObjectNotFound(oid.to_string()))?;
|
|
Ok(CommitSignature::from_git2(commit.committer()))
|
|
}
|
|
|
|
pub fn commit_time(&self, oid: &CommitOid) -> GitResult<i64> {
|
|
let commit = self
|
|
.repo()
|
|
.find_commit(oid.to_oid()?)
|
|
.map_err(|_e| GitError::ObjectNotFound(oid.to_string()))?;
|
|
Ok(commit.time().seconds())
|
|
}
|
|
|
|
pub fn commit_time_offset(&self, oid: &CommitOid) -> GitResult<i32> {
|
|
let commit = self
|
|
.repo()
|
|
.find_commit(oid.to_oid()?)
|
|
.map_err(|_e| GitError::ObjectNotFound(oid.to_string()))?;
|
|
Ok(commit.time().offset_minutes())
|
|
}
|
|
|
|
pub fn commit_encoding(&self, oid: &CommitOid) -> GitResult<Option<String>> {
|
|
let commit = self
|
|
.repo()
|
|
.find_commit(oid.to_oid()?)
|
|
.map_err(|_e| GitError::ObjectNotFound(oid.to_string()))?;
|
|
Ok(commit.message_encoding().map(String::from))
|
|
}
|
|
|
|
pub fn commit_tree_id(&self, oid: &CommitOid) -> GitResult<CommitOid> {
|
|
let commit = self
|
|
.repo()
|
|
.find_commit(oid.to_oid()?)
|
|
.map_err(|_e| GitError::ObjectNotFound(oid.to_string()))?;
|
|
Ok(CommitOid::from_git2(commit.tree_id()))
|
|
}
|
|
|
|
pub fn commit_parent_count(&self, oid: &CommitOid) -> GitResult<usize> {
|
|
let commit = self
|
|
.repo()
|
|
.find_commit(oid.to_oid()?)
|
|
.map_err(|_e| GitError::ObjectNotFound(oid.to_string()))?;
|
|
Ok(commit.parent_count())
|
|
}
|
|
|
|
pub fn commit_parent_ids(&self, oid: &CommitOid) -> GitResult<Vec<CommitOid>> {
|
|
let commit = self
|
|
.repo()
|
|
.find_commit(oid.to_oid()?)
|
|
.map_err(|_e| GitError::ObjectNotFound(oid.to_string()))?;
|
|
Ok(commit.parent_ids().map(CommitOid::from_git2).collect())
|
|
}
|
|
|
|
pub fn commit_parent(&self, oid: &CommitOid, index: usize) -> GitResult<CommitMeta> {
|
|
let commit = self
|
|
.repo()
|
|
.find_commit(oid.to_oid()?)
|
|
.map_err(|_e| GitError::ObjectNotFound(oid.to_string()))?;
|
|
let parent = commit
|
|
.parent(index)
|
|
.map_err(|e| GitError::Internal(e.to_string()))?;
|
|
Ok(CommitMeta::from_git2(&parent))
|
|
}
|
|
|
|
pub fn commit_first_parent(&self, oid: &CommitOid) -> GitResult<Option<CommitMeta>> {
|
|
let commit = self
|
|
.repo()
|
|
.find_commit(oid.to_oid()?)
|
|
.map_err(|_e| GitError::ObjectNotFound(oid.to_string()))?;
|
|
if commit.parent_count() > 0 {
|
|
let parent = commit
|
|
.parent(0)
|
|
.map_err(|e| GitError::Internal(e.to_string()))?;
|
|
Ok(Some(CommitMeta::from_git2(&parent)))
|
|
} else {
|
|
Ok(None)
|
|
}
|
|
}
|
|
|
|
pub fn commit_is_merge(&self, oid: &CommitOid) -> GitResult<bool> {
|
|
let commit = self
|
|
.repo()
|
|
.find_commit(oid.to_oid()?)
|
|
.map_err(|_e| GitError::ObjectNotFound(oid.to_string()))?;
|
|
Ok(commit.parent_count() > 1)
|
|
}
|
|
|
|
pub fn commit_log(
|
|
&self,
|
|
rev: Option<&str>,
|
|
offset: usize,
|
|
limit: usize,
|
|
) -> GitResult<Vec<CommitMeta>> {
|
|
let mut revwalk = self
|
|
.repo()
|
|
.revwalk()
|
|
.map_err(|e| GitError::Internal(e.to_string()))?;
|
|
|
|
if let Some(r) = rev {
|
|
if r.contains("..") {
|
|
revwalk
|
|
.push_range(r)
|
|
.map_err(|e| GitError::Internal(e.to_string()))?;
|
|
} else {
|
|
revwalk
|
|
.push_ref(r)
|
|
.map_err(|e| GitError::Internal(e.to_string()))?;
|
|
}
|
|
} else {
|
|
revwalk
|
|
.push_head()
|
|
.map_err(|e| GitError::Internal(e.to_string()))?;
|
|
}
|
|
|
|
revwalk
|
|
.set_sorting(git2::Sort::TOPOLOGICAL | git2::Sort::TIME)
|
|
.map_err(|e| GitError::Internal(e.to_string()))?;
|
|
|
|
let mut commits = Vec::new();
|
|
let target = offset.saturating_add(limit);
|
|
for oid_result in revwalk {
|
|
let oid = oid_result.map_err(|e| GitError::Internal(e.to_string()))?;
|
|
if target > 0 && commits.len() >= target {
|
|
break;
|
|
}
|
|
if let Ok(commit) = self.repo.find_commit(oid) {
|
|
commits.push(CommitMeta::from_git2(&commit));
|
|
}
|
|
}
|
|
|
|
Ok(commits.into_iter().skip(offset).take(limit).collect())
|
|
}
|
|
|
|
pub fn commit_range(&self, from: &str, to: &str) -> GitResult<Vec<CommitMeta>> {
|
|
let range = format!("{}..{}", from, to);
|
|
self.commit_log(Some(&range), 0, 0)
|
|
}
|
|
|
|
pub fn commit_count(&self, from: Option<&str>, to: Option<&str>) -> GitResult<usize> {
|
|
let rev = match (from, to) {
|
|
(Some(f), Some(t)) => Some(format!("{}..{}", f, t)),
|
|
(Some(f), None) => Some(f.to_string()),
|
|
(None, Some(t)) => Some(t.to_string()),
|
|
(None, None) => None,
|
|
};
|
|
let commits = self.commit_log(rev.as_deref(), 0, 0)?;
|
|
Ok(commits.len())
|
|
}
|
|
|
|
pub fn commit_total(&self, rev: Option<&str>) -> GitResult<usize> {
|
|
self.commit_count(None, rev)
|
|
}
|
|
}
|