Skip to content

Commit

Permalink
Added merge_base_octopus
Browse files Browse the repository at this point in the history
  • Loading branch information
Caleb-T-Owens committed Oct 2, 2024
1 parent 2e0fcda commit 5dd077a
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 0 deletions.
7 changes: 7 additions & 0 deletions libgit2-sys/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3506,6 +3506,13 @@ extern "C" {
input_array: *const git_oid,
) -> c_int;

pub fn git_merge_base_octopus(
out: *mut git_oid,
repo: *mut git_repository,
length: size_t,
input_array: *const git_oid,
) -> c_int;

pub fn git_merge_bases(
out: *mut git_oidarray,
repo: *mut git_repository,
Expand Down
53 changes: 53 additions & 0 deletions src/repo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2467,6 +2467,38 @@ impl Repository {
}

/// Find a merge base given a list of commits
///
/// This behaves similar to [`git merge-base`](https://git-scm.com/docs/git-merge-base#_discussion).
/// Given three commits `a`, `b`, and `c`, `merge_base_many(&[a, b, c])`
/// will compute a hypothetical commit `m`, which is a merge between `b`
/// and `c`.
///
/// For example, with the following topology:
/// ```text
/// o---o---o---o---C
/// /
/// / o---o---o---B
/// / /
/// ---2---1---o---o---o---A
/// ```
///
/// the result of `merge_base_many(&[a, b, c])` is 1. This is because the
/// equivalent topology with a merge commit `m` between `b` and `c` would
/// is:
/// ```text
/// o---o---o---o---o
/// / \
/// / o---o---o---o---M
/// / /
/// ---2---1---o---o---o---A
/// ```
///
/// and the result of `merge_base_many(&[a, m])` is 1.
///
/// ---
///
/// If you're looking to recieve the common merge base between all the
/// given commits, use [`Self::merge_base_octopus`].
pub fn merge_base_many(&self, oids: &[Oid]) -> Result<Oid, Error> {
let mut raw = raw::git_oid {
id: [0; raw::GIT_OID_RAWSZ],
Expand All @@ -2483,6 +2515,23 @@ impl Repository {
}
}

/// Find a common merge base between all given a list of commits
pub fn merge_base_octopus(&self, oids: &[Oid]) -> Result<Oid, Error> {
let mut raw = raw::git_oid {
id: [0; raw::GIT_OID_RAWSZ],
};

unsafe {
try_call!(raw::git_merge_base_octopus(
&mut raw,
self.raw,
oids.len() as size_t,
oids.as_ptr() as *const raw::git_oid
));
Ok(Binding::from_raw(&raw as *const _))
}
}

/// Find all merge bases between two commits
pub fn merge_bases(&self, one: Oid, two: Oid) -> Result<OidArray, Error> {
let mut arr = raw::git_oidarray {
Expand Down Expand Up @@ -3825,6 +3874,10 @@ mod tests {
// the merge base of (oid2,oid3,oid4) should be oid1
let merge_base = repo.merge_base_many(&[oid2, oid3, oid4]).unwrap();
assert_eq!(merge_base, oid1);

// the octopus merge base of (oid2,oid3,oid4) should be oid1
let merge_base = repo.merge_base_octopus(&[oid2, oid3, oid4]).unwrap();
assert_eq!(merge_base, oid1);
}

/// create an octopus:
Expand Down

0 comments on commit 5dd077a

Please sign in to comment.