Skip to content

Commit 54fd80e

Browse files
committed
revwalk: fix uninteresting revs sometimes not limiting graphwalk
When we want to limit our graphwalk, we use the heuristic of checking whether the newest limiting (uninteresting) revision is newer than the oldest interesting revision. We do so by inspecting whether the first item's commit time of the user-supplied list of revisions is newer than the last added interesting revision. This is wrong though, as the user supplied list is in no way guaranteed to be sorted by increasing commit dates. This could lead us to abort the revwalk early before applying all relevant limiting revisions, outputting revisions which should in fact have been hidden. Fix the heuristic by instead checking whether _any_ of the limiting commits was made earlier than the last interesting commit. Add a test.
1 parent 0eca423 commit 54fd80e

File tree

10 files changed

+53
-24
lines changed

10 files changed

+53
-24
lines changed

src/revwalk.c

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -375,20 +375,6 @@ static int add_parents_to_list(git_revwalk *walk, git_commit_list_node *commit,
375375
return 0;
376376
}
377377

378-
static int everybody_uninteresting(git_commit_list *orig)
379-
{
380-
git_commit_list *list = orig;
381-
382-
while (list) {
383-
git_commit_list_node *commit = list->item;
384-
list = list->next;
385-
if (!commit->uninteresting)
386-
return 0;
387-
}
388-
389-
return 1;
390-
}
391-
392378
/* How many unintersting commits we want to look at after we run out of interesting ones */
393379
#define SLOP 5
394380

@@ -398,16 +384,15 @@ static int still_interesting(git_commit_list *list, int64_t time, int slop)
398384
if (!list)
399385
return 0;
400386

401-
/*
402-
* If the destination list has commits with an earlier date
403-
* than our source we want to continue looking.
404-
*/
405-
if (time <= list->item->time)
406-
return SLOP;
407-
408-
/* If we find interesting commits, we reset the slop count */
409-
if (!everybody_uninteresting(list))
410-
return SLOP;
387+
for (; list; list = list->next) {
388+
/*
389+
* If the destination list has commits with an earlier date than
390+
* our source or if it still contains interesting commits we
391+
* want to continue looking.
392+
*/
393+
if (!list->item->uninteresting || list->item->time > time)
394+
return SLOP;
395+
}
411396

412397
/* Everything's uninteresting, reduce the count */
413398
return slop - 1;

tests/resources/revwalk.git/HEAD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ref: refs/heads/master

tests/resources/revwalk.git/config

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[core]
2+
bare = true
3+
repositoryformatversion = 0
4+
filemode = false
5+
symlinks = false
6+
ignorecase = true
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Unnamed repository; edit this file 'description' to name the repository.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
P pack-9adacb9971981a1a3264fd473da5b800f2715959.pack
2+
Binary file not shown.
Binary file not shown.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# pack-refs with: peeled fully-peeled sorted
2+
3ae0f53011bdb7e68f99bde4943449f36c1c318a refs/heads/A
3+
061978578d7c9ff2ba92dd36d31fd8d809871030 refs/heads/B
4+
743398b425d6c216d6cfaae3786b5bc436393ae5 refs/heads/C
5+
790ba0facf6fd103699a5c40cd19dad277ff49cd refs/heads/D
6+
d3d783066cf7d95def6844b9c5118c1e7bcce7df refs/heads/E
7+
d3d783066cf7d95def6844b9c5118c1e7bcce7df refs/heads/master

tests/resources/revwalk.git/refs/.gitkeep

Whitespace-only changes.

tests/revwalk/basic.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,3 +555,30 @@ void test_revwalk_basic__old_hidden_commit_two(void)
555555

556556
cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oid, _walk));
557557
}
558+
559+
/*
560+
* Ensure that we correctly hide all parent commits of a newer
561+
* commit when first hiding older commits.
562+
*
563+
* % git rev-list D ^B ^A ^E
564+
* 790ba0facf6fd103699a5c40cd19dad277ff49cd
565+
* b82cee5004151ae0c4f82b69fb71b87477664b6f
566+
*/
567+
void test_revwalk_basic__newer_hidden_commit_hides_old_commits(void)
568+
{
569+
git_oid oid;
570+
571+
revwalk_basic_setup_walk("revwalk.git");
572+
573+
cl_git_pass(git_revwalk_push_ref(_walk, "refs/heads/D"));
574+
cl_git_pass(git_revwalk_hide_ref(_walk, "refs/heads/B"));
575+
cl_git_pass(git_revwalk_hide_ref(_walk, "refs/heads/A"));
576+
cl_git_pass(git_revwalk_hide_ref(_walk, "refs/heads/E"));
577+
578+
cl_git_pass(git_revwalk_next(&oid, _walk));
579+
cl_assert(git_oid_streq(&oid, "b82cee5004151ae0c4f82b69fb71b87477664b6f"));
580+
cl_git_pass(git_revwalk_next(&oid, _walk));
581+
cl_assert(git_oid_streq(&oid, "790ba0facf6fd103699a5c40cd19dad277ff49cd"));
582+
583+
cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oid, _walk));
584+
}

0 commit comments

Comments
 (0)