diff --git a/commit-reach.c b/commit-reach.c index d806291d5d..940fbf2e17 100644 --- a/commit-reach.c +++ b/commit-reach.c @@ -595,3 +595,50 @@ 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, + int cutoff_by_min_date) +{ + struct object_array from_objs = OBJECT_ARRAY_INIT; + time_t min_commit_date = cutoff_by_min_date ? from->item->date : 0; + struct commit_list *from_iter = from, *to_iter = to; + int result; + + while (from_iter) { + add_object_array(&from_iter->item->object, NULL, &from_objs); + + if (!parse_commit(from_iter->item)) { + if (from_iter->item->date < min_commit_date) + min_commit_date = from_iter->item->date; + } + + from_iter = from_iter->next; + } + + while (to_iter) { + if (!parse_commit(to_iter->item)) { + 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 b28bc22fcd..aa202c9703 100644 --- a/commit-reach.h +++ b/commit-reach.h @@ -72,5 +72,7 @@ int can_all_from_reach_with_flag(struct object_array *from, unsigned int with_flag, unsigned int assign_flag, time_t min_commit_date); +int can_all_from_reach(struct commit_list *from, struct commit_list *to, + int commit_date_cutoff); #endif diff --git a/t/helper/test-reach.c b/t/helper/test-reach.c index e32e193b70..c79729cac0 100644 --- a/t/helper/test-reach.c +++ b/t/helper/test-reach.c @@ -29,7 +29,7 @@ int cmd__reach(int ac, const char **av) { struct object_id oid_A, oid_B; struct commit *A, *B; - struct commit_list *X; + struct commit_list *X, *Y; struct commit **X_array; int X_nr, X_alloc; struct strbuf buf = STRBUF_INIT; @@ -41,7 +41,7 @@ int cmd__reach(int ac, const char **av) exit(1); A = B = NULL; - X = NULL; + X = Y = NULL; X_nr = 0; X_alloc = 16; ALLOC_ARRAY(X_array, X_alloc); @@ -86,6 +86,10 @@ int cmd__reach(int ac, const char **av) X_array[X_nr++] = c; break; + case 'Y': + commit_list_insert(c, &Y); + break; + default: die("unexpected start of line: %c", buf.buf[0]); } @@ -106,6 +110,8 @@ int cmd__reach(int ac, const char **av) struct commit_list *list = reduce_heads(X); printf("%s(X):\n", av[1]); print_sorted_commit_ids(list); + } else if (!strcmp(av[1], "can_all_from_reach")) { + printf("%s(X,Y):%d\n", av[1], can_all_from_reach(X, Y, 1)); } exit(0); diff --git a/t/t6600-test-reach.sh b/t/t6600-test-reach.sh index 17c6467988..e41eb397a7 100755 --- a/t/t6600-test-reach.sh +++ b/t/t6600-test-reach.sh @@ -160,4 +160,49 @@ test_expect_success 'reduce_heads' ' test_three_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 + echo "can_all_from_reach(X,Y):1" >expect && + test_three_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 + echo "can_all_from_reach(X,Y):0" >expect && + test_three_modes can_all_from_reach +' + test_done