summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicent Marti <vicent@github.com>2014-08-29 18:19:56 +0200
committerVicent Marti <vicent@github.com>2014-08-29 18:19:56 +0200
commit46a13f32472741f0ed66db7cb75c8cff279886ad (patch)
tree9faad1600432d9f014fedf4775d3f99359937e9d
parentd99c8ca1783cfd04869e88f8707c036fc6053a05 (diff)
parent7db0e6ee48fd68009a7e78cbcbca125d6ce9008d (diff)
downloadlibgit2-46a13f32472741f0ed66db7cb75c8cff279886ad.tar.gz
Merge pull request #2481 from libgit2/cmn/oidarray
merge: expose multiple merge bases
-rw-r--r--CHANGELOG.md3
-rw-r--r--include/git2/merge.h16
-rw-r--r--include/git2/oidarray.h40
-rw-r--r--src/merge.c54
-rw-r--r--src/oidarray.c21
-rw-r--r--src/oidarray.h18
-rw-r--r--tests/revwalk/mergebase.c18
7 files changed, 169 insertions, 1 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 97c873dc2..4664c4d41 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -51,3 +51,6 @@ v0.21 + 1
* Add support for refspecs with the asterisk in the middle of a
pattern.
+
+* Introduce git_merge_bases() and the git_oidarray type to expose all
+ merge bases between two commits.
diff --git a/include/git2/merge.h b/include/git2/merge.h
index 9eb14ccb1..bd5ebc1bd 100644
--- a/include/git2/merge.h
+++ b/include/git2/merge.h
@@ -10,6 +10,7 @@
#include "common.h"
#include "types.h"
#include "oid.h"
+#include "oidarray.h"
#include "checkout.h"
#include "index.h"
@@ -321,6 +322,21 @@ GIT_EXTERN(int) git_merge_base(
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
*
* @param out the OID of a merge base considering all the commits
diff --git a/include/git2/oidarray.h b/include/git2/oidarray.h
new file mode 100644
index 000000000..0b3204597
--- /dev/null
+++ b/include/git2/oidarray.h
@@ -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
+
diff --git a/src/merge.c b/src/merge.c
index add7eab64..926a600cc 100644
--- a/src/merge.c
+++ b/src/merge.c
@@ -27,6 +27,7 @@
#include "index.h"
#include "filebuf.h"
#include "config.h"
+#include "oidarray.h"
#include "git2/types.h"
#include "git2/repository.h"
@@ -39,6 +40,7 @@
#include "git2/signature.h"
#include "git2/config.h"
#include "git2/tree.h"
+#include "git2/oidarray.h"
#include "git2/sys/index.h"
#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;
}
-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_vector list;
@@ -173,13 +175,63 @@ int git_merge_base(git_oid *out, git_repository *repo, const git_oid *one, const
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_commit_list_free(&result);
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;
on_error:
+ git_commit_list_free(&result);
git_revwalk_free(walk);
return -1;
}
diff --git a/src/oidarray.c b/src/oidarray.c
new file mode 100644
index 000000000..1d51a2958
--- /dev/null
+++ b/src/oidarray.c
@@ -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;
+}
diff --git a/src/oidarray.h b/src/oidarray.h
new file mode 100644
index 000000000..a7215ae6c
--- /dev/null
+++ b/src/oidarray.h
@@ -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
diff --git a/tests/revwalk/mergebase.c b/tests/revwalk/mergebase.c
index 8f1f6ef21..677e1a1b6 100644
--- a/tests/revwalk/mergebase.c
+++ b/tests/revwalk/mergebase.c
@@ -135,6 +135,24 @@ void test_revwalk_mergebase__prefer_youngest_merge_base(void)
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)
{
git_oid result, one, two;