From: Junio C Hamano Date: Mon, 24 Sep 2018 17:30:52 +0000 (-0700) Subject: Merge branch 'ds/reachable' X-Git-Tag: v2.20.0-rc0~210 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/0f7ac90dbe7ecf511883b7aae84acbb698418f60?ds=inline;hp=-c Merge branch 'ds/reachable' Recent update broke the reachability algorithm when refs (e.g. tags) that point at objects that are not commit were involved, which has been fixed. * ds/reachable: commit-reach: fix memory and flag leaks commit-reach: properly peel tags --- 0f7ac90dbe7ecf511883b7aae84acbb698418f60 diff --combined commit-reach.c index 622eeb313d,5a845440a9..00e5ceee6f --- a/commit-reach.c +++ b/commit-reach.c @@@ -39,9 -39,6 +39,9 @@@ static struct commit_list *paint_down_t int i; uint32_t last_gen = GENERATION_NUMBER_INFINITY; + if (!min_generation) + queue.compare = compare_commits_by_commit_date; + one->object.flags |= PARENT1; if (!n) { commit_list_append(one, &result); @@@ -59,7 -56,7 +59,7 @@@ struct commit_list *parents; int flags; - if (commit->generation > last_gen) + if (min_generation && commit->generation > last_gen) BUG("bad generation skip %8x > %8x at %s", commit->generation, last_gen, oid_to_hex(&commit->object.oid)); @@@ -547,20 -544,42 +547,42 @@@ int can_all_from_reach_with_flag(struc { struct commit **list = NULL; int i; + int nr_commits; int result = 1; ALLOC_ARRAY(list, from->nr); + nr_commits = 0; for (i = 0; i < from->nr; i++) { - list[i] = (struct commit *)from->objects[i].item; + struct object *from_one = from->objects[i].item; - if (parse_commit(list[i]) || - list[i]->generation < min_generation) - return 0; + if (!from_one || from_one->flags & assign_flag) + continue; + + from_one = deref_tag(the_repository, from_one, + "a from object", 0); + if (!from_one || from_one->type != OBJ_COMMIT) { + /* no way to tell if this is reachable by + * looking at the ancestry chain alone, so + * leave a note to ourselves not to worry about + * this object anymore. + */ + from->objects[i].item->flags |= assign_flag; + continue; + } + + list[nr_commits] = (struct commit *)from_one; + if (parse_commit(list[nr_commits]) || + list[nr_commits]->generation < min_generation) { + result = 0; + goto cleanup; + } + + nr_commits++; } - QSORT(list, from->nr, compare_commits_by_gen); + QSORT(list, nr_commits, compare_commits_by_gen); - for (i = 0; i < from->nr; i++) { + for (i = 0; i < nr_commits; i++) { /* DFS from list[i] */ struct commit_list *stack = NULL; @@@ -603,10 -622,15 +625,15 @@@ } cleanup: - for (i = 0; i < from->nr; i++) { + for (i = 0; i < nr_commits; i++) { clear_commit_marks(list[i], RESULT); clear_commit_marks(list[i], assign_flag); } + free(list); + + for (i = 0; i < from->nr; i++) + from->objects[i].item->flags &= ~assign_flag; + return result; }