Skip to content

Commit 8965f46

Browse files
committed
Add bindings for git_merge_analysis_for_ref
This is a slightly generalised version of git_merge_analysis that allows specifying the ref to analyse against instead of using the repository's current HEAD.
1 parent 0ea1c39 commit 8965f46

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

libgit2-sys/lib.rs

+9
Original file line numberDiff line numberDiff line change
@@ -3116,6 +3116,15 @@ extern "C" {
31163116
their_heads_len: usize,
31173117
) -> c_int;
31183118

3119+
pub fn git_merge_analysis_for_ref(
3120+
analysis_out: *mut git_merge_analysis_t,
3121+
pref_out: *mut git_merge_preference_t,
3122+
repo: *mut git_repository,
3123+
git_reference: *mut git_reference,
3124+
their_heads: *mut *const git_annotated_commit,
3125+
their_heads_len: usize,
3126+
) -> c_int;
3127+
31193128
// notes
31203129
pub fn git_note_author(note: *const git_note) -> *const git_signature;
31213130
pub fn git_note_committer(note: *const git_note) -> *const git_signature;

src/repo.rs

+67
Original file line numberDiff line numberDiff line change
@@ -1964,6 +1964,35 @@ impl Repository {
19641964
}
19651965
}
19661966

1967+
/// Analyzes the given branch(es) and determines the opportunities for
1968+
/// merging them into a reference.
1969+
pub fn merge_analysis_for_ref(
1970+
&self,
1971+
our_ref: &Reference<'_>,
1972+
their_heads: &[&AnnotatedCommit<'_>],
1973+
) -> Result<(MergeAnalysis, MergePreference), Error> {
1974+
unsafe {
1975+
let mut raw_merge_analysis = 0 as raw::git_merge_analysis_t;
1976+
let mut raw_merge_preference = 0 as raw::git_merge_preference_t;
1977+
let mut their_heads = their_heads
1978+
.iter()
1979+
.map(|v| v.raw() as *const _)
1980+
.collect::<Vec<_>>();
1981+
try_call!(raw::git_merge_analysis_for_ref(
1982+
&mut raw_merge_analysis,
1983+
&mut raw_merge_preference,
1984+
self.raw,
1985+
our_ref.raw(),
1986+
their_heads.as_mut_ptr() as *mut _,
1987+
their_heads.len()
1988+
));
1989+
Ok((
1990+
MergeAnalysis::from_bits_truncate(raw_merge_analysis as u32),
1991+
MergePreference::from_bits_truncate(raw_merge_preference as u32),
1992+
))
1993+
}
1994+
}
1995+
19671996
/// Initializes a rebase operation to rebase the changes in `branch`
19681997
/// relative to `upstream` onto another branch. To begin the rebase process,
19691998
/// call `next()`.
@@ -3621,4 +3650,42 @@ mod tests {
36213650
// reverting twice restores `foo` file
36223651
assert!(foo_file.exists());
36233652
}
3653+
3654+
#[test]
3655+
#[allow(warnings)]
3656+
fn smoke_merge_analysis_for_ref() -> Result<(), crate::Error> {
3657+
let (_td, repo) = graph_repo_init();
3658+
3659+
// Set up this repo state:
3660+
// * second (their-branch)
3661+
// * initial (HEAD -> main)
3662+
//
3663+
// We expect that their-branch can be fast-forward merged into main.
3664+
3665+
// git checkout --detach HEAD
3666+
let head_commit = repo.head()?.peel_to_commit()?;
3667+
repo.set_head_detached(head_commit.id())?;
3668+
3669+
// git branch their-branch HEAD
3670+
let their_branch = repo.branch("their-branch", &head_commit, false)?;
3671+
3672+
// git branch -f main HEAD~
3673+
let mut parents_iter = head_commit.parents();
3674+
let parent = parents_iter.next().unwrap();
3675+
assert!(parents_iter.next().is_none());
3676+
3677+
let main = repo.branch("main", &parent, true)?;
3678+
3679+
// git checkout main
3680+
repo.set_head(main.name()?.unwrap());
3681+
3682+
let (merge_analysis, merge_preference) = repo.merge_analysis_for_ref(
3683+
main.get(),
3684+
&[&repo.reference_to_annotated_commit(their_branch.get())?],
3685+
)?;
3686+
3687+
assert!(merge_analysis.contains(crate::MergeAnalysis::ANALYSIS_FASTFORWARD));
3688+
3689+
Ok(())
3690+
}
36243691
}

0 commit comments

Comments
 (0)