diff --git a/src/revwalk.c b/src/revwalk.c index 4815a10893d..6a10330097e 100644 --- a/src/revwalk.c +++ b/src/revwalk.c @@ -86,7 +86,7 @@ static int mark_uninteresting(git_revwalk *walk, git_commit_list_node *commit) tmp = git_array_pop(pending); commit = tmp ? *tmp : NULL; - } while (commit != NULL && !interesting_arr(pending)); + } while (commit != NULL && interesting_arr(pending)); git_array_clear(pending); @@ -425,48 +425,36 @@ static int contains(git_pqueue *list, git_commit_list_node *node) return 0; } -static int premark_uninteresting(git_revwalk *walk) +static void mark_parents_uninteresting(git_commit_list_node *commit) { - int error = 0; unsigned short i; - git_pqueue q; - git_commit_list *list; - git_commit_list_node *commit, *parent; - - if ((error = git_pqueue_init(&q, 0, 8, git_commit_list_time_cmp)) < 0) - return error; - - for (list = walk->user_input; list; list = list->next) { - if ((error = git_commit_list_parse(walk, list->item)) < 0) - goto cleanup; + git_commit_list *parents = NULL; - if ((error = git_pqueue_insert(&q, list->item)) < 0) - goto cleanup; - } + for (i = 0; i < commit->out_degree; i++) + git_commit_list_insert(commit->parents[i], &parents); - while (interesting(&q)) { - commit = git_pqueue_pop(&q); - for (i = 0; i < commit->out_degree; i++) { - parent = commit->parents[i]; - - if ((error = git_commit_list_parse(walk, parent)) < 0) - goto cleanup; + while (parents) { + git_commit_list_node *commit = git_commit_list_pop(&parents); + while (commit) { if (commit->uninteresting) - parent->uninteresting = 1; - - if (contains(&q, parent)) - continue; - - if ((error = git_pqueue_insert(&q, parent)) < 0) - goto cleanup; + break; + + commit->uninteresting = 1; + /* + * If we've reached this commit some other way + * already, we need to mark its parents uninteresting + * as well. + */ + if (!commit->parents) + break; + + for (i = 0; i < commit->out_degree; i++) + git_commit_list_insert(commit->parents[i], &parents); + commit = commit->parents[0]; } } - -cleanup: - git_pqueue_free(&q); - return error; } static int prepare_walk(git_revwalk *walk) @@ -481,15 +469,17 @@ static int prepare_walk(git_revwalk *walk) return GIT_ITEROVER; } - if (walk->did_hide && (error = premark_uninteresting(walk)) < 0) - return error; - for (list = walk->user_input; list; list = list->next) { + if ((error = git_commit_list_parse(walk, list->item)) < 0) + return error; + + if (list->item->uninteresting) + mark_parents_uninteresting(list->item); + if (process_commit(walk, list->item, list->item->uninteresting) < 0) return -1; } - if (walk->sorting & GIT_SORT_TOPOLOGICAL) { unsigned short i; diff --git a/tests/resources/testrepo.git/objects/43/da5ec3274dd061df152ff5e69853d562b01842 b/tests/resources/testrepo.git/objects/43/da5ec3274dd061df152ff5e69853d562b01842 new file mode 100644 index 00000000000..298feece49d --- /dev/null +++ b/tests/resources/testrepo.git/objects/43/da5ec3274dd061df152ff5e69853d562b01842 @@ -0,0 +1,2 @@ +x-]jC!F*f)]@ + 8 Zۯiv>Os0B%s)fMlhV45 &4ѕ@:D)oIr`$LYws¥Fg`$bo; U|zOu}/._ׁ~J \ No newline at end of file diff --git a/tests/resources/testrepo.git/objects/43/e968a905a821532069bb413801d35b200631cf b/tests/resources/testrepo.git/objects/43/e968a905a821532069bb413801d35b200631cf new file mode 100644 index 00000000000..ec04abf6810 --- /dev/null +++ b/tests/resources/testrepo.git/objects/43/e968a905a821532069bb413801d35b200631cf @@ -0,0 +1,4 @@ +xK +1]}%N'7 8 +\u5zc 68b,D20'Qb㭃@ҩRQ[94)qsmp+ +纾gG=r]/3((tRa>E \ No newline at end of file diff --git a/tests/resources/testrepo.git/objects/5d/0f8f7891e872d284beef38254882dc879b2602 b/tests/resources/testrepo.git/objects/5d/0f8f7891e872d284beef38254882dc879b2602 new file mode 100644 index 00000000000..7a22451ed89 Binary files /dev/null and b/tests/resources/testrepo.git/objects/5d/0f8f7891e872d284beef38254882dc879b2602 differ diff --git a/tests/resources/testrepo.git/objects/5f/34cd6e3285089647165983482cf90873d50940 b/tests/resources/testrepo.git/objects/5f/34cd6e3285089647165983482cf90873d50940 new file mode 100644 index 00000000000..b1df3bdd5cf Binary files /dev/null and b/tests/resources/testrepo.git/objects/5f/34cd6e3285089647165983482cf90873d50940 differ diff --git a/tests/resources/testrepo.git/objects/8e/73b769e97678d684b809b163bebdae2911720f b/tests/resources/testrepo.git/objects/8e/73b769e97678d684b809b163bebdae2911720f new file mode 100644 index 00000000000..d75977a25d4 --- /dev/null +++ b/tests/resources/testrepo.git/objects/8e/73b769e97678d684b809b163bebdae2911720f @@ -0,0 +1,2 @@ +xj0S)*a㚔+l8[A 33yM$m* $qG?YA5< t8r57nD#.d)~N0˄)R,|,hjQ*tC~ |uzҧݗ> +ƒd8\S]!7 s ,[P2fw^ \ No newline at end of file diff --git a/tests/resources/testrepo.git/objects/b2/04707bbc546a1a770ef6ced37c7089cc3bfe6b b/tests/resources/testrepo.git/objects/b2/04707bbc546a1a770ef6ced37c7089cc3bfe6b new file mode 100644 index 00000000000..f9ec61c1e2c --- /dev/null +++ b/tests/resources/testrepo.git/objects/b2/04707bbc546a1a770ef6ced37c7089cc3bfe6b @@ -0,0 +1,2 @@ +x-]0 })t.Q J),{-7^\^ҷA7(FW"A%ɣygiTId?_#[(-D0wdpR*\Bi ~[;|madjRja +kRstmG"7{~LD \ No newline at end of file diff --git a/tests/resources/testrepo.git/objects/b2/35959d89084af8d3544fbdf675e47944f86524 b/tests/resources/testrepo.git/objects/b2/35959d89084af8d3544fbdf675e47944f86524 new file mode 100644 index 00000000000..7d563dbd389 Binary files /dev/null and b/tests/resources/testrepo.git/objects/b2/35959d89084af8d3544fbdf675e47944f86524 differ diff --git a/tests/resources/testrepo.git/objects/b9/1e763008b10db366442469339f90a2b8400d0a b/tests/resources/testrepo.git/objects/b9/1e763008b10db366442469339f90a2b8400d0a new file mode 100644 index 00000000000..7bab59be8c8 Binary files /dev/null and b/tests/resources/testrepo.git/objects/b9/1e763008b10db366442469339f90a2b8400d0a differ diff --git a/tests/resources/testrepo.git/objects/bd/758010071961f28336333bc41e9c64c9a64866 b/tests/resources/testrepo.git/objects/bd/758010071961f28336333bc41e9c64c9a64866 new file mode 100644 index 00000000000..c5e3b87ad08 Binary files /dev/null and b/tests/resources/testrepo.git/objects/bd/758010071961f28336333bc41e9c64c9a64866 differ diff --git a/tests/resources/testrepo.git/objects/db/4df74a2fc340a0d0cb0cafc0db471fdfff1048 b/tests/resources/testrepo.git/objects/db/4df74a2fc340a0d0cb0cafc0db471fdfff1048 new file mode 100644 index 00000000000..5f3d50efa28 --- /dev/null +++ b/tests/resources/testrepo.git/objects/db/4df74a2fc340a0d0cb0cafc0db471fdfff1048 @@ -0,0 +1,2 @@ +x-QJ1PsIz2= @/tz7f",^߬WպpFWgkѭ`$8J0c5 +I҈J>!+NU(û1Di<_7.5O X[#fo; ]\e=[@t&xHhYJn \ No newline at end of file diff --git a/tests/resources/testrepo.git/objects/db/793a00a5615eca1aac97e42b3a68b1acfa8bfd b/tests/resources/testrepo.git/objects/db/793a00a5615eca1aac97e42b3a68b1acfa8bfd new file mode 100644 index 00000000000..ae82880de88 Binary files /dev/null and b/tests/resources/testrepo.git/objects/db/793a00a5615eca1aac97e42b3a68b1acfa8bfd differ diff --git a/tests/resources/testrepo.git/objects/db/c0be625bed24b5d8f5d9a927484f2065d321af b/tests/resources/testrepo.git/objects/db/c0be625bed24b5d8f5d9a927484f2065d321af new file mode 100644 index 00000000000..b966b0b2fda Binary files /dev/null and b/tests/resources/testrepo.git/objects/db/c0be625bed24b5d8f5d9a927484f2065d321af differ diff --git a/tests/resources/testrepo.git/objects/f0/a2a10243ca64f935dbe3dccb89ec8bf16bdace b/tests/resources/testrepo.git/objects/f0/a2a10243ca64f935dbe3dccb89ec8bf16bdace new file mode 100644 index 00000000000..1b299dc257b Binary files /dev/null and b/tests/resources/testrepo.git/objects/f0/a2a10243ca64f935dbe3dccb89ec8bf16bdace differ diff --git a/tests/revwalk/basic.c b/tests/revwalk/basic.c index 5ed7da4eba9..db01773a2b8 100644 --- a/tests/revwalk/basic.c +++ b/tests/revwalk/basic.c @@ -473,3 +473,51 @@ void test_revwalk_basic__big_timestamp(void) git_signature_free(sig); } + +/* Ensure that we correctly hide a commit that is (timewise) older + * than the commits that we are showing. + * + * % git rev-list 8e73b76..bd75801 + * bd758010071961f28336333bc41e9c64c9a64866 + */ +void test_revwalk_basic__old_hidden_commit_one(void) +{ + git_oid new_id, old_id, oid; + + revwalk_basic_setup_walk("testrepo.git"); + + cl_git_pass(git_oid_fromstr(&new_id, "bd758010071961f28336333bc41e9c64c9a64866")); + cl_git_pass(git_revwalk_push(_walk, &new_id)); + + cl_git_pass(git_oid_fromstr(&old_id, "8e73b769e97678d684b809b163bebdae2911720f")); + cl_git_pass(git_revwalk_hide(_walk, &old_id)); + + cl_git_pass(git_revwalk_next(&oid, _walk)); + cl_assert(!git_oid_streq(&oid, "bd758010071961f28336333bc41e9c64c9a64866")); + + cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oid, _walk)); +} + +/* Ensure that we correctly hide a commit that is (timewise) older + * than the commits that we are showing. + * + * % git rev-list bd75801 ^b91e763 + * bd758010071961f28336333bc41e9c64c9a64866 + */ +void test_revwalk_basic__old_hidden_commit_two(void) +{ + git_oid new_id, old_id, oid; + + revwalk_basic_setup_walk("testrepo.git"); + + cl_git_pass(git_oid_fromstr(&new_id, "bd758010071961f28336333bc41e9c64c9a64866")); + cl_git_pass(git_revwalk_push(_walk, &new_id)); + + cl_git_pass(git_oid_fromstr(&old_id, "b91e763008b10db366442469339f90a2b8400d0a")); + cl_git_pass(git_revwalk_hide(_walk, &old_id)); + + cl_git_pass(git_revwalk_next(&oid, _walk)); + cl_assert(!git_oid_streq(&oid, "bd758010071961f28336333bc41e9c64c9a64866")); + + cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oid, _walk)); +}