gitdataai/lib/git/cmd/commit/commit_info.rs
2026-05-30 01:38:40 +08:00

73 lines
2.3 KiB
Rust

use crate::{
bare::GitBare,
cmd::{
commit::{CommitMeta, CommitSignature},
oid::ObjectId,
},
errors::GitResult,
};
impl GitBare {
pub fn commit_info(&self, oid: ObjectId) -> GitResult<CommitMeta> {
let repo = self.gix_repo()?;
let gix_id: gix::hash::ObjectId = (&oid).try_into()?;
let commit = repo.find_commit(gix_id)?;
let decoded = commit.decode()?;
let message_raw = commit.message_raw()?;
let message = message_raw.to_string();
let message = message.trim_end_matches('\n').to_string();
let summary = message.lines().next().unwrap_or("").to_string();
let author_sig = decoded.author()?;
let author_time = author_sig.time()?;
let committer_sig = decoded.committer()?;
let committer_time = committer_sig.time()?;
let tree_id = ObjectId::new(decoded.tree().to_hex().to_string());
let parent_ids: Vec<ObjectId> = decoded
.parents()
.map(|id| ObjectId::new(id.to_hex().to_string()))
.collect();
let encoding = decoded
.extra_headers()
.find("encoding")
.map(|v| v.to_string());
Ok(CommitMeta {
oid,
message,
summary,
author: CommitSignature {
name: author_sig.name.to_string(),
email: author_sig.email.to_string(),
time_secs: author_time.seconds as i64,
offset_minutes: (author_time.offset / 60) as i32,
},
committer: CommitSignature {
name: committer_sig.name.to_string(),
email: committer_sig.email.to_string(),
time_secs: committer_time.seconds as i64,
offset_minutes: (committer_time.offset / 60) as i32,
},
tree_id,
parent_ids,
encoding,
})
}
pub fn commit_exists(&self, oid: ObjectId) -> GitResult<bool> {
let repo = self.gix_repo()?;
let gix_id: gix::hash::ObjectId = (&oid).try_into()?;
if !repo.has_object(gix_id) {
return Ok(false);
}
let header = repo.find_header(gix_id)?;
Ok(header.kind() == gix::object::Kind::Commit)
}
}