Skip to content

Commit b64edf6

Browse files
committed
commit-graph: Introduce git_commit_list_generation_cmp
This change makes calculations of merge-bases a bit faster when there are complex graphs and the commit times cause visiting nodes multiple times. This is done by visiting the nodes in the graph in reverse generation order when the generation number is available instead of commit timestamp. If the generation number is missing in any pair of commits, it can safely fall back to the old heuristic with no negative side-effects. Part of: libgit2#5757
1 parent 846745a commit b64edf6

File tree

4 files changed

+21
-2
lines changed

4 files changed

+21
-2
lines changed

src/commit_list.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,24 @@
1212
#include "odb.h"
1313
#include "commit.h"
1414

15+
int git_commit_list_generation_cmp(const void *a, const void *b)
16+
{
17+
uint32_t generation_a = ((git_commit_list_node *) a)->generation;
18+
uint32_t generation_b = ((git_commit_list_node *) b)->generation;
19+
20+
if (!generation_a || !generation_b) {
21+
/* Fall back to comparing by timestamps if at least one commit lacks a generation. */
22+
return git_commit_list_time_cmp(a, b);
23+
}
24+
25+
if (generation_a < generation_b)
26+
return 1;
27+
if (generation_a > generation_b)
28+
return -1;
29+
30+
return 0;
31+
}
32+
1533
int git_commit_list_time_cmp(const void *a, const void *b)
1634
{
1735
int64_t time_a = ((git_commit_list_node *) a)->time;

src/commit_list.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ typedef struct git_commit_list {
4646
} git_commit_list;
4747

4848
git_commit_list_node *git_commit_list_alloc_node(git_revwalk *walk);
49+
int git_commit_list_generation_cmp(const void *a, const void *b);
4950
int git_commit_list_time_cmp(const void *a, const void *b);
5051
void git_commit_list_free(git_commit_list **list_p);
5152
git_commit_list *git_commit_list_insert(git_commit_list_node *item, git_commit_list **list_p);

src/graph.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ static int mark_parents(git_revwalk *walk, git_commit_list_node *one,
4343
return 0;
4444
}
4545

46-
if (git_pqueue_init(&list, 0, 2, git_commit_list_time_cmp) < 0)
46+
if (git_pqueue_init(&list, 0, 2, git_commit_list_generation_cmp) < 0)
4747
return -1;
4848

4949
if (git_commit_list_parse(walk, one) < 0)

src/merge.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ static int paint_down_to_common(
387387
int error;
388388
unsigned int i;
389389

390-
if (git_pqueue_init(&list, 0, twos->length * 2, git_commit_list_time_cmp) < 0)
390+
if (git_pqueue_init(&list, 0, twos->length * 2, git_commit_list_generation_cmp) < 0)
391391
return -1;
392392

393393
one->flags |= PARENT1;

0 commit comments

Comments
 (0)