use crate::bare::GitBare; use crate::error::GitResult; use crate::pb::*; impl GitBare { /// Find the best merge base for a set of revisions (OIDs). pub fn find_merge_base(&self, request: FindMergeBaseRequest) -> GitResult { if request.revisions.is_empty() { return Ok(FindMergeBaseResponse::default()); } let revisions: Vec = request .revisions .iter() .map(|b| String::from_utf8_lossy(b).to_string()) .collect(); if revisions.len() < 2 { return Ok(FindMergeBaseResponse { base_oid: revisions.first().cloned().unwrap_or_default(), }); } let mut args = vec![ "--git-dir".to_string(), self.bare_dir.to_string_lossy().into_owned(), "merge-base".to_string(), ]; args.extend(revisions.iter().cloned()); let output = std::process::Command::new("git") .args(&args) .stdout(std::process::Stdio::piped()) .stderr(std::process::Stdio::piped()) .output() .map_err(|e| crate::error::GitError::CommandFailed { status_code: None, stderr: e.to_string(), })?; if !output.status.success() { return Ok(FindMergeBaseResponse { base_oid: String::new(), }); } let base_oid = String::from_utf8_lossy(&output.stdout).trim().to_string(); Ok(FindMergeBaseResponse { base_oid }) } /// Check if one commit is an ancestor of another. pub fn commit_is_ancestor(&self, request: CommitIsAncestorRequest) -> GitResult { crate::sanitize::validate_revision(&request.ancestor_oid)?; crate::sanitize::validate_revision(&request.descendant_oid)?; let result = std::process::Command::new("git") .args([ "--git-dir", &self.bare_dir.to_string_lossy(), "merge-base", "--is-ancestor", &request.ancestor_oid, &request.descendant_oid, ]) .stdout(std::process::Stdio::null()) .stderr(std::process::Stdio::null()) .status() .map(|s| s.success()) .unwrap_or(false); Ok(CommitIsAncestorResponse { is_ancestor: result }) } }