Skip to content

Commit 2f503ee

Browse files
committed
Merge branch 'jt/skipping-negotiator-wo-recursion'
Rewrite a deep recursion in the skipping negotiator to use a loop with on-heap prio queue to avoid stack wastage. * jt/skipping-negotiator-wo-recursion: negotiator/skipping: avoid stack overflow
2 parents 1e230df + 4654134 commit 2f503ee

File tree

1 file changed

+17
-12
lines changed

1 file changed

+17
-12
lines changed

negotiator/skipping.c

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -86,21 +86,26 @@ static int clear_marks(const char *refname, const struct object_id *oid,
8686
/*
8787
* Mark this SEEN commit and all its SEEN ancestors as COMMON.
8888
*/
89-
static void mark_common(struct data *data, struct commit *c)
89+
static void mark_common(struct data *data, struct commit *seen_commit)
9090
{
91-
struct commit_list *p;
91+
struct prio_queue queue = { NULL };
92+
struct commit *c;
9293

93-
if (c->object.flags & COMMON)
94-
return;
95-
c->object.flags |= COMMON;
96-
if (!(c->object.flags & POPPED))
97-
data->non_common_revs--;
94+
prio_queue_put(&queue, seen_commit);
95+
while ((c = prio_queue_get(&queue))) {
96+
struct commit_list *p;
97+
if (c->object.flags & COMMON)
98+
return;
99+
c->object.flags |= COMMON;
100+
if (!(c->object.flags & POPPED))
101+
data->non_common_revs--;
98102

99-
if (!c->object.parsed)
100-
return;
101-
for (p = c->parents; p; p = p->next) {
102-
if (p->item->object.flags & SEEN)
103-
mark_common(data, p->item);
103+
if (!c->object.parsed)
104+
return;
105+
for (p = c->parents; p; p = p->next) {
106+
if (p->item->object.flags & SEEN)
107+
prio_queue_put(&queue, p->item);
108+
}
104109
}
105110
}
106111

0 commit comments

Comments
 (0)