diff options
author | Junio C Hamano <gitster@pobox.com> | 2018-09-24 19:30:52 +0200 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2018-09-24 19:30:52 +0200 |
commit | 0f7ac90dbe7ecf511883b7aae84acbb698418f60 (patch) | |
tree | a148890ca8d5886932b96963aa5bb567e7d5974f /commit-reach.c | |
parent | Merge branch 'nd/attr-pathspec-fix' (diff) | |
parent | commit-reach: fix memory and flag leaks (diff) | |
download | git-0f7ac90dbe7ecf511883b7aae84acbb698418f60.tar.xz git-0f7ac90dbe7ecf511883b7aae84acbb698418f60.zip |
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
Diffstat (limited to 'commit-reach.c')
-rw-r--r-- | commit-reach.c | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/commit-reach.c b/commit-reach.c index 622eeb313d..00e5ceee6f 100644 --- a/commit-reach.c +++ b/commit-reach.c @@ -547,20 +547,42 @@ int can_all_from_reach_with_flag(struct object_array *from, { 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 +625,15 @@ int can_all_from_reach_with_flag(struct object_array *from, } 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; } |