diff options
author | Russell Belfer <rb@github.com> | 2013-06-14 02:37:06 +0400 |
---|---|---|
committer | Russell Belfer <rb@github.com> | 2013-06-17 21:03:49 +0400 |
commit | 351888cf3dc3c3525faccb010adcf5c130ac5b16 (patch) | |
tree | 7501c0a9fb6889c50ccacbb79c6ec977dcfbc242 /src/diff.c | |
parent | a3e8dbb40b87f66e1f5f4d1730f9989805822db0 (diff) |
Improve case handling in git_diff__paired_foreach
This commit reinstates some changes to git_diff__paired_foreach
that were discarded during the rebase (because the diff_output.c
file had gone away), and also adjusts the case insensitively
logic slightly to hopefully deal with either mismatched icase
diffs and other case insensitivity scenarios.
Diffstat (limited to 'src/diff.c')
-rw-r--r-- | src/diff.c | 80 |
1 files changed, 57 insertions, 23 deletions
diff --git a/src/diff.c b/src/diff.c index feb77b59b..87189a49c 100644 --- a/src/diff.c +++ b/src/diff.c @@ -254,6 +254,13 @@ int git_diff_delta__cmp(const void *a, const void *b) return val ? val : ((int)da->status - (int)db->status); } +int git_diff_delta__casecmp(const void *a, const void *b) +{ + const git_diff_delta *da = a, *db = b; + int val = strcasecmp(diff_delta__path(da), diff_delta__path(db)); + return val ? val : ((int)da->status - (int)db->status); +} + bool git_diff_delta__should_skip( const git_diff_options *opts, const git_diff_delta *delta) { @@ -1197,51 +1204,78 @@ size_t git_diff_num_deltas_of_type(git_diff_list *diff, git_delta_t type) } int git_diff__paired_foreach( - git_diff_list *idx2head, - git_diff_list *wd2idx, - int (*cb)(git_diff_delta *i2h, git_diff_delta *w2i, void *payload), + git_diff_list *head2idx, + git_diff_list *idx2wd, + int (*cb)(git_diff_delta *h2i, git_diff_delta *i2w, void *payload), void *payload) { int cmp; - git_diff_delta *i2h, *w2i; + git_diff_delta *h2i, *i2w; size_t i, j, i_max, j_max; - int (*strcomp)(const char *, const char *); - - i_max = idx2head ? idx2head->deltas.length : 0; - j_max = wd2idx ? wd2idx->deltas.length : 0; + int (*strcomp)(const char *, const char *) = git__strcmp; + bool icase_mismatch; - /* Get appropriate strcmp function */ - strcomp = idx2head ? idx2head->strcomp : wd2idx ? wd2idx->strcomp : NULL; + i_max = head2idx ? head2idx->deltas.length : 0; + j_max = idx2wd ? idx2wd->deltas.length : 0; - /* Assert both iterators use matching ignore-case. If this function ever - * supports merging diffs that are not sorted by the same function, then - * it will need to spool and sort on one of the results before merging - */ - if (idx2head && wd2idx) { - assert(idx2head->strcomp == wd2idx->strcomp); + /* 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. + */ + icase_mismatch = + (head2idx != NULL && idx2wd != NULL && + ((head2idx->opts.flags ^ idx2wd->opts.flags) & GIT_DIFF_DELTAS_ARE_ICASE)); + + /* force case-sensitive delta sort */ + if (icase_mismatch) { + if (head2idx->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) { + head2idx->deltas._cmp = git_diff_delta__cmp; + git_vector_sort(&head2idx->deltas); + } else { + idx2wd->deltas._cmp = git_diff_delta__cmp; + git_vector_sort(&idx2wd->deltas); + } } + else if (head2idx->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) + strcomp = git__strcasecmp; for (i = 0, j = 0; i < i_max || j < j_max; ) { - i2h = idx2head ? GIT_VECTOR_GET(&idx2head->deltas,i) : NULL; - w2i = wd2idx ? GIT_VECTOR_GET(&wd2idx->deltas,j) : NULL; + h2i = head2idx ? GIT_VECTOR_GET(&head2idx->deltas, i) : NULL; + i2w = idx2wd ? GIT_VECTOR_GET(&idx2wd->deltas, j) : NULL; - cmp = !w2i ? -1 : !i2h ? 1 : - strcomp(i2h->old_file.path, w2i->old_file.path); + cmp = !i2w ? -1 : !h2i ? 1 : + strcomp(h2i->new_file.path, i2w->old_file.path); if (cmp < 0) { - if (cb(i2h, NULL, payload)) + if (cb(h2i, NULL, payload)) return GIT_EUSER; i++; } else if (cmp > 0) { - if (cb(NULL, w2i, payload)) + if (cb(NULL, i2w, payload)) return GIT_EUSER; j++; } else { - if (cb(i2h, w2i, payload)) + if (cb(h2i, i2w, payload)) return GIT_EUSER; i++; j++; } } + /* restore case-insensitive delta sort */ + if (icase_mismatch) { + if (head2idx->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) { + head2idx->deltas._cmp = git_diff_delta__casecmp; + git_vector_sort(&head2idx->deltas); + } else { + idx2wd->deltas._cmp = git_diff_delta__casecmp; + git_vector_sort(&idx2wd->deltas); + } + } + return 0; } |