Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/libgit2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell Belfer <rb@github.com>2013-06-14 02:37:06 +0400
committerRussell Belfer <rb@github.com>2013-06-17 21:03:49 +0400
commit351888cf3dc3c3525faccb010adcf5c130ac5b16 (patch)
tree7501c0a9fb6889c50ccacbb79c6ec977dcfbc242 /src/diff.c
parenta3e8dbb40b87f66e1f5f4d1730f9989805822db0 (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.c80
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;
}