commit-reach: replace ref_newer logic

The ref_newer method is used by 'git push' to check if a force-push is required. This method does not use any kind of cutoff when walking, so in the case of a force-push will walk all reachable commits. The is_descendant_of method already uses paint_down_to_common along with cutoffs. By translating the ref_newer arguments into the commit and commit_list required by is_descendant_of, we can have one fewer commit walk and also improve our performance! For a copy of the Linux repository, 'test-tool reach ref_newer' presents the following improvements with the specified input. In the case that ref_newer returns 1, there is no improvement. The improvement is in the second case where ref_newer returns 0. Input: A:v4.9 B:v3.19 Before: 0.09 s After: 0.09 s To test the negative case, add a new commit with parent v3.19, regenerate the commit-graph, and then run with B pointing at that commit. Before: 0.43 s After: 0.09 s Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Derrick Stolee committed Jul 20, 2018 at 16:33 UTC 1e3497a24cf13fe907b247d1b93a997d6537cca1
1 file changed +3 -23
commit-reach.c
+3 -23
@@ -366,20 +366,11 @@ void reduce_heads_replace(struct commit_list **heads)
366 *heads = result;
367 }
368
369 -static void unmark_and_free(struct commit_list *list, unsigned int mark)
370 -{
371 - while (list) {
372 - struct commit *commit = pop_commit(&list);
373 - commit->object.flags &= ~mark;
374 - }
375 -}
376 -
369 int ref_newer(const struct object_id *new_oid, const struct object_id *old_oid)
370 {
371 struct object *o;
372 struct commit *old_commit, *new_commit;
381 - struct commit_list *list, *used;
382 - int found = 0;
373 + struct commit_list *old_commit_list = NULL;
374
375 /*
376 * Both new_commit and old_commit must be commit-ish and new_commit is descendant of
@@ -400,19 +391,8 @@ int ref_newer(const struct object_id *new_oid, const struct object_id *old_oid)
391 if (parse_commit(new_commit) < 0)
392 return 0;
393
403 - used = list = NULL;
404 - commit_list_insert(new_commit, &list);
405 - while (list) {
406 - new_commit = pop_most_recent_commit(&list, TMP_MARK);
407 - commit_list_insert(new_commit, &used);
408 - if (new_commit == old_commit) {
409 - found = 1;
410 - break;
411 - }
412 - }
413 - unmark_and_free(list, TMP_MARK);
414 - unmark_and_free(used, TMP_MARK);
415 - return found;
394 + commit_list_insert(old_commit, &old_commit_list);
395 + return is_descendant_of(new_commit, old_commit_list);
396 }
397
398 /*