in src/diff_generate.c [1543:1629]
int git_diff__paired_foreach(
git_diff *head2idx,
git_diff *idx2wd,
int (*cb)(git_diff_delta *h2i, git_diff_delta *i2w, void *payload),
void *payload)
{
int cmp, error = 0;
git_diff_delta *h2i, *i2w;
size_t i, j, i_max, j_max;
int (*strcomp)(const char *, const char *) = git__strcmp;
bool h2i_icase, i2w_icase, icase_mismatch;
i_max = head2idx ? head2idx->deltas.length : 0;
j_max = idx2wd ? idx2wd->deltas.length : 0;
if (!i_max && !j_max)
return 0;
/* At some point, tree-to-index diffs will probably never ignore case,
* even if that isn't true now. Index-to-workdir diffs may or may not
* ignore case, but the index filename for the idx2wd diff should
* still be using the canonical case-preserving name.
*
* Therefore the main thing we need to do here is make sure the diffs
* are traversed in a compatible order. To do this, we temporarily
* resort a mismatched diff to get the order correct.
*
* In order to traverse renames in the index->workdir, we need to
* ensure that we compare the index name on both sides, so we
* always sort by the old name in the i2w list.
*/
h2i_icase = head2idx != NULL && git_diff_is_sorted_icase(head2idx);
i2w_icase = idx2wd != NULL && git_diff_is_sorted_icase(idx2wd);
icase_mismatch =
(head2idx != NULL && idx2wd != NULL && h2i_icase != i2w_icase);
if (icase_mismatch && h2i_icase) {
git_vector_set_cmp(&head2idx->deltas, git_diff_delta__cmp);
git_vector_sort(&head2idx->deltas);
}
if (i2w_icase && !icase_mismatch) {
strcomp = git__strcasecmp;
git_vector_set_cmp(&idx2wd->deltas, git_diff_delta__i2w_casecmp);
git_vector_sort(&idx2wd->deltas);
} else if (idx2wd != NULL) {
git_vector_set_cmp(&idx2wd->deltas, git_diff_delta__i2w_cmp);
git_vector_sort(&idx2wd->deltas);
}
for (i = 0, j = 0; i < i_max || j < j_max; ) {
h2i = head2idx ? GIT_VECTOR_GET(&head2idx->deltas, i) : NULL;
i2w = idx2wd ? GIT_VECTOR_GET(&idx2wd->deltas, j) : NULL;
cmp = !i2w ? -1 : !h2i ? 1 :
strcomp(h2i->new_file.path, i2w->old_file.path);
if (cmp < 0) {
i++; i2w = NULL;
} else if (cmp > 0) {
j++; h2i = NULL;
} else {
i++; j++;
}
if ((error = cb(h2i, i2w, payload)) != 0) {
git_error_set_after_callback(error);
break;
}
}
/* restore case-insensitive delta sort */
if (icase_mismatch && h2i_icase) {
git_vector_set_cmp(&head2idx->deltas, git_diff_delta__casecmp);
git_vector_sort(&head2idx->deltas);
}
/* restore idx2wd sort by new path */
if (idx2wd != NULL) {
git_vector_set_cmp(&idx2wd->deltas,
i2w_icase ? git_diff_delta__casecmp : git_diff_delta__cmp);
git_vector_sort(&idx2wd->deltas);
}
return error;
}