Skip to content

Commit cc280db

Browse files
spkrkagitster
authored andcommitted
commit-reach: remove get_reachable_subset()
get_reachable_subset() and tips_reachable_from_bases() answer the same question: given a set of bases and a set of tips, which tips are reachable from at least one base? get_reachable_subset() was introduced in fcb2c07 (2018-11-02) for add_missing_tags() in remote.c. tips_reachable_from_bases() was added in cbfe360 (2023-03-20) as part of the ahead-behind series. The two were never consolidated. With a commit-graph, tips_reachable_from_bases() can have an edge: its DFS raises the generation floor as lower targets are found, pruning more aggressively than the static floor in get_reachable_subset(). Without generation numbers, some edge cases may be slower with DFS instead of BFS since the date-ordered prio_queue naturally stays near the top of the graph, but this should not matter in practice -- worst case both visit the full graph down from the bases. The flag in remote.c changes from 1 (bit 0) to TMP_MARK (bit 4) because tips_reachable_from_bases() uses SEEN (bit 0) internally. TMP_MARK is already used for deduplication earlier in the same function and is cleared before the reachability check. Signed-off-by: Kristofer Karlsson <krka@spotify.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 1ff279f commit cc280db

5 files changed

Lines changed: 36 additions & 126 deletions

File tree

commit-reach.c

Lines changed: 0 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,79 +1013,6 @@ int can_all_from_reach(struct commit_list *from, struct commit_list *to,
10131013
return result;
10141014
}
10151015

1016-
struct commit_list *get_reachable_subset(struct commit **from, size_t nr_from,
1017-
struct commit **to, size_t nr_to,
1018-
unsigned int reachable_flag)
1019-
{
1020-
struct commit **item;
1021-
struct commit *current;
1022-
struct commit_list *found_commits = NULL;
1023-
struct commit **to_last = to + nr_to;
1024-
struct commit **from_last = from + nr_from;
1025-
timestamp_t min_generation = GENERATION_NUMBER_INFINITY;
1026-
int num_to_find = 0;
1027-
1028-
struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
1029-
1030-
for (item = to; item < to_last; item++) {
1031-
timestamp_t generation;
1032-
struct commit *c = *item;
1033-
1034-
repo_parse_commit(the_repository, c);
1035-
generation = commit_graph_generation(c);
1036-
if (generation < min_generation)
1037-
min_generation = generation;
1038-
1039-
if (!(c->object.flags & PARENT1)) {
1040-
c->object.flags |= PARENT1;
1041-
num_to_find++;
1042-
}
1043-
}
1044-
1045-
for (item = from; item < from_last; item++) {
1046-
struct commit *c = *item;
1047-
if (!(c->object.flags & PARENT2)) {
1048-
c->object.flags |= PARENT2;
1049-
repo_parse_commit(the_repository, c);
1050-
1051-
prio_queue_put(&queue, *item);
1052-
}
1053-
}
1054-
1055-
while (num_to_find && (current = prio_queue_get(&queue)) != NULL) {
1056-
struct commit_list *parents;
1057-
1058-
if (current->object.flags & PARENT1) {
1059-
current->object.flags &= ~PARENT1;
1060-
current->object.flags |= reachable_flag;
1061-
commit_list_insert(current, &found_commits);
1062-
num_to_find--;
1063-
}
1064-
1065-
for (parents = current->parents; parents; parents = parents->next) {
1066-
struct commit *p = parents->item;
1067-
1068-
repo_parse_commit(the_repository, p);
1069-
1070-
if (commit_graph_generation(p) < min_generation)
1071-
continue;
1072-
1073-
if (p->object.flags & PARENT2)
1074-
continue;
1075-
1076-
p->object.flags |= PARENT2;
1077-
prio_queue_put(&queue, p);
1078-
}
1079-
}
1080-
1081-
clear_prio_queue(&queue);
1082-
1083-
clear_commit_marks_many(nr_to, to, PARENT1);
1084-
clear_commit_marks_many(nr_from, from, PARENT2);
1085-
1086-
return found_commits;
1087-
}
1088-
10891016
define_commit_slab(bit_arrays, struct bitmap *);
10901017
static struct bit_arrays bit_arrays;
10911018

commit-reach.h

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -96,19 +96,6 @@ int can_all_from_reach_with_flag(struct object_array *from,
9696
int can_all_from_reach(struct commit_list *from, struct commit_list *to,
9797
int commit_date_cutoff);
9898

99-
100-
/*
101-
* Return a list of commits containing the commits in the 'to' array
102-
* that are reachable from at least one commit in the 'from' array.
103-
* Also add the given 'flag' to each of the commits in the returned list.
104-
*
105-
* This method uses the PARENT1 and PARENT2 flags during its operation,
106-
* so be sure these flags are not set before calling the method.
107-
*/
108-
struct commit_list *get_reachable_subset(struct commit **from, size_t nr_from,
109-
struct commit **to, size_t nr_to,
110-
unsigned int reachable_flag);
111-
11299
struct ahead_behind_count {
113100
/**
114101
* As input, the *_index members indicate which positions in

remote.c

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1459,9 +1459,8 @@ static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***ds
14591459
* sent to the other side.
14601460
*/
14611461
if (sent_tips.nr) {
1462-
const int reachable_flag = 1;
1463-
struct commit_list *found_commits;
14641462
struct commit_stack src_commits = COMMIT_STACK_INIT;
1463+
struct commit_list *bases = NULL;
14651464

14661465
for_each_string_list_item(item, &src_tag) {
14671466
struct ref *ref = item->util;
@@ -1479,11 +1478,12 @@ static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***ds
14791478
commit_stack_push(&src_commits, commit);
14801479
}
14811480

1482-
found_commits = get_reachable_subset(sent_tips.items,
1483-
sent_tips.nr,
1484-
src_commits.items,
1485-
src_commits.nr,
1486-
reachable_flag);
1481+
for (size_t i = 0; i < sent_tips.nr; i++)
1482+
commit_list_insert(sent_tips.items[i], &bases);
1483+
tips_reachable_from_bases(the_repository,
1484+
bases, src_commits.items,
1485+
src_commits.nr, TMP_MARK);
1486+
commit_list_free(bases);
14871487

14881488
for_each_string_list_item(item, &src_tag) {
14891489
struct ref *dst_ref;
@@ -1503,7 +1503,7 @@ static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***ds
15031503
* Is this tag, which they do not have, reachable from
15041504
* any of the commits we are sending?
15051505
*/
1506-
if (!(commit->object.flags & reachable_flag))
1506+
if (!(commit->object.flags & TMP_MARK))
15071507
continue;
15081508

15091509
/* Add it in */
@@ -1513,9 +1513,8 @@ static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***ds
15131513
}
15141514

15151515
clear_commit_marks_many(src_commits.nr, src_commits.items,
1516-
reachable_flag);
1516+
TMP_MARK);
15171517
commit_stack_clear(&src_commits);
1518-
commit_list_free(found_commits);
15191518
}
15201519

15211520
string_list_clear(&src_tag, 0);

t/helper/test-reach.c

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "hex.h"
88
#include "object-name.h"
99
#include "ref-filter.h"
10+
#include "revision.h"
1011
#include "setup.h"
1112
#include "string-list.h"
1213
#include "tag.h"
@@ -149,30 +150,26 @@ int cmd__reach(int ac, const char **av)
149150

150151
printf("%s(_,A,X,_):%d\n", av[1], commit_contains(&filter, A, X, &cache));
151152
clear_contains_cache(&cache);
152-
} else if (!strcmp(av[1], "get_reachable_subset")) {
153-
const int reachable_flag = 1;
154-
int count = 0;
155-
struct commit_list *current;
156-
struct commit_list *list = get_reachable_subset(X_stack.items, X_stack.nr,
157-
Y_stack.items, Y_stack.nr,
158-
reachable_flag);
159-
printf("get_reachable_subset(X,Y)\n");
160-
for (current = list; current; current = current->next) {
161-
if (!(list->item->object.flags & reachable_flag))
162-
die(_("commit %s is not marked reachable"),
163-
oid_to_hex(&list->item->object.oid));
164-
count++;
165-
}
153+
} else if (!strcmp(av[1], "tips_reachable_from_bases")) {
154+
struct commit_list *bases = NULL;
155+
struct commit_list *result = NULL;
156+
157+
for (size_t i = 0; i < X_stack.nr; i++)
158+
commit_list_insert(X_stack.items[i], &bases);
159+
tips_reachable_from_bases(the_repository,
160+
bases, Y_stack.items,
161+
Y_stack.nr, TMP_MARK);
162+
commit_list_free(bases);
163+
164+
printf("tips_reachable_from_bases(X,Y)\n");
166165
for (size_t i = 0; i < Y_stack.nr; i++) {
167-
if (Y_stack.items[i]->object.flags & reachable_flag)
168-
count--;
166+
if (Y_stack.items[i]->object.flags & TMP_MARK)
167+
commit_list_insert(Y_stack.items[i], &result);
169168
}
169+
print_sorted_commit_ids(result);
170170

171-
if (count < 0)
172-
die(_("too many commits marked reachable"));
173-
174-
print_sorted_commit_ids(list);
175-
commit_list_free(list);
171+
clear_commit_marks_many(Y_stack.nr, Y_stack.items, TMP_MARK);
172+
commit_list_free(result);
176173
}
177174

178175
object_array_clear(&X_obj);

t/t6600-test-reach.sh

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ test_expect_success 'rev-list: symmetric difference topo-order' '
391391
run_all_modes git rev-list --topo-order commit-3-8...commit-6-6
392392
'
393393

394-
test_expect_success 'get_reachable_subset:all' '
394+
test_expect_success 'tips_reachable_from_bases:all' '
395395
cat >input <<-\EOF &&
396396
X:commit-9-1
397397
X:commit-8-3
@@ -403,15 +403,15 @@ test_expect_success 'get_reachable_subset:all' '
403403
Y:commit-5-6
404404
EOF
405405
(
406-
echo "get_reachable_subset(X,Y)" &&
406+
echo "tips_reachable_from_bases(X,Y)" &&
407407
git rev-parse commit-3-3 \
408408
commit-1-7 \
409409
commit-5-6 | sort
410410
) >expect &&
411-
test_all_modes get_reachable_subset
411+
test_all_modes tips_reachable_from_bases
412412
'
413413

414-
test_expect_success 'get_reachable_subset:some' '
414+
test_expect_success 'tips_reachable_from_bases:some' '
415415
cat >input <<-\EOF &&
416416
X:commit-9-1
417417
X:commit-8-3
@@ -422,14 +422,14 @@ test_expect_success 'get_reachable_subset:some' '
422422
Y:commit-5-6
423423
EOF
424424
(
425-
echo "get_reachable_subset(X,Y)" &&
425+
echo "tips_reachable_from_bases(X,Y)" &&
426426
git rev-parse commit-3-3 \
427427
commit-1-7 | sort
428428
) >expect &&
429-
test_all_modes get_reachable_subset
429+
test_all_modes tips_reachable_from_bases
430430
'
431431

432-
test_expect_success 'get_reachable_subset:none' '
432+
test_expect_success 'tips_reachable_from_bases:none' '
433433
cat >input <<-\EOF &&
434434
X:commit-9-1
435435
X:commit-8-3
@@ -439,8 +439,8 @@ test_expect_success 'get_reachable_subset:none' '
439439
Y:commit-7-6
440440
Y:commit-2-8
441441
EOF
442-
echo "get_reachable_subset(X,Y)" >expect &&
443-
test_all_modes get_reachable_subset
442+
echo "tips_reachable_from_bases(X,Y)" >expect &&
443+
test_all_modes tips_reachable_from_bases
444444
'
445445

446446
test_expect_success 'for-each-ref ahead-behind:linear' '

0 commit comments

Comments
 (0)