mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-21 22:21:37 +00:00
merge: expose multiple merge bases
We always calculate multiple merge bases, but up to now we had only exposed the "best" merge base. Introduce git_oidarray which analogously to git_strarray lets us return multiple ids.
This commit is contained in:
parent
091165c53b
commit
7db0e6ee48
@ -39,3 +39,6 @@ v0.21 + 1
|
|||||||
|
|
||||||
* Add support for refspecs with the asterisk in the middle of a
|
* Add support for refspecs with the asterisk in the middle of a
|
||||||
pattern.
|
pattern.
|
||||||
|
|
||||||
|
* Introduce git_merge_bases() and the git_oidarray type to expose all
|
||||||
|
merge bases between two commits.
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "oid.h"
|
#include "oid.h"
|
||||||
|
#include "oidarray.h"
|
||||||
#include "checkout.h"
|
#include "checkout.h"
|
||||||
#include "index.h"
|
#include "index.h"
|
||||||
|
|
||||||
@ -320,6 +321,21 @@ GIT_EXTERN(int) git_merge_base(
|
|||||||
const git_oid *one,
|
const git_oid *one,
|
||||||
const git_oid *two);
|
const git_oid *two);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find merge bases between two commits
|
||||||
|
*
|
||||||
|
* @param out array in which to store the resulting ids
|
||||||
|
* @param repo the repository where the commits exist
|
||||||
|
* @param one one of the commits
|
||||||
|
* @param two the other commit
|
||||||
|
* @return 0 on success, GIT_ENOTFOUND if not found or error code
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_merge_bases(
|
||||||
|
git_oidarray *out,
|
||||||
|
git_repository *repo,
|
||||||
|
const git_oid *one,
|
||||||
|
const git_oid *two);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a merge base given a list of commits
|
* Find a merge base given a list of commits
|
||||||
*
|
*
|
||||||
|
40
include/git2/oidarray.h
Normal file
40
include/git2/oidarray.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) the libgit2 contributors. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||||
|
* a Linking Exception. For full terms see the included COPYING file.
|
||||||
|
*/
|
||||||
|
#ifndef INCLUDE_git_oidarray_h__
|
||||||
|
#define INCLUDE_git_oidarray_h__
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "oid.h"
|
||||||
|
|
||||||
|
GIT_BEGIN_DECL
|
||||||
|
|
||||||
|
/** Array of object ids */
|
||||||
|
typedef struct git_oidarray {
|
||||||
|
git_oid *ids;
|
||||||
|
size_t count;
|
||||||
|
} git_oidarray;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free the OID array
|
||||||
|
*
|
||||||
|
* This method must (and must only) be called on `git_oidarray`
|
||||||
|
* objects where the array is allocated by the library. Not doing so,
|
||||||
|
* will result in a memory leak.
|
||||||
|
*
|
||||||
|
* This does not free the `git_oidarray` itself, since the library will
|
||||||
|
* never allocate that object directly itself (it is more commonly embedded
|
||||||
|
* inside another struct or created on the stack).
|
||||||
|
*
|
||||||
|
* @param array git_oidarray from which to free oid data
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(void) git_oidarray_free(git_oidarray *array);
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
GIT_END_DECL
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
54
src/merge.c
54
src/merge.c
@ -27,6 +27,7 @@
|
|||||||
#include "index.h"
|
#include "index.h"
|
||||||
#include "filebuf.h"
|
#include "filebuf.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "oidarray.h"
|
||||||
|
|
||||||
#include "git2/types.h"
|
#include "git2/types.h"
|
||||||
#include "git2/repository.h"
|
#include "git2/repository.h"
|
||||||
@ -39,6 +40,7 @@
|
|||||||
#include "git2/signature.h"
|
#include "git2/signature.h"
|
||||||
#include "git2/config.h"
|
#include "git2/config.h"
|
||||||
#include "git2/tree.h"
|
#include "git2/tree.h"
|
||||||
|
#include "git2/oidarray.h"
|
||||||
#include "git2/sys/index.h"
|
#include "git2/sys/index.h"
|
||||||
|
|
||||||
#define GIT_MERGE_INDEX_ENTRY_EXISTS(X) ((X).mode != 0)
|
#define GIT_MERGE_INDEX_ENTRY_EXISTS(X) ((X).mode != 0)
|
||||||
@ -139,7 +141,7 @@ int git_merge_base_octopus(git_oid *out, git_repository *repo, size_t length, co
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_merge_base(git_oid *out, git_repository *repo, const git_oid *one, const git_oid *two)
|
static int merge_bases(git_commit_list **out, git_revwalk **walk_out, git_repository *repo, const git_oid *one, const git_oid *two)
|
||||||
{
|
{
|
||||||
git_revwalk *walk;
|
git_revwalk *walk;
|
||||||
git_vector list;
|
git_vector list;
|
||||||
@ -173,13 +175,63 @@ int git_merge_base(git_oid *out, git_repository *repo, const git_oid *one, const
|
|||||||
return GIT_ENOTFOUND;
|
return GIT_ENOTFOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*out = result;
|
||||||
|
*walk_out = walk;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
on_error:
|
||||||
|
git_revwalk_free(walk);
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_merge_base(git_oid *out, git_repository *repo, const git_oid *one, const git_oid *two)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
git_revwalk *walk;
|
||||||
|
git_commit_list *result;
|
||||||
|
|
||||||
|
if ((error = merge_bases(&result, &walk, repo, one, two)) < 0)
|
||||||
|
return error;
|
||||||
|
|
||||||
git_oid_cpy(out, &result->item->oid);
|
git_oid_cpy(out, &result->item->oid);
|
||||||
git_commit_list_free(&result);
|
git_commit_list_free(&result);
|
||||||
git_revwalk_free(walk);
|
git_revwalk_free(walk);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_merge_bases(git_oidarray *out, git_repository *repo, const git_oid *one, const git_oid *two)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
git_revwalk *walk;
|
||||||
|
git_commit_list *result, *list;
|
||||||
|
git_array_oid_t array;
|
||||||
|
|
||||||
|
git_array_init(array);
|
||||||
|
|
||||||
|
if ((error = merge_bases(&result, &walk, repo, one, two)) < 0)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
list = result;
|
||||||
|
while (list) {
|
||||||
|
git_oid *id = git_array_alloc(array);
|
||||||
|
if (id == NULL)
|
||||||
|
goto on_error;
|
||||||
|
|
||||||
|
git_oid_cpy(id, &list->item->oid);
|
||||||
|
list = list->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
git_oidarray__from_array(out, &array);
|
||||||
|
git_commit_list_free(&result);
|
||||||
|
git_revwalk_free(walk);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
on_error:
|
on_error:
|
||||||
|
git_commit_list_free(&result);
|
||||||
git_revwalk_free(walk);
|
git_revwalk_free(walk);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
21
src/oidarray.c
Normal file
21
src/oidarray.c
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) the libgit2 contributors. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||||
|
* a Linking Exception. For full terms see the included COPYING file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "git2/oidarray.h"
|
||||||
|
#include "oidarray.h"
|
||||||
|
#include "array.h"
|
||||||
|
|
||||||
|
void git_oidarray_free(git_oidarray *arr)
|
||||||
|
{
|
||||||
|
git__free(arr->ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
void git_oidarray__from_array(git_oidarray *arr, git_array_oid_t *array)
|
||||||
|
{
|
||||||
|
arr->count = array->size;
|
||||||
|
arr->ids = array->ptr;
|
||||||
|
}
|
18
src/oidarray.h
Normal file
18
src/oidarray.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) the libgit2 contributors. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||||
|
* a Linking Exception. For full terms see the included COPYING file.
|
||||||
|
*/
|
||||||
|
#ifndef INCLUDE_oidarray_h__
|
||||||
|
#define INCLUDE_oidarray_h__
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "git2/oidarray.h"
|
||||||
|
#include "array.h"
|
||||||
|
|
||||||
|
typedef git_array_t(git_oid) git_array_oid_t;
|
||||||
|
|
||||||
|
extern void git_oidarray__from_array(git_oidarray *arr, git_array_oid_t *array);
|
||||||
|
|
||||||
|
#endif
|
@ -135,6 +135,24 @@ void test_revwalk_mergebase__prefer_youngest_merge_base(void)
|
|||||||
cl_assert_equal_oid(&expected, &result);
|
cl_assert_equal_oid(&expected, &result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_revwalk_mergebase__multiple_merge_bases(void)
|
||||||
|
{
|
||||||
|
git_oid one, two, expected1, expected2;
|
||||||
|
git_oidarray result = {NULL, 0};
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&one, "a4a7dce85cf63874e984719f4fdd239f5145052f "));
|
||||||
|
cl_git_pass(git_oid_fromstr(&two, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"));
|
||||||
|
cl_git_pass(git_oid_fromstr(&expected1, "c47800c7266a2be04c571c04d5a6614691ea99bd"));
|
||||||
|
cl_git_pass(git_oid_fromstr(&expected2, "9fd738e8f7967c078dceed8190330fc8648ee56a"));
|
||||||
|
|
||||||
|
cl_git_pass(git_merge_bases(&result, _repo, &one, &two));
|
||||||
|
cl_assert_equal_i(2, result.count);
|
||||||
|
cl_assert_equal_oid(&expected1, &result.ids[0]);
|
||||||
|
cl_assert_equal_oid(&expected2, &result.ids[1]);
|
||||||
|
|
||||||
|
git_oidarray_free(&result);
|
||||||
|
}
|
||||||
|
|
||||||
void test_revwalk_mergebase__no_off_by_one_missing(void)
|
void test_revwalk_mergebase__no_off_by_one_missing(void)
|
||||||
{
|
{
|
||||||
git_oid result, one, two;
|
git_oid result, one, two;
|
||||||
|
Loading…
Reference in New Issue
Block a user