summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornulltoken <emeric.fermas@gmail.com>2012-07-11 16:14:12 +0200
committernulltoken <emeric.fermas@gmail.com>2012-07-12 01:06:11 +0200
commitb1aca6eae084ebe59c5a092314e94019c59ecec6 (patch)
tree3e8f251d9a98e23c30003a39e23741807b9bae04
parent2b92a154b66f213b664e44544048a2df7708b9de (diff)
downloadlibgit2-b1aca6eae084ebe59c5a092314e94019c59ecec6.tar.gz
commit: introduce git_commit_nth_gen_ancestor()
-rw-r--r--include/git2/commit.h19
-rw-r--r--src/commit.c34
-rw-r--r--tests-clar/commit/parent.c57
3 files changed, 110 insertions, 0 deletions
diff --git a/include/git2/commit.h b/include/git2/commit.h
index 640adf5c2..5b6da520d 100644
--- a/include/git2/commit.h
+++ b/include/git2/commit.h
@@ -179,6 +179,25 @@ GIT_EXTERN(int) git_commit_parent(git_commit **parent, git_commit *commit, unsig
GIT_EXTERN(const git_oid *) git_commit_parent_oid(git_commit *commit, unsigned int n);
/**
+ * Get the commit object that is the <n>th generation ancestor
+ * of the named commit object, following only the first parents.
+ * The returned commit has to be freed by the caller.
+ *
+ * Passing `0` as the generation number returns another instance of the
+ * base commit itself.
+ *
+ * @param ancestor Pointer where to store the ancestor commit
+ * @param commit a previously loaded commit.
+ * @param n the requested generation
+ * @return 0 on success; GIT_ENOTFOUND if no matching ancestor exists
+ * or an error code
+ */
+int git_commit_nth_gen_ancestor(
+ git_commit **ancestor,
+ const git_commit *commit,
+ unsigned int n);
+
+/**
* Create a new commit in the repository using `git_object`
* instances as parameters.
*
diff --git a/src/commit.c b/src/commit.c
index 5acbbc39b..32c47944b 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -255,3 +255,37 @@ int git_commit_parent(git_commit **parent, git_commit *commit, unsigned int n)
return git_commit_lookup(parent, commit->object.repo, parent_oid);
}
+
+int git_commit_nth_gen_ancestor(
+ git_commit **ancestor,
+ const git_commit *commit,
+ unsigned int n)
+{
+ git_commit *current, *parent;
+ int error;
+
+ assert(ancestor && commit);
+
+ current = (git_commit *)commit;
+
+ if (n == 0)
+ return git_commit_lookup(
+ ancestor,
+ commit->object.repo,
+ git_object_id((const git_object *)commit));
+
+ while (n--) {
+ error = git_commit_parent(&parent, (git_commit *)current, 0);
+
+ if (current != commit)
+ git_commit_free(current);
+
+ if (error < 0)
+ return error;
+
+ current = parent;
+ }
+
+ *ancestor = parent;
+ return 0;
+}
diff --git a/tests-clar/commit/parent.c b/tests-clar/commit/parent.c
new file mode 100644
index 000000000..a00757732
--- /dev/null
+++ b/tests-clar/commit/parent.c
@@ -0,0 +1,57 @@
+#include "clar_libgit2.h"
+
+static git_repository *_repo;
+static git_commit *commit;
+
+void test_commit_parent__initialize(void)
+{
+ git_oid oid;
+
+ cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git")));
+
+ git_oid_fromstr(&oid, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
+ cl_git_pass(git_commit_lookup(&commit, _repo, &oid));
+}
+
+void test_commit_parent__cleanup(void)
+{
+ git_commit_free(commit);
+ git_repository_free(_repo);
+}
+
+static void assert_nth_gen_parent(unsigned int gen, const char *expected_oid)
+{
+ git_commit *parent = NULL;
+ int error;
+
+ error = git_commit_nth_gen_ancestor(&parent, commit, gen);
+
+ if (expected_oid != NULL) {
+ cl_assert_equal_i(0, error);
+ cl_assert_equal_i(0, git_oid_streq(git_commit_id(parent), expected_oid));
+ } else
+ cl_assert_equal_i(GIT_ENOTFOUND, error);
+
+ git_commit_free(parent);
+}
+
+/*
+ * $ git show be35~0
+ * commit be3563ae3f795b2b4353bcce3a527ad0a4f7f644
+ *
+ * $ git show be35~1
+ * commit 9fd738e8f7967c078dceed8190330fc8648ee56a
+ *
+ * $ git show be35~3
+ * commit 5b5b025afb0b4c913b4c338a42934a3863bf3644
+ *
+ * $ git show be35~42
+ * fatal: ambiguous argument 'be35~42': unknown revision or path not in the working tree.
+ */
+void test_commit_parent__can_retrieve_nth_generation_parent(void)
+{
+ assert_nth_gen_parent(0, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
+ assert_nth_gen_parent(1, "9fd738e8f7967c078dceed8190330fc8648ee56a");
+ assert_nth_gen_parent(3, "5b5b025afb0b4c913b4c338a42934a3863bf3644");
+ assert_nth_gen_parent(42, NULL);
+}