Signed-off-by: Derrick Stolee <dstolee@xxxxxxxxxxxxx> --- commit-reach.c | 52 +++++++++++++++++++++++++++++++++++++++---- commit-reach.h | 4 +++- t/helper/test-reach.c | 7 ++++-- t/t6600-test-reach.sh | 51 +++++++++++++++++++++++++++++++++++++++--- upload-pack.c | 2 +- 5 files changed, 105 insertions(+), 11 deletions(-) diff --git a/commit-reach.c b/commit-reach.c index 44c09669ec..992ad5cdc7 100644 --- a/commit-reach.c +++ b/commit-reach.c @@ -562,14 +562,14 @@ static int reachable(struct commit *from, int with_flag, int assign_flag, time_t return (from->object.flags & assign_flag); } -int can_all_from_reach_with_flag(struct object_array from, +int can_all_from_reach_with_flag(struct object_array *from, int with_flag, int assign_flag, time_t min_commit_date) { int i; - for (i = 0; i < from.nr; i++) { - struct object *from_one = from.objects[i].item; + for (i = 0; i < from->nr; i++) { + struct object *from_one = from->objects[i].item; if (from_one->flags & assign_flag) continue; @@ -580,7 +580,7 @@ int can_all_from_reach_with_flag(struct object_array from, * leave a note to ourselves not to worry about * this object anymore. */ - from.objects[i].item->flags |= assign_flag; + from->objects[i].item->flags |= assign_flag; continue; } if (!reachable((struct commit *)from_one, with_flag, @@ -589,3 +589,47 @@ int can_all_from_reach_with_flag(struct object_array from, } return 1; } + +int can_all_from_reach(struct commit_list *from, struct commit_list *to) +{ + struct object_array from_objs = OBJECT_ARRAY_INIT; + time_t min_commit_date = from->item->date; + struct commit_list *from_iter = from; + struct commit_list *to_iter = to; + int result; + + while (from_iter) { + add_object_array(&from_iter->item->object, NULL, &from_objs); + + if (from_iter->item->date < min_commit_date) + min_commit_date = from_iter->item->date; + + from_iter = from_iter->next; + } + + while (to_iter) { + if (to_iter->item->date < min_commit_date) + min_commit_date = to_iter->item->date; + + to_iter->item->object.flags |= PARENT2; + + to_iter = to_iter->next; + } + + result = can_all_from_reach_with_flag(&from_objs, PARENT2, PARENT1, + min_commit_date); + + while (from) { + clear_commit_marks(from->item, PARENT1); + from = from->next; + } + + while (to) { + clear_commit_marks(to->item, PARENT2); + to = to->next; + } + + object_array_clear(&from_objs); + + return result; +} diff --git a/commit-reach.h b/commit-reach.h index c3da8488eb..8ab06af2eb 100644 --- a/commit-reach.h +++ b/commit-reach.h @@ -27,7 +27,9 @@ int commit_contains(struct ref_filter *filter, struct commit *commit, * the 'with_flag' bit on? Mark the commits in 'from' that can reach * such commits with 'assign_flag'. */ -int can_all_from_reach_with_flag(struct object_array from, int with_flag, +int can_all_from_reach_with_flag(struct object_array *from, int with_flag, int assign_flag, time_t min_commit_date); +int can_all_from_reach(struct commit_list *from, struct commit_list *to); + #endif diff --git a/t/helper/test-reach.c b/t/helper/test-reach.c index d57660af45..88639a2945 100644 --- a/t/helper/test-reach.c +++ b/t/helper/test-reach.c @@ -15,9 +15,9 @@ int cmd__reach(int ac, const char **av) struct strbuf buf = STRBUF_INIT; setup_git_directory(); - get_git_config(default_git_config, 0); + git_config(git_default_config, NULL); - if (argc < 2) + if (ac < 2) exit(1); /* load input data */ @@ -117,6 +117,9 @@ int cmd__reach(int ac, const char **av) printf("%s\n", oid_to_hex(&list->item->object.oid)); list = list->next; } + } else if (!strcmp(av[1], "can_all_from_reach")) { + int result = can_all_from_reach(list_X, list_Y); + printf("%s(X,Y):%d\n", av[1], result); } exit(0); diff --git a/t/t6600-test-reach.sh b/t/t6600-test-reach.sh index 0f60db9c60..ef25e70174 100755 --- a/t/t6600-test-reach.sh +++ b/t/t6600-test-reach.sh @@ -64,7 +64,7 @@ test_expect_success 'ref_newer:miss' ' cat >expect <<- EOF && ref_newer:0 EOF - test_reach_two_modes "ref_newer" + test_reach_two_modes ref_newer ' test_expect_success 'ref_newer:miss' ' @@ -75,7 +75,7 @@ test_expect_success 'ref_newer:miss' ' cat >expect <<- EOF && ref_newer:1 EOF - test_reach_two_modes "ref_newer" + test_reach_two_modes ref_newer ' test_expect_success 'reduce_heads' ' @@ -101,7 +101,52 @@ test_expect_success 'reduce_heads' ' git rev-parse commit-1-10 >>expect && printf "reduce_heads(Y):\n" >>expect && git rev-parse commit-10-10 >>expect && - test_reach_two_modes "reduce_heads" + test_reach_two_modes reduce_heads +' + +test_expect_success 'can_all_from_reach:hit' ' + cat >input <<- EOF && + X:commit-2-10 + X:commit-3-9 + X:commit-4-8 + X:commit-5-7 + X:commit-6-6 + X:commit-7-5 + X:commit-8-4 + X:commit-9-3 + Y:commit-1-9 + Y:commit-2-8 + Y:commit-3-7 + Y:commit-4-6 + Y:commit-5-5 + Y:commit-6-4 + Y:commit-7-3 + Y:commit-8-1 + EOF + printf "can_all_from_reach(X,Y):1\n" >expect && + test_reach_two_modes can_all_from_reach +' + +test_expect_success 'can_all_from_reach:miss' ' + cat >input <<- EOF && + X:commit-2-10 + X:commit-3-9 + X:commit-4-8 + X:commit-5-7 + X:commit-6-6 + X:commit-7-5 + X:commit-8-4 + X:commit-9-3 + Y:commit-1-9 + Y:commit-2-8 + Y:commit-3-7 + Y:commit-4-6 + Y:commit-5-5 + Y:commit-6-4 + Y:commit-8-5 + EOF + printf "can_all_from_reach(X,Y):0\n" >expect && + test_reach_two_modes can_all_from_reach ' test_done diff --git a/upload-pack.c b/upload-pack.c index 7c58cb8f5e..e59fbca257 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -339,7 +339,7 @@ static int ok_to_give_up(void) if (!have_obj.nr) return 0; - return can_all_from_reach_with_flag(want_obj, THEY_HAVE, + return can_all_from_reach_with_flag(&want_obj, THEY_HAVE, COMMON_KNOWN, oldest_have); } -- 2.18.0.118.gd4f65b8d14