Skip to content

Commit cc9c952

Browse files
authored
Merge pull request libgit2#4606 from libgit2/cmn/revwalk-iteration
revwalk: avoid walking the entire history when output is unsorted
2 parents 96882f2 + ff98fec commit cc9c952

File tree

2 files changed

+44
-10
lines changed

2 files changed

+44
-10
lines changed

src/revwalk.c

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include "merge.h"
1616
#include "vector.h"
1717

18+
static int get_revision(git_commit_list_node **out, git_revwalk *walk, git_commit_list **list);
19+
1820
git_commit_list_node *git_revwalk__commit_lookup(
1921
git_revwalk *walk, const git_oid *oid)
2022
{
@@ -76,10 +78,12 @@ static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting,
7678
if (commit->uninteresting)
7779
return 0;
7880

79-
if (uninteresting)
81+
if (uninteresting) {
82+
walk->limited = 1;
8083
walk->did_hide = 1;
81-
else
84+
} else {
8285
walk->did_push = 1;
86+
}
8387

8488
commit->uninteresting = uninteresting;
8589
list = walk->user_input;
@@ -245,34 +249,34 @@ static int revwalk_next_timesort(git_commit_list_node **object_out, git_revwalk
245249

246250
static int revwalk_next_unsorted(git_commit_list_node **object_out, git_revwalk *walk)
247251
{
252+
int error;
248253
git_commit_list_node *next;
249254

250-
while ((next = git_commit_list_pop(&walk->iterator_rand)) != NULL) {
255+
while (!(error = get_revision(&next, walk, &walk->iterator_rand))) {
251256
/* Some commits might become uninteresting after being added to the list */
252257
if (!next->uninteresting) {
253258
*object_out = next;
254259
return 0;
255260
}
256261
}
257262

258-
giterr_clear();
259-
return GIT_ITEROVER;
263+
return error;
260264
}
261265

262266
static int revwalk_next_toposort(git_commit_list_node **object_out, git_revwalk *walk)
263267
{
268+
int error;
264269
git_commit_list_node *next;
265270

266-
while ((next = git_commit_list_pop(&walk->iterator_topo)) != NULL) {
271+
while (!(error = get_revision(&next, walk, &walk->iterator_topo))) {
267272
/* Some commits might become uninteresting after being added to the list */
268273
if (!next->uninteresting) {
269274
*object_out = next;
270275
return 0;
271276
}
272277
}
273278

274-
giterr_clear();
275-
return GIT_ITEROVER;
279+
return error;
276280
}
277281

278282
static int revwalk_next_reverse(git_commit_list_node **object_out, git_revwalk *walk)
@@ -434,6 +438,30 @@ static int limit_list(git_commit_list **out, git_revwalk *walk, git_commit_list
434438
return 0;
435439
}
436440

441+
static int get_revision(git_commit_list_node **out, git_revwalk *walk, git_commit_list **list)
442+
{
443+
int error;
444+
git_commit_list_node *commit;
445+
446+
commit = git_commit_list_pop(list);
447+
if (!commit) {
448+
giterr_clear();
449+
return GIT_ITEROVER;
450+
}
451+
452+
/*
453+
* If we did not run limit_list and we must add parents to the
454+
* list ourselves.
455+
*/
456+
if (!walk->limited) {
457+
if ((error = add_parents_to_list(walk, commit, list)) < 0)
458+
return error;
459+
}
460+
461+
*out = commit;
462+
return 0;
463+
}
464+
437465
static int sort_in_topological_order(git_commit_list **out, git_revwalk *walk, git_commit_list *list)
438466
{
439467
git_commit_list *ll = NULL, *newlist, **pptr;
@@ -546,7 +574,7 @@ static int prepare_walk(git_revwalk *walk)
546574
}
547575
}
548576

549-
if ((error = limit_list(&commits, walk, commits)) < 0)
577+
if (walk->limited && (error = limit_list(&commits, walk, commits)) < 0)
550578
return error;
551579

552580
if (walk->sorting & GIT_SORT_TOPOLOGICAL) {
@@ -649,6 +677,9 @@ void git_revwalk_sorting(git_revwalk *walk, unsigned int sort_mode)
649677
walk->get_next = &revwalk_next_unsorted;
650678
walk->enqueue = &revwalk_enqueue_unsorted;
651679
}
680+
681+
if (sort_mode != GIT_SORT_NONE)
682+
walk->limited = 1;
652683
}
653684

654685
void git_revwalk_simplify_first_parent(git_revwalk *walk)
@@ -704,6 +735,7 @@ void git_revwalk_reset(git_revwalk *walk)
704735
git_commit_list_free(&walk->user_input);
705736
walk->first_parent = 0;
706737
walk->walking = 0;
738+
walk->limited = 0;
707739
walk->did_push = walk->did_hide = 0;
708740
}
709741

@@ -725,6 +757,7 @@ int git_revwalk_add_hide_cb(
725757

726758
walk->hide_cb = hide_cb;
727759
walk->hide_cb_payload = payload;
760+
walk->limited = 1;
728761

729762
return 0;
730763
}

src/revwalk.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ struct git_revwalk {
3636
unsigned walking:1,
3737
first_parent: 1,
3838
did_hide: 1,
39-
did_push: 1;
39+
did_push: 1,
40+
limited: 1;
4041
unsigned int sorting;
4142

4243
/* the pushes and hides */

0 commit comments

Comments
 (0)