diff options
author | Aimeast <lixd3389@gmail.com> | 2014-03-18 22:31:14 +0800 |
---|---|---|
committer | Aimeast <lixd3389@gmail.com> | 2014-03-18 22:31:14 +0800 |
commit | 0aee025befc82efe3b8a92692ebe852ac56171dd (patch) | |
tree | 7c4cbdc6565496ba7619fce3ed6dc607c185d33f | |
parent | a7af1f7dd6929d2c903aa932ae5ea10d368e75d0 (diff) | |
download | libgit2-0aee025befc82efe3b8a92692ebe852ac56171dd.tar.gz |
Implement git_merge_base_octopus
-rw-r--r-- | include/git2/merge.h | 17 | ||||
-rw-r--r-- | src/merge.c | 25 | ||||
-rw-r--r-- | tests/revwalk/mergebase.c | 65 |
3 files changed, 105 insertions, 2 deletions
diff --git a/include/git2/merge.h b/include/git2/merge.h index 3563f35d5..cfec32f4d 100644 --- a/include/git2/merge.h +++ b/include/git2/merge.h @@ -191,7 +191,7 @@ GIT_EXTERN(int) git_merge_base( * @param repo the repository where the commits exist * @param length The number of commits in the provided `input_array` * @param input_array oids of the commits - * @return 0 on success, GIT_ENOTFOUND if not found or error code + * @return Zero on success; GIT_ENOTFOUND or -1 on failure. */ GIT_EXTERN(int) git_merge_base_many( git_oid *out, @@ -200,6 +200,21 @@ GIT_EXTERN(int) git_merge_base_many( const git_oid input_array[]); /** + * Find a merge base in preparation for an octopus merge + * + * @param out the OID of a merge base considering all the commits + * @param repo the repository where the commits exist + * @param length The number of commits in the provided `input_array` + * @param input_array oids of the commits + * @return Zero on success; GIT_ENOTFOUND or -1 on failure. + */ +GIT_EXTERN(int) git_merge_base_octopus( + git_oid *out, + git_repository *repo, + size_t length, + const git_oid input_array[]); + +/** * Creates a `git_merge_head` from the given reference. The resulting * git_merge_head must be freed with `git_merge_head_free`. * diff --git a/src/merge.c b/src/merge.c index 124e8c3a7..0b11c0da3 100644 --- a/src/merge.c +++ b/src/merge.c @@ -114,6 +114,31 @@ cleanup: return error; } +int git_merge_base_octopus(git_oid *out, git_repository *repo, size_t length, const git_oid input_array[]) +{ + git_oid result; + unsigned int i; + int error = -1; + + assert(out && repo && input_array); + + if (length < 2) { + giterr_set(GITERR_INVALID, "At least two commits are required to find an ancestor. Provided 'length' was %u.", length); + return -1; + } + + result = input_array[0]; + for (i = 1; i < length; i++) { + error = git_merge_base(&result, repo, &result, &input_array[i]); + if (error < 0) + return error; + } + + *out = result; + + return 0; +} + int git_merge_base(git_oid *out, git_repository *repo, const git_oid *one, const git_oid *two) { git_revwalk *walk; diff --git a/tests/revwalk/mergebase.c b/tests/revwalk/mergebase.c index 2d01647fd..97663502c 100644 --- a/tests/revwalk/mergebase.c +++ b/tests/revwalk/mergebase.c @@ -189,7 +189,6 @@ void test_revwalk_mergebase__many_no_common_ancestor_returns_ENOTFOUND(void) assert_mergebase_many(NULL, 3, "e90810", "41bc8c", "a65fed"); assert_mergebase_many(NULL, 3, "e90810", "a65fed", "41bc8c"); assert_mergebase_many(NULL, 3, "a65fed", "e90810", "41bc8c"); - assert_mergebase_many(NULL, 3, "a65fed", "e90810", "41bc8c"); assert_mergebase_many(NULL, 3, "a65fed", "41bc8c", "e90810"); assert_mergebase_many(NULL, 3, "e90810", "763d71", "a65fed"); @@ -209,6 +208,70 @@ void test_revwalk_mergebase__many_merge_branch(void) assert_mergebase_many("5b5b025afb0b4c913b4c338a42934a3863bf3644", 5, "5b5b02", "763d71", "a4a7dc", "a65fed", "41bc8c"); } +static void assert_mergebase_octopus(const char *expected_sha, int count, ...) +{ + va_list ap; + int i; + git_oid *oids; + git_oid oid, expected; + char *partial_oid; + git_object *object; + + oids = git__malloc(count * sizeof(git_oid)); + cl_assert(oids != NULL); + + memset(oids, 0x0, count * sizeof(git_oid)); + + va_start(ap, count); + + for (i = 0; i < count; ++i) { + partial_oid = va_arg(ap, char *); + cl_git_pass(git_oid_fromstrn(&oid, partial_oid, strlen(partial_oid))); + + cl_git_pass(git_object_lookup_prefix(&object, _repo, &oid, strlen(partial_oid), GIT_OBJ_COMMIT)); + git_oid_cpy(&oids[i], git_object_id(object)); + git_object_free(object); + } + + va_end(ap); + + if (expected_sha == NULL) + cl_assert_equal_i(GIT_ENOTFOUND, git_merge_base_octopus(&oid, _repo, count, oids)); + else { + cl_git_pass(git_merge_base_octopus(&oid, _repo, count, oids)); + cl_git_pass(git_oid_fromstr(&expected, expected_sha)); + + cl_assert(git_oid_cmp(&expected, &oid) == 0); + } + + git__free(oids); +} + +void test_revwalk_mergebase__octopus_no_common_ancestor_returns_ENOTFOUND(void) +{ + assert_mergebase_octopus(NULL, 3, "41bc8c", "e90810", "a65fed"); + assert_mergebase_octopus(NULL, 3, "e90810", "41bc8c", "a65fed"); + assert_mergebase_octopus(NULL, 3, "e90810", "a65fed", "41bc8c"); + assert_mergebase_octopus(NULL, 3, "a65fed", "e90810", "41bc8c"); + assert_mergebase_octopus(NULL, 3, "a65fed", "41bc8c", "e90810"); + + assert_mergebase_octopus(NULL, 3, "e90810", "763d71", "a65fed"); + + assert_mergebase_octopus(NULL, 3, "763d71", "e90810", "a65fed"); + assert_mergebase_octopus(NULL, 3, "763d71", "a65fed", "e90810"); + + assert_mergebase_octopus(NULL, 5, "5b5b02", "763d71", "a4a7dc", "a65fed", "41bc8c"); +} + +void test_revwalk_mergebase__octopus_merge_branch(void) +{ + assert_mergebase_octopus("8496071c1b46c854b31185ea97743be6a8774479", 3, "a65fed", "763d71", "849607"); + + assert_mergebase_octopus("8496071c1b46c854b31185ea97743be6a8774479", 3, "a65fed", "763d71", "849607"); + assert_mergebase_octopus("8496071c1b46c854b31185ea97743be6a8774479", 3, "a65fed", "849607", "763d71"); + assert_mergebase_octopus("8496071c1b46c854b31185ea97743be6a8774479", 3, "849607", "a65fed", "763d71"); +} + /* * testrepo.git $ git log --graph --all * * commit 763d71aadf09a7951596c9746c024e7eece7c7af |