From f6adbcbfc963b1e18276b719dc108a3da9f41501 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sat, 25 Jun 2016 20:02:45 -0400 Subject: [PATCH 1/4] revwalk: introduce tests that hide old commits Introduce some tests that show some commits, while hiding some commits that have a timestamp older than the common ancestors of these two commits. --- .../43/da5ec3274dd061df152ff5e69853d562b01842 | 2 + .../43/e968a905a821532069bb413801d35b200631cf | 4 ++ .../5d/0f8f7891e872d284beef38254882dc879b2602 | Bin 0 -> 149 bytes .../5f/34cd6e3285089647165983482cf90873d50940 | Bin 0 -> 37 bytes .../8e/73b769e97678d684b809b163bebdae2911720f | 2 + .../b2/04707bbc546a1a770ef6ced37c7089cc3bfe6b | 2 + .../b2/35959d89084af8d3544fbdf675e47944f86524 | Bin 0 -> 77 bytes .../b9/1e763008b10db366442469339f90a2b8400d0a | Bin 0 -> 206 bytes .../bd/758010071961f28336333bc41e9c64c9a64866 | Bin 0 -> 162 bytes .../db/4df74a2fc340a0d0cb0cafc0db471fdfff1048 | 2 + .../db/793a00a5615eca1aac97e42b3a68b1acfa8bfd | Bin 0 -> 193 bytes .../db/c0be625bed24b5d8f5d9a927484f2065d321af | Bin 0 -> 175 bytes .../f0/a2a10243ca64f935dbe3dccb89ec8bf16bdace | Bin 0 -> 38 bytes tests/revwalk/basic.c | 48 ++++++++++++++++++ 14 files changed, 60 insertions(+) create mode 100644 tests/resources/testrepo.git/objects/43/da5ec3274dd061df152ff5e69853d562b01842 create mode 100644 tests/resources/testrepo.git/objects/43/e968a905a821532069bb413801d35b200631cf create mode 100644 tests/resources/testrepo.git/objects/5d/0f8f7891e872d284beef38254882dc879b2602 create mode 100644 tests/resources/testrepo.git/objects/5f/34cd6e3285089647165983482cf90873d50940 create mode 100644 tests/resources/testrepo.git/objects/8e/73b769e97678d684b809b163bebdae2911720f create mode 100644 tests/resources/testrepo.git/objects/b2/04707bbc546a1a770ef6ced37c7089cc3bfe6b create mode 100644 tests/resources/testrepo.git/objects/b2/35959d89084af8d3544fbdf675e47944f86524 create mode 100644 tests/resources/testrepo.git/objects/b9/1e763008b10db366442469339f90a2b8400d0a create mode 100644 tests/resources/testrepo.git/objects/bd/758010071961f28336333bc41e9c64c9a64866 create mode 100644 tests/resources/testrepo.git/objects/db/4df74a2fc340a0d0cb0cafc0db471fdfff1048 create mode 100644 tests/resources/testrepo.git/objects/db/793a00a5615eca1aac97e42b3a68b1acfa8bfd create mode 100644 tests/resources/testrepo.git/objects/db/c0be625bed24b5d8f5d9a927484f2065d321af create mode 100644 tests/resources/testrepo.git/objects/f0/a2a10243ca64f935dbe3dccb89ec8bf16bdace 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 0000000000000000000000000000000000000000..7a22451ed894b5a42364a7f66369ebcbdc7e8f98 GIT binary patch literal 149 zcmV;G0BZku0V^p=O;s>7F=Q|_FfcPQQ3!H%bn$g%5N`dHvVMD1*wTH+ot*d0HmhE8 zio?VJ2ow^N7(P11yjPSt(6h?$`BvBen~c_Mm~j}YJ*g-$FF7MVEi)%oucV@c!F6Zz zKC|sM>>YRJ?Ae~PyWvmuhH$9Tywq~Ak`Id(GC7}0`DuFl@txD1Z@NEb-#P~X4@N+M D#z04o literal 0 HcmV?d00001 diff --git a/tests/resources/testrepo.git/objects/5f/34cd6e3285089647165983482cf90873d50940 b/tests/resources/testrepo.git/objects/5f/34cd6e3285089647165983482cf90873d50940 new file mode 100644 index 0000000000000000000000000000000000000000..b1df3bdd5cf408c6a576fa3041938b194b268734 GIT binary patch literal 37 vcmV+=0NVd}0ZYosPf{>4W(dj1ELH%b#5{%koD_wmqQt!93`H&goVE$TEmshD literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..7d563dbd38955498b07eff4660c2b6cff623abbe GIT binary patch literal 77 zcmV-T0J8sh0V^p=O;s>6WiT`_Ff%bx2y%6F@pWYoZvB+9etT5d(tXFBocGN(t6p-7 j1F9lFCxs#2r13djB-Bl`UFwXBD&G1 znbAz`>$(iE);)|}6{J)w8pszFa>Yw*UQ$lPF1kh-yjU{1O&@vJZ2$)=Y;u-{DRc71 zr%)5SP?4OnYE`cM>vvXDh&iFpk&L%TV=BcN8_|gMg%E=^wN3dx=Dx$LeCA!?eeUb6 zZ}6-K{Z=oRWz6^TRQq}cLu`qSa~>X%5vPM5uZI3NKfURGQTVBW(_crQVA)28eifR& I02(=EX>-VC7sl_|4+y#`=hEw^H@Na)e{`Q;W7(!l>h%W7dQZVQqu?y9l;W_*<=}sN Q(Rhcn#5S||0*`k|){{(4dH?_b literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..ae82880de88232c2d4ea9b6d1f096a847d955b4d GIT binary patch literal 193 zcmV;y06zbC0WFSON(3r!a3a7 zYTXAIYo12W8G@z|Rz@EpT3wvZ2?NVgI5^9hSF6bqCH2KU-v$sHG-An#U=d8>b162K zlEp@k!Xn8aEsBq^wGQvGjRBX9W4po2J^sS^T6zC`j;+3eHlDoE%d)}=J))ZHd^mE4 vxAe_D!N=C>{bA=>e9-y2kL{3upPUOmtiey8rmq-EJNnq*ucUqeBnL|0%C}%Q literal 0 HcmV?d00001 diff --git a/tests/resources/testrepo.git/objects/db/c0be625bed24b5d8f5d9a927484f2065d321af b/tests/resources/testrepo.git/objects/db/c0be625bed24b5d8f5d9a927484f2065d321af new file mode 100644 index 0000000000000000000000000000000000000000..b966b0b2fda7c481c94a110b27d32c6f7484aa4c GIT binary patch literal 175 zcmV;g08syU0V^p=O;s>7H)1d}FfcPQQ3!H%bn$g%5N`dHvVMD1*wTH+ot*d0HmhE8 zio?VJ2ow^N7(P11yjPSt(6h?$`BvBen~c_Mm~j}YJ*g-$FF7MVEi)%oucV@c!F6Zz zKC|sM>>YRJ?Ae~PyWvmuhH$9Tywq~Al3$)1%BL$&TpPh$5b$Yve97ZJ d@g`^Uj9NLSxr;?Md+7Y+D89<+008njM;gt0RR;h7 literal 0 HcmV?d00001 diff --git a/tests/resources/testrepo.git/objects/f0/a2a10243ca64f935dbe3dccb89ec8bf16bdace b/tests/resources/testrepo.git/objects/f0/a2a10243ca64f935dbe3dccb89ec8bf16bdace new file mode 100644 index 0000000000000000000000000000000000000000..1b299dc257b712a486bb7ec5bd07720d88001374 GIT binary patch literal 38 ucmbxW_q Date: Thu, 21 Jul 2016 01:24:12 -0600 Subject: [PATCH 2/4] revwalk: reverse bad logic when marking uninteresting We want to loop until there are no more interesting commits in the array. The reversed logic will stop prematurely leading to incorrect results in cases with nonmonotonic timestamps. --- src/revwalk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/revwalk.c b/src/revwalk.c index 4815a10893d..1bd5b7e0a24 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); From ee0c8b595fb70c5e156529f0e3def1f0aa184f9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 31 Aug 2016 10:22:03 +0200 Subject: [PATCH 3/4] revwalk: mark all incoming uninteresting commits' parents Failing to do so can mean the priority queue never gets around to the unintersting commits that are older than the rest of the history. --- src/revwalk.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/revwalk.c b/src/revwalk.c index 1bd5b7e0a24..5bccb5c3acd 100644 --- a/src/revwalk.c +++ b/src/revwalk.c @@ -425,6 +425,38 @@ static int contains(git_pqueue *list, git_commit_list_node *node) return 0; } +static void mark_parents_uninteresting(git_commit_list_node *commit) +{ + unsigned short i; + git_commit_list *parents = NULL; + + for (i = 0; i < commit->out_degree; i++) + git_commit_list_insert(commit->parents[i], &parents); + + + while (parents) { + git_commit_list_node *commit = git_commit_list_pop(&parents); + + while (commit) { + if (commit->uninteresting) + 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]; + } + } +} + static int premark_uninteresting(git_revwalk *walk) { int error = 0; @@ -440,6 +472,9 @@ static int premark_uninteresting(git_revwalk *walk) if ((error = git_commit_list_parse(walk, list->item)) < 0) goto cleanup; + if (list->item->uninteresting) + mark_parents_uninteresting(list->item); + if ((error = git_pqueue_insert(&q, list->item)) < 0) goto cleanup; } From 872ee9d81069e116ed07e7994c4f13ad2dc05b7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 31 Aug 2016 15:04:41 +0200 Subject: [PATCH 4/4] revwalk: refactor the initial mark-unintersting loop We're now close to the way git itself does it, and most of the logic goes into mark_parents_uninteresting so we can remove our own loop from premark_uninteresting. This function then becomes so simple we should extract its loop and make it part of loop we're running over the same input in its caller. --- src/revwalk.c | 57 ++++++--------------------------------------------- 1 file changed, 6 insertions(+), 51 deletions(-) diff --git a/src/revwalk.c b/src/revwalk.c index 5bccb5c3acd..6a10330097e 100644 --- a/src/revwalk.c +++ b/src/revwalk.c @@ -457,53 +457,6 @@ static void mark_parents_uninteresting(git_commit_list_node *commit) } } -static int premark_uninteresting(git_revwalk *walk) -{ - 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; - - if (list->item->uninteresting) - mark_parents_uninteresting(list->item); - - if ((error = git_pqueue_insert(&q, list->item)) < 0) - goto cleanup; - } - - 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; - - if (commit->uninteresting) - parent->uninteresting = 1; - - if (contains(&q, parent)) - continue; - - if ((error = git_pqueue_insert(&q, parent)) < 0) - goto cleanup; - } - } - -cleanup: - git_pqueue_free(&q); - return error; -} - static int prepare_walk(git_revwalk *walk) { int error; @@ -516,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;