From bff53e5405e686f78e1ae81a4521566e3c67b5df Mon Sep 17 00:00:00 2001 From: "Scott J. Goldman" Date: Tue, 27 Nov 2012 16:36:50 -0800 Subject: [PATCH 1/9] Add initial implementation of ahead-behind count --- include/git2/merge.h | 11 ++++++ src/merge.c | 81 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/include/git2/merge.h b/include/git2/merge.h index 59493969c..928c4758c 100644 --- a/include/git2/merge.h +++ b/include/git2/merge.h @@ -50,6 +50,17 @@ GIT_EXTERN(int) git_merge_base_many( const git_oid input_array[], size_t length); +/** + * Count the number of unique commits between two commit objects + * + * @param ahead number of commits, starting at `one`, unique from commits in `two` + * @param behind number of commits, starting at `two`, unique from commits in `one` + * @param repo the repository where the commits exist + * @param one one of the commits + * @param two the other commit + */ +GIT_EXTERN(int) git_count_ahead_behind(int *ahead, int *behind, git_repository *repo, git_oid *one, git_oid *two); + /** @} */ GIT_END_DECL #endif diff --git a/src/merge.c b/src/merge.c index c795b808b..e0fc0abf1 100644 --- a/src/merge.c +++ b/src/merge.c @@ -242,3 +242,84 @@ int git_merge__bases_many(git_commit_list **out, git_revwalk *walk, git_commit_l return 0; } +static int count_ahead_behind(git_commit_list_node *one, git_commit_list_node *two, + int *ahead, int *behind) +{ + git_commit_list_node *commit; + git_pqueue pq; + int i; + *ahead = 0; + *behind = 0; + + if (git_pqueue_init(&pq, 2, git_commit_list_time_cmp) < 0) + return -1; + if (git_pqueue_insert(&pq, one) < 0) + return -1; + if (git_pqueue_insert(&pq, two) < 0) + return -1; + + while((commit = git_pqueue_pop(&pq)) != NULL) { + if (commit->flags & RESULT || + (commit->flags & (PARENT1 | PARENT2)) == (PARENT1 | PARENT2)) + continue; + else if (commit->flags & PARENT1) + (*behind)++; + else if (commit->flags & PARENT2) + (*ahead)++; + + for (i = 0; i < commit->out_degree; i++) { + git_commit_list_node *p = commit->parents[i]; + if (git_pqueue_insert(&pq, p) < 0) + return -1; + } + commit->flags |= RESULT; + } + + return 0; +} + +int git_count_ahead_behind(int *ahead, int *behind, git_repository *repo, git_oid *one, + git_oid *two) +{ + git_revwalk *walk; + git_vector list; + struct git_commit_list *result = NULL; + git_commit_list_node *commit1, *commit2; + void *contents[1]; + + if (git_revwalk_new(&walk, repo) < 0) + return -1; + + commit2 = commit_lookup(walk, two); + if (commit2 == NULL) + goto on_error; + + /* This is just one value, so we can do it on the stack */ + memset(&list, 0x0, sizeof(git_vector)); + contents[0] = commit2; + list.length = 1; + list.contents = contents; + + commit1 = commit_lookup(walk, one); + if (commit1 == NULL) + goto on_error; + + if (git_merge__bases_many(&result, walk, commit1, &list) < 0) + goto on_error; + if (count_ahead_behind(commit1, commit2, ahead, behind) < 0) + goto on_error; + + if (!result) { + git_revwalk_free(walk); + return GIT_ENOTFOUND; + } + + git_commit_list_free(&result); + git_revwalk_free(walk); + + return 0; + +on_error: + git_revwalk_free(walk); + return -1; +} From eddde61846d3e2bcd5bfbfec486940d378d61231 Mon Sep 17 00:00:00 2001 From: "Scott J. Goldman" Date: Tue, 27 Nov 2012 16:37:11 -0800 Subject: [PATCH 2/9] Add tests for ahead-behind count --- tests-clar/revwalk/mergebase.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests-clar/revwalk/mergebase.c b/tests-clar/revwalk/mergebase.c index 268574eb6..c70222f19 100644 --- a/tests-clar/revwalk/mergebase.c +++ b/tests-clar/revwalk/mergebase.c @@ -18,6 +18,7 @@ void test_revwalk_mergebase__cleanup(void) void test_revwalk_mergebase__single1(void) { git_oid result, one, two, expected; + int ahead, behind; cl_git_pass(git_oid_fromstr(&one, "c47800c7266a2be04c571c04d5a6614691ea99bd ")); cl_git_pass(git_oid_fromstr(&two, "9fd738e8f7967c078dceed8190330fc8648ee56a")); @@ -25,11 +26,20 @@ void test_revwalk_mergebase__single1(void) cl_git_pass(git_merge_base(&result, _repo, &one, &two)); cl_assert(git_oid_cmp(&result, &expected) == 0); + + cl_git_pass(git_count_ahead_behind(&ahead, &behind, _repo, &one, &two)); + cl_assert(ahead == 2); + cl_assert(behind == 1); + + cl_git_pass(git_count_ahead_behind(&ahead, &behind, _repo, &two, &one)); + cl_assert(ahead == 1); + cl_assert(behind == 2); } void test_revwalk_mergebase__single2(void) { git_oid result, one, two, expected; + int ahead, behind; cl_git_pass(git_oid_fromstr(&one, "763d71aadf09a7951596c9746c024e7eece7c7af")); cl_git_pass(git_oid_fromstr(&two, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750")); @@ -37,11 +47,20 @@ void test_revwalk_mergebase__single2(void) cl_git_pass(git_merge_base(&result, _repo, &one, &two)); cl_assert(git_oid_cmp(&result, &expected) == 0); + + cl_git_pass(git_count_ahead_behind( &ahead, &behind, _repo, &one, &two)); + cl_assert(ahead == 4); + cl_assert(behind == 1); + + cl_git_pass(git_count_ahead_behind( &ahead, &behind, _repo, &two, &one)); + cl_assert(ahead == 1); + cl_assert(behind == 4); } void test_revwalk_mergebase__merged_branch(void) { git_oid result, one, two, expected; + int ahead, behind; cl_git_pass(git_oid_fromstr(&one, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750")); cl_git_pass(git_oid_fromstr(&two, "9fd738e8f7967c078dceed8190330fc8648ee56a")); @@ -52,11 +71,20 @@ void test_revwalk_mergebase__merged_branch(void) cl_git_pass(git_merge_base(&result, _repo, &two, &one)); cl_assert(git_oid_cmp(&result, &expected) == 0); + + cl_git_pass(git_count_ahead_behind(&ahead, &behind, _repo, &one, &two)); + cl_assert(ahead == 0); + cl_assert(behind == 3); + + cl_git_pass(git_count_ahead_behind(&ahead, &behind, _repo, &two, &one)); + cl_assert(ahead == 3); + cl_assert(behind == 0); } void test_revwalk_mergebase__no_common_ancestor_returns_ENOTFOUND(void) { git_oid result, one, two; + int ahead, behind; int error; cl_git_pass(git_oid_fromstr(&one, "763d71aadf09a7951596c9746c024e7eece7c7af")); @@ -66,6 +94,11 @@ void test_revwalk_mergebase__no_common_ancestor_returns_ENOTFOUND(void) cl_git_fail(error); cl_assert_equal_i(GIT_ENOTFOUND, error); + + cl_git_fail(git_count_ahead_behind(&ahead, &behind, _repo, &one, &two)); + cl_git_fail(error); + + cl_assert_equal_i(GIT_ENOTFOUND, error); } void test_revwalk_mergebase__no_off_by_one_missing(void) From 0d9e0323a552078a6bec639f2c715b3d9f267922 Mon Sep 17 00:00:00 2001 From: "Scott J. Goldman" Date: Tue, 27 Nov 2012 23:27:41 -0800 Subject: [PATCH 3/9] Add the ahead/behind test that Carlos suggested Adds a repo with a more complex topology to test the ahead-behind count. --- tests-clar/resources/twowaymerge.git/HEAD | 1 + tests-clar/resources/twowaymerge.git/config | 5 + .../resources/twowaymerge.git/description | 1 + .../resources/twowaymerge.git/info/exclude | 6 + .../0c/8a3f1f3d5f421cf83048c7c73ee3b55a5e0f29 | Bin 0 -> 157 bytes .../10/2dce8e3081f398e4bdd9fd894dc85ac3ca6a67 | Bin 0 -> 54 bytes .../17/7d8634a28e26ec7819284752757ebe01a479d5 | Bin 0 -> 80 bytes .../1c/30b88f5f3ee66d78df6520a7de9e89b890818b | 3 + .../1f/4c0311a24b63f6fc209a59a1e404942d4a5006 | 2 + .../22/24e191514cb4bd8c566d80dac22dfcb1e9bb83 | 3 + .../29/6e56023cdc034d2735fee8c0d85a659d1b07f4 | Bin 0 -> 51 bytes .../31/51880ae2b363f1c262cf98b750c1f169a0d432 | Bin 0 -> 68 bytes .../3b/287f8730c81d0b763c2d294618a5e32b67b4f8 | Bin 0 -> 54 bytes .../42/b7311aa626e712891940c1ec5d5cba201946a4 | 3 + .../49/6d6428b9cf92981dc9495211e6e1120fb6f2ba | Bin 0 -> 46 bytes .../59/b0cf7d74659e1cdb13305319d6d4ce2733c118 | Bin 0 -> 65 bytes .../6a/b5d28acbf3c3bdff276f7ccfdf29c1520e542f | 1 + .../6c/fca542b55b8b37017e6125a4b8f59a6eae6f11 | Bin 0 -> 68 bytes .../76/5b32c65d38f04c4f287abda055818ec0f26912 | Bin 0 -> 54 bytes .../7b/8c336c45fc6895c1c60827260fe5d798e5d247 | 3 + .../82/bf9a1a10a4b25c1f14c9607b60970705e92545 | 1 + .../8b/82fb1794cb1c8c7f172ec730a4c2db0ae3e650 | 3 + .../9a/40a2f11c191f180c47e54b11567cb3c1e89b30 | Bin 0 -> 62 bytes .../9b/219343610c88a1187c996d0dc58330b55cee28 | 2 + .../9f/e06a50f4d1634d6c6879854d01d80857388706 | Bin 0 -> 65 bytes .../a4/1a49f8f5cd9b6cb14a076bf8394881ed0b4d19 | 3 + .../a9/53a018c5b10b20c86e69fef55ebc8ad4c5a417 | 1 + .../a9/cce3cd1b3efbda5b1f4a6dcc3f1570b2d3d74c | 1 + .../bd/1732c43c68d712ad09e1d872b9be6d4b9efdc4 | Bin 0 -> 158 bytes .../c3/7a783c20d92ac92362a78a32860f7eebf938ef | Bin 0 -> 158 bytes .../cb/dd40facab1682754eb67f7a43f29e672903cf6 | Bin 0 -> 51 bytes .../cd/f97fd3bb48eb3827638bb33d208f5fd32d0aa6 | Bin 0 -> 158 bytes .../d6/f10d549cb335b9e6d38afc1f0088be69b50494 | Bin 0 -> 62 bytes .../d9/acdc7ae7632adfeec67fa73c1e343cf4d1f47e | 1 + .../e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 | Bin 0 -> 15 bytes .../ef/0488f0b722f0be8bcb90a7730ac7efafd1d694 | 1 + .../fc/f7e3f51c11d199ab7a78403ee4f9ccd028da25 | Bin 0 -> 62 bytes .../twowaymerge.git/refs/heads/first-branch | 1 + .../twowaymerge.git/refs/heads/master | 1 + .../twowaymerge.git/refs/heads/second-branch | 1 + tests-clar/revwalk/mergebase.c | 118 +++++++++++++++++- 41 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 tests-clar/resources/twowaymerge.git/HEAD create mode 100644 tests-clar/resources/twowaymerge.git/config create mode 100644 tests-clar/resources/twowaymerge.git/description create mode 100644 tests-clar/resources/twowaymerge.git/info/exclude create mode 100644 tests-clar/resources/twowaymerge.git/objects/0c/8a3f1f3d5f421cf83048c7c73ee3b55a5e0f29 create mode 100644 tests-clar/resources/twowaymerge.git/objects/10/2dce8e3081f398e4bdd9fd894dc85ac3ca6a67 create mode 100644 tests-clar/resources/twowaymerge.git/objects/17/7d8634a28e26ec7819284752757ebe01a479d5 create mode 100644 tests-clar/resources/twowaymerge.git/objects/1c/30b88f5f3ee66d78df6520a7de9e89b890818b create mode 100644 tests-clar/resources/twowaymerge.git/objects/1f/4c0311a24b63f6fc209a59a1e404942d4a5006 create mode 100644 tests-clar/resources/twowaymerge.git/objects/22/24e191514cb4bd8c566d80dac22dfcb1e9bb83 create mode 100644 tests-clar/resources/twowaymerge.git/objects/29/6e56023cdc034d2735fee8c0d85a659d1b07f4 create mode 100644 tests-clar/resources/twowaymerge.git/objects/31/51880ae2b363f1c262cf98b750c1f169a0d432 create mode 100644 tests-clar/resources/twowaymerge.git/objects/3b/287f8730c81d0b763c2d294618a5e32b67b4f8 create mode 100644 tests-clar/resources/twowaymerge.git/objects/42/b7311aa626e712891940c1ec5d5cba201946a4 create mode 100644 tests-clar/resources/twowaymerge.git/objects/49/6d6428b9cf92981dc9495211e6e1120fb6f2ba create mode 100644 tests-clar/resources/twowaymerge.git/objects/59/b0cf7d74659e1cdb13305319d6d4ce2733c118 create mode 100644 tests-clar/resources/twowaymerge.git/objects/6a/b5d28acbf3c3bdff276f7ccfdf29c1520e542f create mode 100644 tests-clar/resources/twowaymerge.git/objects/6c/fca542b55b8b37017e6125a4b8f59a6eae6f11 create mode 100644 tests-clar/resources/twowaymerge.git/objects/76/5b32c65d38f04c4f287abda055818ec0f26912 create mode 100644 tests-clar/resources/twowaymerge.git/objects/7b/8c336c45fc6895c1c60827260fe5d798e5d247 create mode 100644 tests-clar/resources/twowaymerge.git/objects/82/bf9a1a10a4b25c1f14c9607b60970705e92545 create mode 100644 tests-clar/resources/twowaymerge.git/objects/8b/82fb1794cb1c8c7f172ec730a4c2db0ae3e650 create mode 100644 tests-clar/resources/twowaymerge.git/objects/9a/40a2f11c191f180c47e54b11567cb3c1e89b30 create mode 100644 tests-clar/resources/twowaymerge.git/objects/9b/219343610c88a1187c996d0dc58330b55cee28 create mode 100644 tests-clar/resources/twowaymerge.git/objects/9f/e06a50f4d1634d6c6879854d01d80857388706 create mode 100644 tests-clar/resources/twowaymerge.git/objects/a4/1a49f8f5cd9b6cb14a076bf8394881ed0b4d19 create mode 100644 tests-clar/resources/twowaymerge.git/objects/a9/53a018c5b10b20c86e69fef55ebc8ad4c5a417 create mode 100644 tests-clar/resources/twowaymerge.git/objects/a9/cce3cd1b3efbda5b1f4a6dcc3f1570b2d3d74c create mode 100644 tests-clar/resources/twowaymerge.git/objects/bd/1732c43c68d712ad09e1d872b9be6d4b9efdc4 create mode 100644 tests-clar/resources/twowaymerge.git/objects/c3/7a783c20d92ac92362a78a32860f7eebf938ef create mode 100644 tests-clar/resources/twowaymerge.git/objects/cb/dd40facab1682754eb67f7a43f29e672903cf6 create mode 100644 tests-clar/resources/twowaymerge.git/objects/cd/f97fd3bb48eb3827638bb33d208f5fd32d0aa6 create mode 100644 tests-clar/resources/twowaymerge.git/objects/d6/f10d549cb335b9e6d38afc1f0088be69b50494 create mode 100644 tests-clar/resources/twowaymerge.git/objects/d9/acdc7ae7632adfeec67fa73c1e343cf4d1f47e create mode 100644 tests-clar/resources/twowaymerge.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 create mode 100644 tests-clar/resources/twowaymerge.git/objects/ef/0488f0b722f0be8bcb90a7730ac7efafd1d694 create mode 100644 tests-clar/resources/twowaymerge.git/objects/fc/f7e3f51c11d199ab7a78403ee4f9ccd028da25 create mode 100644 tests-clar/resources/twowaymerge.git/refs/heads/first-branch create mode 100644 tests-clar/resources/twowaymerge.git/refs/heads/master create mode 100644 tests-clar/resources/twowaymerge.git/refs/heads/second-branch diff --git a/tests-clar/resources/twowaymerge.git/HEAD b/tests-clar/resources/twowaymerge.git/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests-clar/resources/twowaymerge.git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests-clar/resources/twowaymerge.git/config b/tests-clar/resources/twowaymerge.git/config new file mode 100644 index 000000000..c53d818dd --- /dev/null +++ b/tests-clar/resources/twowaymerge.git/config @@ -0,0 +1,5 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = true + ignorecase = true diff --git a/tests-clar/resources/twowaymerge.git/description b/tests-clar/resources/twowaymerge.git/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests-clar/resources/twowaymerge.git/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/twowaymerge.git/info/exclude b/tests-clar/resources/twowaymerge.git/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests-clar/resources/twowaymerge.git/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests-clar/resources/twowaymerge.git/objects/0c/8a3f1f3d5f421cf83048c7c73ee3b55a5e0f29 b/tests-clar/resources/twowaymerge.git/objects/0c/8a3f1f3d5f421cf83048c7c73ee3b55a5e0f29 new file mode 100644 index 0000000000000000000000000000000000000000..12698affab4238d1a9cd8efe845514523d1a7e4e GIT binary patch literal 157 zcmV;O0Al}m0iBLZ3c@fH0A1%4?*f*WmzOjF5qE-HPmph`m_}-Pf9n<84#P09)%xf_ z#D~7-4CGAK21&&fQE{SC>5{XJn5_0jyCegSg~i*idFdbv@1B&NI2ct-iGL?isx=eEK0pw literal 0 HcmV?d00001 diff --git a/tests-clar/resources/twowaymerge.git/objects/10/2dce8e3081f398e4bdd9fd894dc85ac3ca6a67 b/tests-clar/resources/twowaymerge.git/objects/10/2dce8e3081f398e4bdd9fd894dc85ac3ca6a67 new file mode 100644 index 0000000000000000000000000000000000000000..3806ee74cf9a9e0f45db0d033bebed587e3dac37 GIT binary patch literal 54 zcmb9v}7TKy4`6 ,y9jGJ8b\f5/ ^8v'˜`SƝ%[ +T[[,psL6oK5;n-=D \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/1f/4c0311a24b63f6fc209a59a1e404942d4a5006 b/tests-clar/resources/twowaymerge.git/objects/1f/4c0311a24b63f6fc209a59a1e404942d4a5006 new file mode 100644 index 000000000..99288fdd7 --- /dev/null +++ b/tests-clar/resources/twowaymerge.git/objects/1f/4c0311a24b63f6fc209a59a1e404942d4a5006 @@ -0,0 +1,2 @@ +x=0 @aM6BlH m!RqO7[ r5gNXű)Eg]DY2c R8x7 +TRo8~Ӣ[#uj;`7 \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/22/24e191514cb4bd8c566d80dac22dfcb1e9bb83 b/tests-clar/resources/twowaymerge.git/objects/22/24e191514cb4bd8c566d80dac22dfcb1e9bb83 new file mode 100644 index 000000000..48466ea51 --- /dev/null +++ b/tests-clar/resources/twowaymerge.git/objects/22/24e191514cb4bd8c566d80dac22dfcb1e9bb83 @@ -0,0 +1,3 @@ +xK +0@]sK& z4HMobY1t[JblɈ4vɡL '՛V`B . +Im 1ZǠxcKh^^+\>?2a.M,tTBp^kucjV_sFh \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/29/6e56023cdc034d2735fee8c0d85a659d1b07f4 b/tests-clar/resources/twowaymerge.git/objects/29/6e56023cdc034d2735fee8c0d85a659d1b07f4 new file mode 100644 index 0000000000000000000000000000000000000000..aa3fccdf0c0bc5425c76decb4105a908641c9e44 GIT binary patch literal 51 zcmb)BU|?ckU~CxZky2sy{o)&6@%5I~<=N}B`*#(-@bv%SvLZz&%#)#d Hr|fzF-?|ht literal 0 HcmV?d00001 diff --git a/tests-clar/resources/twowaymerge.git/objects/31/51880ae2b363f1c262cf98b750c1f169a0d432 b/tests-clar/resources/twowaymerge.git/objects/31/51880ae2b363f1c262cf98b750c1f169a0d432 new file mode 100644 index 0000000000000000000000000000000000000000..235d42bff5f9d890465806df814f5fb954a12429 GIT binary patch literal 68 zcmV-K0K5Nq0V^p=O;s>5FlI0`FfcPQQAlKXHuur&O&6~@dv|NDE04Ny=t)oTM5tsE aKFMT!k}3EkQ}Icr;gd|qDhU8=`C@}+o*X;? literal 0 HcmV?d00001 diff --git a/tests-clar/resources/twowaymerge.git/objects/3b/287f8730c81d0b763c2d294618a5e32b67b4f8 b/tests-clar/resources/twowaymerge.git/objects/3b/287f8730c81d0b763c2d294618a5e32b67b4f8 new file mode 100644 index 0000000000000000000000000000000000000000..56ddac5ee6ce544f60ff65dcfa1601822f76dcb3 GIT binary patch literal 54 zcmb)5VqjumU~CxZky2sy{o)&6@%5I~<=N}B`*#(-@bv%S!tmz_{}%v( Ch!a`> literal 0 HcmV?d00001 diff --git a/tests-clar/resources/twowaymerge.git/objects/59/b0cf7d74659e1cdb13305319d6d4ce2733c118 b/tests-clar/resources/twowaymerge.git/objects/59/b0cf7d74659e1cdb13305319d6d4ce2733c118 new file mode 100644 index 0000000000000000000000000000000000000000..30b507c06839e5ee67fc272a15916040a7e4dc5c GIT binary patch literal 65 zcmV-H0KWft0V^p=O;s>7H(@X|FfcPQQAlKXHuur&O&6~@dv|NDE04Ny=t)oTM5tsE XKFKtElIi#)Gw?}fVwD5{Dgsp456~ID literal 0 HcmV?d00001 diff --git a/tests-clar/resources/twowaymerge.git/objects/6a/b5d28acbf3c3bdff276f7ccfdf29c1520e542f b/tests-clar/resources/twowaymerge.git/objects/6a/b5d28acbf3c3bdff276f7ccfdf29c1520e542f new file mode 100644 index 000000000..ff6a386ac --- /dev/null +++ b/tests-clar/resources/twowaymerge.git/objects/6a/b5d28acbf3c3bdff276f7ccfdf29c1520e542f @@ -0,0 +1 @@ +xM0@a=\@2cܙeRܾŗǵRԶ@(i$uO 19Ro" 9x- @cc3;-KvH+9Fe{O{]b +\>oܦ}踖+Hm z(zl7 F- \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/6c/fca542b55b8b37017e6125a4b8f59a6eae6f11 b/tests-clar/resources/twowaymerge.git/objects/6c/fca542b55b8b37017e6125a4b8f59a6eae6f11 new file mode 100644 index 0000000000000000000000000000000000000000..9a969a279bce6d737174d2eea9425b47d9029236 GIT binary patch literal 68 zcmV-K0K5Nq0V^p=O;s>5FlI0`FfcPQQAlKXHuur&O&6~@dv|NDE04Ny=t)oTM5tsE aKFKtElIi#)Gw?}f;*-q6DhU8_sbZ3D)*Pz< literal 0 HcmV?d00001 diff --git a/tests-clar/resources/twowaymerge.git/objects/76/5b32c65d38f04c4f287abda055818ec0f26912 b/tests-clar/resources/twowaymerge.git/objects/76/5b32c65d38f04c4f287abda055818ec0f26912 new file mode 100644 index 0000000000000000000000000000000000000000..493bbc076b4fec7fb33ff4401945b46b667520d5 GIT binary patch literal 54 zcmbYGMVeMK9Z5H#{EJ: +ϲp:ne>6-sH GծfMS}ZE \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/82/bf9a1a10a4b25c1f14c9607b60970705e92545 b/tests-clar/resources/twowaymerge.git/objects/82/bf9a1a10a4b25c1f14c9607b60970705e92545 new file mode 100644 index 000000000..89b0b9f9b --- /dev/null +++ b/tests-clar/resources/twowaymerge.git/objects/82/bf9a1a10a4b25c1f14c9607b60970705e92545 @@ -0,0 +1 @@ +x 09mh_BܐRןc1-pyPKy4RږDGFJvFE>1#q joimbvSYSbErQ"e{+ޖ=6b+>?/-;3hC#gXyF \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/8b/82fb1794cb1c8c7f172ec730a4c2db0ae3e650 b/tests-clar/resources/twowaymerge.git/objects/8b/82fb1794cb1c8c7f172ec730a4c2db0ae3e650 new file mode 100644 index 000000000..8e9b758ea --- /dev/null +++ b/tests-clar/resources/twowaymerge.git/objects/8b/82fb1794cb1c8c7f172ec730a4c2db0ae3e650 @@ -0,0 +1,3 @@ +xν 0@ajOq 7BtHLp%A8FٟW<= x"ʎ$%1dcDNL:Yv=7yic +l$\b{DbOd9x+ +6T[{ ??yqnӖ:cQZ]͖7H \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/9a/40a2f11c191f180c47e54b11567cb3c1e89b30 b/tests-clar/resources/twowaymerge.git/objects/9a/40a2f11c191f180c47e54b11567cb3c1e89b30 new file mode 100644 index 0000000000000000000000000000000000000000..1de1224f7533b0ab4dff1b7cf4f9eaa07f92a8b2 GIT binary patch literal 62 zcmV-E0Kxxw0V^p=O;s>7F=a3`FfcPQQAlKXHuur&O&6~@dv|NDE04Ny=t)oTM5tso UKFJ(>lDYUK^RP++0CD0+F~%VoEdT%j literal 0 HcmV?d00001 diff --git a/tests-clar/resources/twowaymerge.git/objects/9b/219343610c88a1187c996d0dc58330b55cee28 b/tests-clar/resources/twowaymerge.git/objects/9b/219343610c88a1187c996d0dc58330b55cee28 new file mode 100644 index 000000000..8b64b4381 --- /dev/null +++ b/tests-clar/resources/twowaymerge.git/objects/9b/219343610c88a1187c996d0dc58330b55cee28 @@ -0,0 +1,2 @@ +xKj1ЬFj}Z3 VdFA#?\ zu]FSo"J& ^,9$GEd)7|&[6(FU"&h< Fc4Aƿ>"ZQ;m9\;KP%1b9k93Gkwni[uZ h"RYC[]=0IrKpO: +pʯ _(c \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/9f/e06a50f4d1634d6c6879854d01d80857388706 b/tests-clar/resources/twowaymerge.git/objects/9f/e06a50f4d1634d6c6879854d01d80857388706 new file mode 100644 index 0000000000000000000000000000000000000000..055de01580a58db62f907e09c049224b8be26e26 GIT binary patch literal 65 zcmV-H0KWft0V^p=O;s>7H(@X|FfcPQQAlKXHuur&O&6~@dv|NDE04Ny=t)oTM5tsE XKFMT!k}3Ek)9^{AW0eE|CplEk5=R<2 literal 0 HcmV?d00001 diff --git a/tests-clar/resources/twowaymerge.git/objects/a4/1a49f8f5cd9b6cb14a076bf8394881ed0b4d19 b/tests-clar/resources/twowaymerge.git/objects/a4/1a49f8f5cd9b6cb14a076bf8394881ed0b4d19 new file mode 100644 index 000000000..cb4d34e77 --- /dev/null +++ b/tests-clar/resources/twowaymerge.git/objects/a4/1a49f8f5cd9b6cb14a076bf8394881ed0b4d19 @@ -0,0 +1,3 @@ +xν 0@ajOq 7'!DD A$FٟW<=<5Z +8N(CzDž$'2!>[):#Dzǵ, z M d=tNŭ= +wk}9.p9^Ʃ=I@Y =ulD \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/a9/53a018c5b10b20c86e69fef55ebc8ad4c5a417 b/tests-clar/resources/twowaymerge.git/objects/a9/53a018c5b10b20c86e69fef55ebc8ad4c5a417 new file mode 100644 index 000000000..8235f1839 --- /dev/null +++ b/tests-clar/resources/twowaymerge.git/objects/a9/53a018c5b10b20c86e69fef55ebc8ad4c5a417 @@ -0,0 +1 @@ +xJ0])nV3$is"ONŶɼ\|8!dz dXG/ޫϹp*CX@Z8|f[V0HDHE]6gI#g*9UEHH!MḦhRuo.{zSײ|үwȾ>14C8;rn8qۿ7kNui~M^ \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/a9/cce3cd1b3efbda5b1f4a6dcc3f1570b2d3d74c b/tests-clar/resources/twowaymerge.git/objects/a9/cce3cd1b3efbda5b1f4a6dcc3f1570b2d3d74c new file mode 100644 index 000000000..4da7e826a --- /dev/null +++ b/tests-clar/resources/twowaymerge.git/objects/a9/cce3cd1b3efbda5b1f4a6dcc3f1570b2d3d74c @@ -0,0 +1 @@ +x+)JMU044c040031QHdx6M9{wk+qIODd6>|X%>9j \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/bd/1732c43c68d712ad09e1d872b9be6d4b9efdc4 b/tests-clar/resources/twowaymerge.git/objects/bd/1732c43c68d712ad09e1d872b9be6d4b9efdc4 new file mode 100644 index 0000000000000000000000000000000000000000..b9b60122d7044e8382ae6c6339d126dfc7524424 GIT binary patch literal 158 zcmV;P0Ac@l0iBLP4uUWc06q5=`vJ+e+ofw_j5ianzMw2EV1ybh{};dDb&{EkmU*5k zIOh*_O$kEF9XV~eC&}p5XD1nkRU&1ZspssS)hvWwG-#ld zsAG!i!Lrbl2Z{Sv5{TvrKe}3dST!*QSTi0lrFJOs1wgE}th=OQ#x^LF> McfhFm0ySSn$XT09J^%m! literal 0 HcmV?d00001 diff --git a/tests-clar/resources/twowaymerge.git/objects/c3/7a783c20d92ac92362a78a32860f7eebf938ef b/tests-clar/resources/twowaymerge.git/objects/c3/7a783c20d92ac92362a78a32860f7eebf938ef new file mode 100644 index 0000000000000000000000000000000000000000..041e890abacd84fbfa028b11891f671377b52fe2 GIT binary patch literal 158 zcmV;P0Ac@l0iDiG4uUWcKw;NC#auu#(;ucJ#<(+a>j~On0F6+C<^JLo+9<bR_^!dqiyo`@JZMl&$pMhNP$c%yEh!N53x^Gtf MJ75;`1v)83>3AheTmS$7 literal 0 HcmV?d00001 diff --git a/tests-clar/resources/twowaymerge.git/objects/cb/dd40facab1682754eb67f7a43f29e672903cf6 b/tests-clar/resources/twowaymerge.git/objects/cb/dd40facab1682754eb67f7a43f29e672903cf6 new file mode 100644 index 0000000000000000000000000000000000000000..ccb156d889008fbd24fd13354e0e50183c0cdeec GIT binary patch literal 51 zcmb)BU|?ckU~CxZky2sy{o)&6@%5I~<=N}B`*#(-@bv%SvLeMS%#)#} HUUmln;5ig0 literal 0 HcmV?d00001 diff --git a/tests-clar/resources/twowaymerge.git/objects/cd/f97fd3bb48eb3827638bb33d208f5fd32d0aa6 b/tests-clar/resources/twowaymerge.git/objects/cd/f97fd3bb48eb3827638bb33d208f5fd32d0aa6 new file mode 100644 index 0000000000000000000000000000000000000000..0e028dc019f5399a42380532e9d084f02c6dc0fe GIT binary patch literal 158 zcmV;P0Ac@l0iBLP4#FT106p`H{eTSxWNBiIHxsYEU|E*7MvAHQ|JE;fnZq0=!?l#T zfidpTRuM=8abhGvZw;j^!X7iBj8V(Q0Cp zOgZ(*4^Gk6rnhkP$+Wor9Ck-NgXE2^a(b literal 0 HcmV?d00001 diff --git a/tests-clar/resources/twowaymerge.git/objects/d9/acdc7ae7632adfeec67fa73c1e343cf4d1f47e b/tests-clar/resources/twowaymerge.git/objects/d9/acdc7ae7632adfeec67fa73c1e343cf4d1f47e new file mode 100644 index 000000000..de94528a4 --- /dev/null +++ b/tests-clar/resources/twowaymerge.git/objects/d9/acdc7ae7632adfeec67fa73c1e343cf4d1f47e @@ -0,0 +1 @@ +x+)JMU044c040031QHdx6M9{wk+qIODd>4|X%:79U \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 b/tests-clar/resources/twowaymerge.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 new file mode 100644 index 0000000000000000000000000000000000000000..711223894375fe1186ac5bfffdc48fb1fa1e65cc GIT binary patch literal 15 WcmbhkP$+WorV%4mCGBwm>4qc+yw!^%@`H{ literal 0 HcmV?d00001 diff --git a/tests-clar/resources/twowaymerge.git/refs/heads/first-branch b/tests-clar/resources/twowaymerge.git/refs/heads/first-branch new file mode 100644 index 000000000..ef0dead7f --- /dev/null +++ b/tests-clar/resources/twowaymerge.git/refs/heads/first-branch @@ -0,0 +1 @@ +2224e191514cb4bd8c566d80dac22dfcb1e9bb83 diff --git a/tests-clar/resources/twowaymerge.git/refs/heads/master b/tests-clar/resources/twowaymerge.git/refs/heads/master new file mode 100644 index 000000000..ebf18f58e --- /dev/null +++ b/tests-clar/resources/twowaymerge.git/refs/heads/master @@ -0,0 +1 @@ +1c30b88f5f3ee66d78df6520a7de9e89b890818b diff --git a/tests-clar/resources/twowaymerge.git/refs/heads/second-branch b/tests-clar/resources/twowaymerge.git/refs/heads/second-branch new file mode 100644 index 000000000..586a14a84 --- /dev/null +++ b/tests-clar/resources/twowaymerge.git/refs/heads/second-branch @@ -0,0 +1 @@ +9b219343610c88a1187c996d0dc58330b55cee28 diff --git a/tests-clar/revwalk/mergebase.c b/tests-clar/revwalk/mergebase.c index c70222f19..a44e35b54 100644 --- a/tests-clar/revwalk/mergebase.c +++ b/tests-clar/revwalk/mergebase.c @@ -3,10 +3,12 @@ #include static git_repository *_repo; +static git_repository *_repo2; void test_revwalk_mergebase__initialize(void) { cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git"))); + cl_git_pass(git_repository_open(&_repo2, cl_fixture("twowaymerge.git"))); } void test_revwalk_mergebase__cleanup(void) @@ -81,6 +83,19 @@ void test_revwalk_mergebase__merged_branch(void) cl_assert(behind == 0); } +void test_revwalk_meregebase__two_way_merge(void) +{ + git_oid one, two; + int ahead, behind; + + cl_git_pass(git_oid_fromstr(&one, "9b219343610c88a1187c996d0dc58330b55cee28")); + cl_git_pass(git_oid_fromstr(&two, "a953a018c5b10b20c86e69fef55ebc8ad4c5a417")); + cl_git_pass(git_count_ahead_behind(&ahead, &behind, _repo2, &one, &two)); + + cl_assert(ahead == 8); + cl_assert(behind == 2); +} + void test_revwalk_mergebase__no_common_ancestor_returns_ENOTFOUND(void) { git_oid result, one, two; @@ -176,7 +191,7 @@ void test_revwalk_mergebase__many_merge_branch(void) } /* - * $ git log --graph --all + * testrepo.git $ git log --graph --all * * commit 763d71aadf09a7951596c9746c024e7eece7c7af * | Author: nulltoken * | Date: Sun Oct 9 12:54:47 2011 +0200 @@ -255,3 +270,104 @@ void test_revwalk_mergebase__many_merge_branch(void) * * packed commit one */ + +/* + * twowaymerge.git $ git log --graph --all + * * commit 9b219343610c88a1187c996d0dc58330b55cee28 + * |\ Merge: c37a783 2224e19 + * | | Author: Scott J. Goldman + * | | Date: Tue Nov 27 20:31:04 2012 -0800 + * | | + * | | Merge branch 'first-branch' into second-branch + * | | + * | * commit 2224e191514cb4bd8c566d80dac22dfcb1e9bb83 + * | | Author: Scott J. Goldman + * | | Date: Tue Nov 27 20:28:51 2012 -0800 + * | | + * | | j + * | | + * | * commit a41a49f8f5cd9b6cb14a076bf8394881ed0b4d19 + * | | Author: Scott J. Goldman + * | | Date: Tue Nov 27 20:28:39 2012 -0800 + * | | + * | | i + * | | + * | * commit 82bf9a1a10a4b25c1f14c9607b60970705e92545 + * | | Author: Scott J. Goldman + * | | Date: Tue Nov 27 20:28:28 2012 -0800 + * | | + * | | h + * | | + * * | commit c37a783c20d92ac92362a78a32860f7eebf938ef + * | | Author: Scott J. Goldman + * | | Date: Tue Nov 27 20:30:57 2012 -0800 + * | | + * | | n + * | | + * * | commit 8b82fb1794cb1c8c7f172ec730a4c2db0ae3e650 + * | | Author: Scott J. Goldman + * | | Date: Tue Nov 27 20:30:43 2012 -0800 + * | | + * | | m + * | | + * * | commit 6ab5d28acbf3c3bdff276f7ccfdf29c1520e542f + * | | Author: Scott J. Goldman + * | | Date: Tue Nov 27 20:30:38 2012 -0800 + * | | + * | | l + * | | + * * | commit 7b8c336c45fc6895c1c60827260fe5d798e5d247 + * | | Author: Scott J. Goldman + * | | Date: Tue Nov 27 20:30:24 2012 -0800 + * | | + * | | k + * | | + * | | * commit 1c30b88f5f3ee66d78df6520a7de9e89b890818b + * | | | Author: Scott J. Goldman + * | | | Date: Tue Nov 27 20:28:10 2012 -0800 + * | | | + * | | | e + * | | | + * | | * commit 42b7311aa626e712891940c1ec5d5cba201946a4 + * | | | Author: Scott J. Goldman + * | | | Date: Tue Nov 27 20:28:06 2012 -0800 + * | | | + * | | | d + * | | | + * | | * commit a953a018c5b10b20c86e69fef55ebc8ad4c5a417 + * | | |\ Merge: bd1732c cdf97fd + * | | |/ Author: Scott J. Goldman + * | |/| Date: Tue Nov 27 20:26:43 2012 -0800 + * | | | + * | | | Merge branch 'first-branch' + * | | | + * | * | commit cdf97fd3bb48eb3827638bb33d208f5fd32d0aa6 + * | | | Author: Scott J. Goldman + * | | | Date: Tue Nov 27 20:24:46 2012 -0800 + * | | | + * | | | g + * | | | + * | * | commit ef0488f0b722f0be8bcb90a7730ac7efafd1d694 + * | | | Author: Scott J. Goldman + * | | | Date: Tue Nov 27 20:24:39 2012 -0800 + * | | | + * | | | f + * | | | + * | | * commit bd1732c43c68d712ad09e1d872b9be6d4b9efdc4 + * | |/ Author: Scott J. Goldman + * | | Date: Tue Nov 27 17:43:58 2012 -0800 + * | | + * | | c + * | | + * | * commit 0c8a3f1f3d5f421cf83048c7c73ee3b55a5e0f29 + * |/ Author: Scott J. Goldman + * | Date: Tue Nov 27 17:43:48 2012 -0800 + * | + * | b + * | + * * commit 1f4c0311a24b63f6fc209a59a1e404942d4a5006 + * Author: Scott J. Goldman + * Date: Tue Nov 27 17:43:41 2012 -0800 + * + * a + */ From c6d03c958fc5604c8a00c9a512ec342caa3e43ef Mon Sep 17 00:00:00 2001 From: "Scott J. Goldman" Date: Wed, 28 Nov 2012 18:07:08 -0800 Subject: [PATCH 4/9] fix coding style: while( -> while ( --- src/merge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/merge.c b/src/merge.c index e0fc0abf1..96d2168ba 100644 --- a/src/merge.c +++ b/src/merge.c @@ -258,7 +258,7 @@ static int count_ahead_behind(git_commit_list_node *one, git_commit_list_node *t if (git_pqueue_insert(&pq, two) < 0) return -1; - while((commit = git_pqueue_pop(&pq)) != NULL) { + while ((commit = git_pqueue_pop(&pq)) != NULL) { if (commit->flags & RESULT || (commit->flags & (PARENT1 | PARENT2)) == (PARENT1 | PARENT2)) continue; From 0984c8768d36c73adeabe0229960e651531edf17 Mon Sep 17 00:00:00 2001 From: "Scott J. Goldman" Date: Wed, 28 Nov 2012 18:27:43 -0800 Subject: [PATCH 5/9] Rename git_count_ahead_behind -> git_graph_ahead_behind Moved it into graph.{c,h} which i created for the new "graph" functions namespace. Also adjusted the function prototype to use `size_t` and `const git_oid *`. --- include/git2.h | 1 + include/git2/graph.h | 36 ++++++++++++ include/git2/merge.h | 11 ---- src/graph.c | 100 +++++++++++++++++++++++++++++++++ src/merge.c | 82 --------------------------- tests-clar/revwalk/mergebase.c | 26 ++++----- 6 files changed, 150 insertions(+), 106 deletions(-) create mode 100644 include/git2/graph.h create mode 100644 src/graph.c diff --git a/include/git2.h b/include/git2.h index 501128c43..36f2416c0 100644 --- a/include/git2.h +++ b/include/git2.h @@ -23,6 +23,7 @@ #include "git2/repository.h" #include "git2/revwalk.h" #include "git2/merge.h" +#include "git2/graph.h" #include "git2/refs.h" #include "git2/reflog.h" #include "git2/revparse.h" diff --git a/include/git2/graph.h b/include/git2/graph.h new file mode 100644 index 000000000..c89efa6dd --- /dev/null +++ b/include/git2/graph.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2009-2012 the libgit2 contributors + * + * 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_graph_h__ +#define INCLUDE_git_graph_h__ + +#include "common.h" +#include "types.h" +#include "oid.h" + +/** + * @file git2/graph.h + * @brief Git graph traversal routines + * @defgroup git_revwalk Git graph traversal routines + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** + * Count the number of unique commits between two commit objects + * + * @param ahead number of commits, starting at `one`, unique from commits in `two` + * @param behind number of commits, starting at `two`, unique from commits in `one` + * @param repo the repository where the commits exist + * @param one one of the commits + * @param two the other commit + */ +GIT_EXTERN(int) git_graph_ahead_behind(size_t *ahead, size_t *behind, git_repository *repo, const git_oid *one, const git_oid *two); + +/** @} */ +GIT_END_DECL +#endif diff --git a/include/git2/merge.h b/include/git2/merge.h index 928c4758c..59493969c 100644 --- a/include/git2/merge.h +++ b/include/git2/merge.h @@ -50,17 +50,6 @@ GIT_EXTERN(int) git_merge_base_many( const git_oid input_array[], size_t length); -/** - * Count the number of unique commits between two commit objects - * - * @param ahead number of commits, starting at `one`, unique from commits in `two` - * @param behind number of commits, starting at `two`, unique from commits in `one` - * @param repo the repository where the commits exist - * @param one one of the commits - * @param two the other commit - */ -GIT_EXTERN(int) git_count_ahead_behind(int *ahead, int *behind, git_repository *repo, git_oid *one, git_oid *two); - /** @} */ GIT_END_DECL #endif diff --git a/src/graph.c b/src/graph.c new file mode 100644 index 000000000..db4d73025 --- /dev/null +++ b/src/graph.c @@ -0,0 +1,100 @@ + +/* + * Copyright (C) 2009-2012 the libgit2 contributors + * + * 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 "repository.h" +#include "revwalk.h" +#include "buffer.h" +#include "merge.h" +#include "refs.h" +#include "git2/repository.h" +#include "git2/merge.h" +#include "git2/reset.h" +#include "commit_list.h" +#include "git2/graph.h" + +static int ahead_behind(git_commit_list_node *one, git_commit_list_node *two, + size_t *ahead, size_t *behind) +{ + git_commit_list_node *commit; + git_pqueue pq; + int i; + *ahead = 0; + *behind = 0; + + if (git_pqueue_init(&pq, 2, git_commit_list_time_cmp) < 0) + return -1; + if (git_pqueue_insert(&pq, one) < 0) + return -1; + if (git_pqueue_insert(&pq, two) < 0) + return -1; + + while ((commit = git_pqueue_pop(&pq)) != NULL) { + if (commit->flags & RESULT || + (commit->flags & (PARENT1 | PARENT2)) == (PARENT1 | PARENT2)) + continue; + else if (commit->flags & PARENT1) + (*behind)++; + else if (commit->flags & PARENT2) + (*ahead)++; + + for (i = 0; i < commit->out_degree; i++) { + git_commit_list_node *p = commit->parents[i]; + if (git_pqueue_insert(&pq, p) < 0) + return -1; + } + commit->flags |= RESULT; + } + + return 0; +} + +int git_graph_ahead_behind(size_t *ahead, size_t *behind, git_repository *repo, + const git_oid *one, const git_oid *two) +{ + git_revwalk *walk; + git_vector list; + struct git_commit_list *result = NULL; + git_commit_list_node *commit1, *commit2; + void *contents[1]; + + if (git_revwalk_new(&walk, repo) < 0) + return -1; + + commit2 = commit_lookup(walk, two); + if (commit2 == NULL) + goto on_error; + + /* This is just one value, so we can do it on the stack */ + memset(&list, 0x0, sizeof(git_vector)); + contents[0] = commit2; + list.length = 1; + list.contents = contents; + + commit1 = commit_lookup(walk, one); + if (commit1 == NULL) + goto on_error; + + if (git_merge__bases_many(&result, walk, commit1, &list) < 0) + goto on_error; + if (ahead_behind(commit1, commit2, ahead, behind) < 0) + goto on_error; + + if (!result) { + git_revwalk_free(walk); + return GIT_ENOTFOUND; + } + + git_commit_list_free(&result); + git_revwalk_free(walk); + + return 0; + +on_error: + git_revwalk_free(walk); + return -1; +} diff --git a/src/merge.c b/src/merge.c index 96d2168ba..323b7b877 100644 --- a/src/merge.c +++ b/src/merge.c @@ -241,85 +241,3 @@ int git_merge__bases_many(git_commit_list **out, git_revwalk *walk, git_commit_l *out = result; return 0; } - -static int count_ahead_behind(git_commit_list_node *one, git_commit_list_node *two, - int *ahead, int *behind) -{ - git_commit_list_node *commit; - git_pqueue pq; - int i; - *ahead = 0; - *behind = 0; - - if (git_pqueue_init(&pq, 2, git_commit_list_time_cmp) < 0) - return -1; - if (git_pqueue_insert(&pq, one) < 0) - return -1; - if (git_pqueue_insert(&pq, two) < 0) - return -1; - - while ((commit = git_pqueue_pop(&pq)) != NULL) { - if (commit->flags & RESULT || - (commit->flags & (PARENT1 | PARENT2)) == (PARENT1 | PARENT2)) - continue; - else if (commit->flags & PARENT1) - (*behind)++; - else if (commit->flags & PARENT2) - (*ahead)++; - - for (i = 0; i < commit->out_degree; i++) { - git_commit_list_node *p = commit->parents[i]; - if (git_pqueue_insert(&pq, p) < 0) - return -1; - } - commit->flags |= RESULT; - } - - return 0; -} - -int git_count_ahead_behind(int *ahead, int *behind, git_repository *repo, git_oid *one, - git_oid *two) -{ - git_revwalk *walk; - git_vector list; - struct git_commit_list *result = NULL; - git_commit_list_node *commit1, *commit2; - void *contents[1]; - - if (git_revwalk_new(&walk, repo) < 0) - return -1; - - commit2 = commit_lookup(walk, two); - if (commit2 == NULL) - goto on_error; - - /* This is just one value, so we can do it on the stack */ - memset(&list, 0x0, sizeof(git_vector)); - contents[0] = commit2; - list.length = 1; - list.contents = contents; - - commit1 = commit_lookup(walk, one); - if (commit1 == NULL) - goto on_error; - - if (git_merge__bases_many(&result, walk, commit1, &list) < 0) - goto on_error; - if (count_ahead_behind(commit1, commit2, ahead, behind) < 0) - goto on_error; - - if (!result) { - git_revwalk_free(walk); - return GIT_ENOTFOUND; - } - - git_commit_list_free(&result); - git_revwalk_free(walk); - - return 0; - -on_error: - git_revwalk_free(walk); - return -1; -} diff --git a/tests-clar/revwalk/mergebase.c b/tests-clar/revwalk/mergebase.c index a44e35b54..2cd18601f 100644 --- a/tests-clar/revwalk/mergebase.c +++ b/tests-clar/revwalk/mergebase.c @@ -20,7 +20,7 @@ void test_revwalk_mergebase__cleanup(void) void test_revwalk_mergebase__single1(void) { git_oid result, one, two, expected; - int ahead, behind; + size_t ahead, behind; cl_git_pass(git_oid_fromstr(&one, "c47800c7266a2be04c571c04d5a6614691ea99bd ")); cl_git_pass(git_oid_fromstr(&two, "9fd738e8f7967c078dceed8190330fc8648ee56a")); @@ -29,11 +29,11 @@ void test_revwalk_mergebase__single1(void) cl_git_pass(git_merge_base(&result, _repo, &one, &two)); cl_assert(git_oid_cmp(&result, &expected) == 0); - cl_git_pass(git_count_ahead_behind(&ahead, &behind, _repo, &one, &two)); + cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &one, &two)); cl_assert(ahead == 2); cl_assert(behind == 1); - cl_git_pass(git_count_ahead_behind(&ahead, &behind, _repo, &two, &one)); + cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &two, &one)); cl_assert(ahead == 1); cl_assert(behind == 2); } @@ -41,7 +41,7 @@ void test_revwalk_mergebase__single1(void) void test_revwalk_mergebase__single2(void) { git_oid result, one, two, expected; - int ahead, behind; + size_t ahead, behind; cl_git_pass(git_oid_fromstr(&one, "763d71aadf09a7951596c9746c024e7eece7c7af")); cl_git_pass(git_oid_fromstr(&two, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750")); @@ -50,11 +50,11 @@ void test_revwalk_mergebase__single2(void) cl_git_pass(git_merge_base(&result, _repo, &one, &two)); cl_assert(git_oid_cmp(&result, &expected) == 0); - cl_git_pass(git_count_ahead_behind( &ahead, &behind, _repo, &one, &two)); + cl_git_pass(git_graph_ahead_behind( &ahead, &behind, _repo, &one, &two)); cl_assert(ahead == 4); cl_assert(behind == 1); - cl_git_pass(git_count_ahead_behind( &ahead, &behind, _repo, &two, &one)); + cl_git_pass(git_graph_ahead_behind( &ahead, &behind, _repo, &two, &one)); cl_assert(ahead == 1); cl_assert(behind == 4); } @@ -62,7 +62,7 @@ void test_revwalk_mergebase__single2(void) void test_revwalk_mergebase__merged_branch(void) { git_oid result, one, two, expected; - int ahead, behind; + size_t ahead, behind; cl_git_pass(git_oid_fromstr(&one, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750")); cl_git_pass(git_oid_fromstr(&two, "9fd738e8f7967c078dceed8190330fc8648ee56a")); @@ -74,11 +74,11 @@ void test_revwalk_mergebase__merged_branch(void) cl_git_pass(git_merge_base(&result, _repo, &two, &one)); cl_assert(git_oid_cmp(&result, &expected) == 0); - cl_git_pass(git_count_ahead_behind(&ahead, &behind, _repo, &one, &two)); + cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &one, &two)); cl_assert(ahead == 0); cl_assert(behind == 3); - cl_git_pass(git_count_ahead_behind(&ahead, &behind, _repo, &two, &one)); + cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &two, &one)); cl_assert(ahead == 3); cl_assert(behind == 0); } @@ -86,11 +86,11 @@ void test_revwalk_mergebase__merged_branch(void) void test_revwalk_meregebase__two_way_merge(void) { git_oid one, two; - int ahead, behind; + size_t ahead, behind; cl_git_pass(git_oid_fromstr(&one, "9b219343610c88a1187c996d0dc58330b55cee28")); cl_git_pass(git_oid_fromstr(&two, "a953a018c5b10b20c86e69fef55ebc8ad4c5a417")); - cl_git_pass(git_count_ahead_behind(&ahead, &behind, _repo2, &one, &two)); + cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo2, &one, &two)); cl_assert(ahead == 8); cl_assert(behind == 2); @@ -99,7 +99,7 @@ void test_revwalk_meregebase__two_way_merge(void) void test_revwalk_mergebase__no_common_ancestor_returns_ENOTFOUND(void) { git_oid result, one, two; - int ahead, behind; + size_t ahead, behind; int error; cl_git_pass(git_oid_fromstr(&one, "763d71aadf09a7951596c9746c024e7eece7c7af")); @@ -110,7 +110,7 @@ void test_revwalk_mergebase__no_common_ancestor_returns_ENOTFOUND(void) cl_assert_equal_i(GIT_ENOTFOUND, error); - cl_git_fail(git_count_ahead_behind(&ahead, &behind, _repo, &one, &two)); + cl_git_fail(git_graph_ahead_behind(&ahead, &behind, _repo, &one, &two)); cl_git_fail(error); cl_assert_equal_i(GIT_ENOTFOUND, error); From b994bfe3398d797ff8e8bb538eec41602d5e360a Mon Sep 17 00:00:00 2001 From: "Scott J. Goldman" Date: Wed, 28 Nov 2012 18:48:22 -0800 Subject: [PATCH 6/9] graph.c: prune includes --- src/graph.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/graph.c b/src/graph.c index db4d73025..ff0a8464a 100644 --- a/src/graph.c +++ b/src/graph.c @@ -6,15 +6,8 @@ * a Linking Exception. For full terms see the included COPYING file. */ -#include "repository.h" #include "revwalk.h" -#include "buffer.h" #include "merge.h" -#include "refs.h" -#include "git2/repository.h" -#include "git2/merge.h" -#include "git2/reset.h" -#include "commit_list.h" #include "git2/graph.h" static int ahead_behind(git_commit_list_node *one, git_commit_list_node *two, From d5e44d84983ba199a62ec67f823312584339fae3 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 29 Nov 2012 17:02:27 -0800 Subject: [PATCH 7/9] Fix function name and add real error check `revwalk.h:commit_lookup()` -> `git_revwalk__commit_lookup()` and make `git_commit_list_parse()` do real error checking that the item in the list is an actual commit object. Also fixed an apparent typo in a test name. --- src/commit_list.c | 10 +++++++--- src/graph.c | 4 ++-- src/merge.c | 8 ++++---- src/revwalk.c | 5 +++-- src/revwalk.h | 2 +- tests-clar/revwalk/mergebase.c | 2 +- 6 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/commit_list.c b/src/commit_list.c index c1a7b223f..734e1051f 100644 --- a/src/commit_list.c +++ b/src/commit_list.c @@ -127,7 +127,7 @@ static int commit_quick_parse(git_revwalk *walk, git_commit_list_node *commit, g if (git_oid_fromstr(&oid, (char *)buffer + strlen("parent ")) < 0) return -1; - commit->parents[i] = commit_lookup(walk, &oid); + commit->parents[i] = git_revwalk__commit_lookup(walk, &oid); if (commit->parents[i] == NULL) return -1; @@ -181,9 +181,13 @@ int git_commit_list_parse(git_revwalk *walk, git_commit_list_node *commit) if ((error = git_odb_read(&obj, walk->odb, &commit->oid)) < 0) return error; - assert(obj->raw.type == GIT_OBJ_COMMIT); - error = commit_quick_parse(walk, commit, &obj->raw); + if (obj->raw.type == GIT_OBJ_COMMIT) { + giterr_set(GITERR_INVALID, "Object is no commit object"); + error = -1; + } else + error = commit_quick_parse(walk, commit, &obj->raw); + git_odb_object_free(obj); return error; } diff --git a/src/graph.c b/src/graph.c index ff0a8464a..28026d4b4 100644 --- a/src/graph.c +++ b/src/graph.c @@ -58,7 +58,7 @@ int git_graph_ahead_behind(size_t *ahead, size_t *behind, git_repository *repo, if (git_revwalk_new(&walk, repo) < 0) return -1; - commit2 = commit_lookup(walk, two); + commit2 = git_revwalk__commit_lookup(walk, two); if (commit2 == NULL) goto on_error; @@ -68,7 +68,7 @@ int git_graph_ahead_behind(size_t *ahead, size_t *behind, git_repository *repo, list.length = 1; list.contents = contents; - commit1 = commit_lookup(walk, one); + commit1 = git_revwalk__commit_lookup(walk, one); if (commit1 == NULL) goto on_error; diff --git a/src/merge.c b/src/merge.c index 323b7b877..1386d0908 100644 --- a/src/merge.c +++ b/src/merge.c @@ -71,14 +71,14 @@ int git_merge_base_many(git_oid *out, git_repository *repo, const git_oid input_ goto cleanup; for (i = 1; i < length; i++) { - commit = commit_lookup(walk, &input_array[i]); + commit = git_revwalk__commit_lookup(walk, &input_array[i]); if (commit == NULL) goto cleanup; git_vector_insert(&list, commit); } - commit = commit_lookup(walk, &input_array[0]); + commit = git_revwalk__commit_lookup(walk, &input_array[0]); if (commit == NULL) goto cleanup; @@ -112,7 +112,7 @@ int git_merge_base(git_oid *out, git_repository *repo, const git_oid *one, const if (git_revwalk_new(&walk, repo) < 0) return -1; - commit = commit_lookup(walk, two); + commit = git_revwalk__commit_lookup(walk, two); if (commit == NULL) goto on_error; @@ -122,7 +122,7 @@ int git_merge_base(git_oid *out, git_repository *repo, const git_oid *one, const list.length = 1; list.contents = contents; - commit = commit_lookup(walk, one); + commit = git_revwalk__commit_lookup(walk, one); if (commit == NULL) goto on_error; diff --git a/src/revwalk.c b/src/revwalk.c index bdbbdbd17..cad2f09bd 100644 --- a/src/revwalk.c +++ b/src/revwalk.c @@ -15,7 +15,8 @@ #include -git_commit_list_node *commit_lookup(git_revwalk *walk, const git_oid *oid) +git_commit_list_node *git_revwalk__commit_lookup( + git_revwalk *walk, const git_oid *oid) { git_commit_list_node *commit; khiter_t pos; @@ -101,7 +102,7 @@ static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting) return -1; } - commit = commit_lookup(walk, oid); + commit = git_revwalk__commit_lookup(walk, oid); if (commit == NULL) return -1; /* error already reported by failed lookup */ diff --git a/src/revwalk.h b/src/revwalk.h index 2d482cfcc..6146eaf25 100644 --- a/src/revwalk.h +++ b/src/revwalk.h @@ -39,6 +39,6 @@ struct git_revwalk { git_vector twos; }; -git_commit_list_node *commit_lookup(git_revwalk *walk, const git_oid *oid); +git_commit_list_node *git_revwalk__commit_lookup(git_revwalk *walk, const git_oid *oid); #endif diff --git a/tests-clar/revwalk/mergebase.c b/tests-clar/revwalk/mergebase.c index 2cd18601f..0eb6a9bdb 100644 --- a/tests-clar/revwalk/mergebase.c +++ b/tests-clar/revwalk/mergebase.c @@ -83,7 +83,7 @@ void test_revwalk_mergebase__merged_branch(void) cl_assert(behind == 0); } -void test_revwalk_meregebase__two_way_merge(void) +void test_revwalk_mergebase__two_way_merge(void) { git_oid one, two; size_t ahead, behind; From bdf3e6df8313e44890b137eae28ee2e5d63833b8 Mon Sep 17 00:00:00 2001 From: "Scott J. Goldman" Date: Thu, 29 Nov 2012 17:34:41 -0800 Subject: [PATCH 8/9] Fix error condition typo --- src/commit_list.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commit_list.c b/src/commit_list.c index 734e1051f..d79934a2f 100644 --- a/src/commit_list.c +++ b/src/commit_list.c @@ -182,7 +182,7 @@ int git_commit_list_parse(git_revwalk *walk, git_commit_list_node *commit) if ((error = git_odb_read(&obj, walk->odb, &commit->oid)) < 0) return error; - if (obj->raw.type == GIT_OBJ_COMMIT) { + if (obj->raw.type != GIT_OBJ_COMMIT) { giterr_set(GITERR_INVALID, "Object is no commit object"); error = -1; } else From 1a0c5a34e027620416dadc604f3702ad2e8fe5d0 Mon Sep 17 00:00:00 2001 From: "Scott J. Goldman" Date: Thu, 29 Nov 2012 17:38:37 -0800 Subject: [PATCH 9/9] Fixup ahead/behind tests Fix a typo that caused a failing test, and use cl_assert_equal instead of cl_assert. --- tests-clar/revwalk/mergebase.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/tests-clar/revwalk/mergebase.c b/tests-clar/revwalk/mergebase.c index 0eb6a9bdb..9707d42ca 100644 --- a/tests-clar/revwalk/mergebase.c +++ b/tests-clar/revwalk/mergebase.c @@ -30,12 +30,12 @@ void test_revwalk_mergebase__single1(void) cl_assert(git_oid_cmp(&result, &expected) == 0); cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &one, &two)); - cl_assert(ahead == 2); - cl_assert(behind == 1); + cl_assert_equal_i(ahead, 2); + cl_assert_equal_i(behind, 1); cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &two, &one)); - cl_assert(ahead == 1); - cl_assert(behind == 2); + cl_assert_equal_i(ahead, 1); + cl_assert_equal_i(behind, 2); } void test_revwalk_mergebase__single2(void) @@ -51,12 +51,12 @@ void test_revwalk_mergebase__single2(void) cl_assert(git_oid_cmp(&result, &expected) == 0); cl_git_pass(git_graph_ahead_behind( &ahead, &behind, _repo, &one, &two)); - cl_assert(ahead == 4); - cl_assert(behind == 1); + cl_assert_equal_i(ahead, 4); + cl_assert_equal_i(behind, 1); cl_git_pass(git_graph_ahead_behind( &ahead, &behind, _repo, &two, &one)); - cl_assert(ahead == 1); - cl_assert(behind == 4); + cl_assert_equal_i(ahead, 1); + cl_assert_equal_i(behind, 4); } void test_revwalk_mergebase__merged_branch(void) @@ -75,12 +75,12 @@ void test_revwalk_mergebase__merged_branch(void) cl_assert(git_oid_cmp(&result, &expected) == 0); cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &one, &two)); - cl_assert(ahead == 0); - cl_assert(behind == 3); + cl_assert_equal_i(ahead, 0); + cl_assert_equal_i(behind, 3); cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &two, &one)); - cl_assert(ahead == 3); - cl_assert(behind == 0); + cl_assert_equal_i(ahead, 3); + cl_assert_equal_i(behind, 0); } void test_revwalk_mergebase__two_way_merge(void) @@ -92,8 +92,13 @@ void test_revwalk_mergebase__two_way_merge(void) cl_git_pass(git_oid_fromstr(&two, "a953a018c5b10b20c86e69fef55ebc8ad4c5a417")); cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo2, &one, &two)); - cl_assert(ahead == 8); - cl_assert(behind == 2); + cl_assert_equal_i(ahead, 2); + cl_assert_equal_i(behind, 8); + + cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo2, &two, &one)); + + cl_assert_equal_i(ahead, 8); + cl_assert_equal_i(behind, 2); } void test_revwalk_mergebase__no_common_ancestor_returns_ENOTFOUND(void)