зеркало из https://github.com/microsoft/git.git
Merge branch 'hx/negotiator-non-recursive'
The implementation of the default "negotiator", used to find common ancestor over the network for object tranfer, used to be recursive; it was updated to be iterative to conserve stackspace usage. * hx/negotiator-non-recursive: negotiator/skipping: fix some problems in mark_common() negotiator/default: avoid stack overflow
This commit is contained in:
Коммит
e2abfa7212
|
@ -56,30 +56,49 @@ static int clear_marks(const char *refname, const struct object_id *oid,
|
|||
static void mark_common(struct negotiation_state *ns, struct commit *commit,
|
||||
int ancestors_only, int dont_parse)
|
||||
{
|
||||
if (commit != NULL && !(commit->object.flags & COMMON)) {
|
||||
struct object *o = (struct object *)commit;
|
||||
struct prio_queue queue = { NULL };
|
||||
|
||||
if (!ancestors_only)
|
||||
o->flags |= COMMON;
|
||||
if (!commit || (commit->object.flags & COMMON))
|
||||
return;
|
||||
|
||||
prio_queue_put(&queue, commit);
|
||||
if (!ancestors_only) {
|
||||
commit->object.flags |= COMMON;
|
||||
|
||||
if ((commit->object.flags & SEEN) && !(commit->object.flags & POPPED))
|
||||
ns->non_common_revs--;
|
||||
}
|
||||
while ((commit = prio_queue_get(&queue))) {
|
||||
struct object *o = (struct object *)commit;
|
||||
|
||||
if (!(o->flags & SEEN))
|
||||
rev_list_push(ns, commit, SEEN);
|
||||
else {
|
||||
struct commit_list *parents;
|
||||
|
||||
if (!ancestors_only && !(o->flags & POPPED))
|
||||
ns->non_common_revs--;
|
||||
if (!o->parsed && !dont_parse)
|
||||
if (repo_parse_commit(the_repository, commit))
|
||||
return;
|
||||
continue;
|
||||
|
||||
for (parents = commit->parents;
|
||||
parents;
|
||||
parents = parents->next)
|
||||
mark_common(ns, parents->item, 0,
|
||||
dont_parse);
|
||||
parents = parents->next) {
|
||||
struct commit *p = parents->item;
|
||||
|
||||
if (p->object.flags & COMMON)
|
||||
continue;
|
||||
|
||||
p->object.flags |= COMMON;
|
||||
|
||||
if ((p->object.flags & SEEN) && !(p->object.flags & POPPED))
|
||||
ns->non_common_revs--;
|
||||
|
||||
prio_queue_put(&queue, parents->item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clear_prio_queue(&queue);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -86,29 +86,37 @@ static int clear_marks(const char *refname, const struct object_id *oid,
|
|||
}
|
||||
|
||||
/*
|
||||
* Mark this SEEN commit and all its SEEN ancestors as COMMON.
|
||||
* Mark this SEEN commit and all its parsed SEEN ancestors as COMMON.
|
||||
*/
|
||||
static void mark_common(struct data *data, struct commit *seen_commit)
|
||||
{
|
||||
struct prio_queue queue = { NULL };
|
||||
struct commit *c;
|
||||
|
||||
if (seen_commit->object.flags & COMMON)
|
||||
return;
|
||||
|
||||
prio_queue_put(&queue, seen_commit);
|
||||
seen_commit->object.flags |= COMMON;
|
||||
while ((c = prio_queue_get(&queue))) {
|
||||
struct commit_list *p;
|
||||
if (c->object.flags & COMMON)
|
||||
return;
|
||||
c->object.flags |= COMMON;
|
||||
|
||||
if (!(c->object.flags & POPPED))
|
||||
data->non_common_revs--;
|
||||
|
||||
if (!c->object.parsed)
|
||||
return;
|
||||
continue;
|
||||
for (p = c->parents; p; p = p->next) {
|
||||
if (p->item->object.flags & SEEN)
|
||||
prio_queue_put(&queue, p->item);
|
||||
if (!(p->item->object.flags & SEEN) ||
|
||||
(p->item->object.flags & COMMON))
|
||||
continue;
|
||||
|
||||
p->item->object.flags |= COMMON;
|
||||
prio_queue_put(&queue, p->item);
|
||||
}
|
||||
}
|
||||
|
||||
clear_prio_queue(&queue);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Загрузка…
Ссылка в новой задаче