77 lines
2.2 KiB
Rust
77 lines
2.2 KiB
Rust
use serde::{Deserialize, Serialize};
|
|
|
|
use crate::{
|
|
bare::GitBare,
|
|
cmd::{merge::MergeOptions, oid::ObjectId},
|
|
errors::{GitError, GitResult},
|
|
};
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
pub struct MergeTreeResult {
|
|
pub tree_id: ObjectId,
|
|
pub has_conflicts: bool,
|
|
}
|
|
|
|
impl GitBare {
|
|
pub fn merge_tree(
|
|
&self,
|
|
ours: ObjectId,
|
|
theirs: ObjectId,
|
|
options: Option<MergeOptions>,
|
|
) -> GitResult<MergeTreeResult> {
|
|
let mut args =
|
|
vec!["merge-tree".to_string(), "--write-tree".to_string()];
|
|
|
|
if let Some(opts) = &options {
|
|
if opts.find_renames {
|
|
args.push("--find-renames".to_string());
|
|
if opts.rename_threshold > 0 {
|
|
args.push(format!(
|
|
"--rename-threshold={}",
|
|
opts.rename_threshold
|
|
));
|
|
}
|
|
}
|
|
if opts.fail_on_conflict {
|
|
args.push("--fail-on-conflict".to_string());
|
|
}
|
|
if opts.no_recursive {
|
|
args.push("--no-recursive".to_string());
|
|
}
|
|
if opts.target_limit > 0 {
|
|
args.push(format!("--target-limit={}", opts.target_limit));
|
|
}
|
|
}
|
|
|
|
args.push(ours.as_str().to_string());
|
|
args.push(theirs.as_str().to_string());
|
|
|
|
let output = self.git_command_with(
|
|
crate::cmd::command::GitCommandParams::new(args).unchecked(),
|
|
)?;
|
|
|
|
let stdout = output.stdout_lossy();
|
|
let mut lines = stdout.lines();
|
|
let tree_oid_str = lines.next().unwrap_or("").trim();
|
|
|
|
if tree_oid_str.is_empty() {
|
|
if !output.success {
|
|
return Err(GitError::CommandFailed {
|
|
status_code: output.status_code,
|
|
stderr: output.stderr_lossy(),
|
|
});
|
|
}
|
|
return Err(GitError::ParseError(
|
|
"merge-tree produced no tree OID output".to_string(),
|
|
));
|
|
}
|
|
let has_conflicts =
|
|
!output.success || lines.any(|l| !l.trim().is_empty());
|
|
|
|
Ok(MergeTreeResult {
|
|
tree_id: ObjectId::new(tree_oid_str),
|
|
has_conflicts,
|
|
})
|
|
}
|
|
}
|