//! Copyright (c) 2022-2026 GitDataAi All rights reserved. use crate::bare::GitBare; use crate::error::{GitError, GitResult}; use crate::pb::{Commit, GetCommitRequest}; use crate::resolve_revision; impl GitBare { pub fn get_commit(&self, request: GetCommitRequest) -> GitResult { let repo = self.gix_repo()?; let revision = resolve_revision!(request.revision); let id = repo.rev_parse_single(revision.as_str())?; let commit = id .object()? .try_into_commit() .map_err(|e| GitError::Gix(e.to_string()))?; Ok(commit_to_pb(self, &commit, request.include_raw)) } } pub(crate) fn commit_to_pb(gb: &GitBare, commit: &gix::Commit<'_>, include_raw: bool) -> Commit { let hex = commit.id.to_string(); let tree_hex = commit.tree_id().map(|t| t.to_string()).unwrap_or_default(); let message = commit .message_raw() .map(|m| m.to_string()) .unwrap_or_default(); let (subject, body) = message .split_once('\n') .map(|(s, b)| (s.to_string(), b.trim_start_matches('\n').to_string())) .unwrap_or_else(|| (message.clone(), String::new())); let author_sig = commit.author().ok(); let committer_sig = commit.committer().ok(); Commit { oid: Some(gb.oid_to_pb(hex.clone())), abbreviated_oid: commit .short_id() .map(|s| s.to_string()) .unwrap_or_else(|_| hex.chars().take(7).collect()), parent_oids: commit .parent_ids() .map(|p| gb.oid_to_pb(p.to_string())) .collect(), tree_oid: Some(gb.oid_to_pb(tree_hex)), author: author_sig.as_ref().map(gix_sig_to_pb), committer: committer_sig.as_ref().map(gix_sig_to_pb), subject, body, message, trailers: Vec::new(), signature: None, stats: None, authored_at: author_sig.as_ref().map(|s| prost_types::Timestamp { seconds: s.seconds(), nanos: 0, }), committed_at: committer_sig.as_ref().map(|s| prost_types::Timestamp { seconds: s.seconds(), nanos: 0, }), raw: if include_raw { commit.data.clone() } else { Vec::new() }, } } pub(crate) fn gix_sig_to_pb(sig: &gix::actor::SignatureRef<'_>) -> crate::pb::Signature { let time = sig.time().ok(); crate::pb::Signature { identity: Some(crate::pb::Identity { name: sig.name.to_string(), email: sig.email.to_string(), }), when: Some(prost_types::Timestamp { seconds: sig.seconds(), nanos: 0, }), timezone_offset: time.map(|t| t.offset / 60).unwrap_or(0), } }