mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-25 01:37:09 +00:00
revwalk: use merge bases to speed up processing
There is no need walk down the parents of a merge base to mark them as uninteresting because we'll never see them. Calculate the merge bases in prepare_walk() so mark_uninteresting() can stop at a merge base instead of walking all the way to the root.
This commit is contained in:
parent
de7ab85dc6
commit
2c4ef1dd0d
@ -59,6 +59,10 @@ struct git_revwalk {
|
|||||||
|
|
||||||
unsigned walking:1;
|
unsigned walking:1;
|
||||||
unsigned int sorting;
|
unsigned int sorting;
|
||||||
|
|
||||||
|
/* merge base calculation */
|
||||||
|
commit_object *one;
|
||||||
|
git_vector twos;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int commit_time_cmp(void *a, void *b)
|
static int commit_time_cmp(void *a, void *b)
|
||||||
@ -341,6 +345,7 @@ static int merge_bases_many(commit_list **out, git_revwalk *walk, commit_object
|
|||||||
}
|
}
|
||||||
|
|
||||||
commit_list_free(&list);
|
commit_list_free(&list);
|
||||||
|
|
||||||
/* filter out any stale commits in the results */
|
/* filter out any stale commits in the results */
|
||||||
list = result;
|
list = result;
|
||||||
result = NULL;
|
result = NULL;
|
||||||
@ -409,6 +414,10 @@ static void mark_uninteresting(commit_object *commit)
|
|||||||
|
|
||||||
commit->uninteresting = 1;
|
commit->uninteresting = 1;
|
||||||
|
|
||||||
|
/* This means we've reached a merge base, so there's no need to walk any more */
|
||||||
|
if ((commit->flags & (RESULT | STALE)) == RESULT)
|
||||||
|
return;
|
||||||
|
|
||||||
for (i = 0; i < commit->out_degree; ++i)
|
for (i = 0; i < commit->out_degree; ++i)
|
||||||
if (!commit->parents[i]->uninteresting)
|
if (!commit->parents[i]->uninteresting)
|
||||||
mark_uninteresting(commit->parents[i]);
|
mark_uninteresting(commit->parents[i]);
|
||||||
@ -452,7 +461,15 @@ static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting)
|
|||||||
if (commit == NULL)
|
if (commit == NULL)
|
||||||
return git__throw(GIT_ENOTFOUND, "Failed to push commit. Object not found");
|
return git__throw(GIT_ENOTFOUND, "Failed to push commit. Object not found");
|
||||||
|
|
||||||
return process_commit(walk, commit, uninteresting);
|
commit->uninteresting = uninteresting;
|
||||||
|
if (walk->one == NULL && !uninteresting) {
|
||||||
|
walk->one = commit;
|
||||||
|
} else {
|
||||||
|
if (git_vector_insert(&walk->twos, commit) < GIT_SUCCESS)
|
||||||
|
return GIT_ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_revwalk_push(git_revwalk *walk, const git_oid *oid)
|
int git_revwalk_push(git_revwalk *walk, const git_oid *oid)
|
||||||
@ -666,7 +683,25 @@ static int revwalk_next_reverse(commit_object **object_out, git_revwalk *walk)
|
|||||||
static int prepare_walk(git_revwalk *walk)
|
static int prepare_walk(git_revwalk *walk)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
commit_object *next;
|
unsigned int i;
|
||||||
|
commit_object *next, *two;
|
||||||
|
commit_list *bases = NULL;
|
||||||
|
|
||||||
|
/* first figure out what the merge bases are */
|
||||||
|
error = merge_bases_many(&bases, walk, walk->one, &walk->twos);
|
||||||
|
if (error < GIT_SUCCESS)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
commit_list_free(&bases);
|
||||||
|
error = process_commit(walk, walk->one, walk->one->uninteresting);
|
||||||
|
if (error < GIT_SUCCESS)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
git_vector_foreach(&walk->twos, i, two) {
|
||||||
|
error = process_commit(walk, two, two->uninteresting);
|
||||||
|
if (error < GIT_SUCCESS)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
if (walk->sorting & GIT_SORT_TOPOLOGICAL) {
|
if (walk->sorting & GIT_SORT_TOPOLOGICAL) {
|
||||||
unsigned short i;
|
unsigned short i;
|
||||||
@ -729,6 +764,7 @@ int git_revwalk_new(git_revwalk **revwalk_out, git_repository *repo)
|
|||||||
|
|
||||||
git_pqueue_init(&walk->iterator_time, 8, commit_time_cmp);
|
git_pqueue_init(&walk->iterator_time, 8, commit_time_cmp);
|
||||||
git_vector_init(&walk->memory_alloc, 8, NULL);
|
git_vector_init(&walk->memory_alloc, 8, NULL);
|
||||||
|
git_vector_init(&walk->twos, 4, NULL);
|
||||||
alloc_chunk(walk);
|
alloc_chunk(walk);
|
||||||
|
|
||||||
walk->get_next = &revwalk_next_unsorted;
|
walk->get_next = &revwalk_next_unsorted;
|
||||||
@ -772,6 +808,7 @@ void git_revwalk_free(git_revwalk *walk)
|
|||||||
git__free(git_vector_get(&walk->memory_alloc, i));
|
git__free(git_vector_get(&walk->memory_alloc, i));
|
||||||
|
|
||||||
git_vector_free(&walk->memory_alloc);
|
git_vector_free(&walk->memory_alloc);
|
||||||
|
git_vector_free(&walk->twos);
|
||||||
git__free(walk);
|
git__free(walk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user