Commit 3940310e by Russell Belfer

Fix some of the glaring errors in GIT_DIFF_REVERSE

These changes fix the basic problem with GIT_DIFF_REVERSE being
broken for text diffs.  The reversed diff entries were getting
added to the git_diff correctly, but some of the metadata was kept
incorrectly in a way that prevented the text diffs from being
generated correctly.  Once I fixed that, it became clear that it
was not possible to merge reversed diffs correctly.  This has a
first pass at fixing that problem.  We probably need more tests
to make sure that is really fixed thoroughly.
parent 567649f2
...@@ -448,6 +448,13 @@ static int diff_list_apply_options( ...@@ -448,6 +448,13 @@ static int diff_list_apply_options(
/* add other defaults here */ /* add other defaults here */
} }
/* Reverse src info if diff is reversed */
if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_REVERSE)) {
git_iterator_type_t tmp_src = diff->old_src;
diff->old_src = diff->new_src;
diff->new_src = tmp_src;
}
/* if ignore_submodules not explicitly set, check diff config */ /* if ignore_submodules not explicitly set, check diff config */
if (diff->opts.ignore_submodules <= 0) { if (diff->opts.ignore_submodules <= 0) {
const char *str; const char *str;
...@@ -484,9 +491,9 @@ static int diff_list_apply_options( ...@@ -484,9 +491,9 @@ static int diff_list_apply_options(
return -1; return -1;
if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_REVERSE)) { if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_REVERSE)) {
const char *swap = diff->opts.old_prefix; const char *tmp_prefix = diff->opts.old_prefix;
diff->opts.old_prefix = diff->opts.new_prefix; diff->opts.old_prefix = diff->opts.new_prefix;
diff->opts.new_prefix = swap; diff->opts.new_prefix = tmp_prefix;
} }
return 0; return 0;
......
...@@ -46,7 +46,10 @@ fail: ...@@ -46,7 +46,10 @@ fail:
} }
static git_diff_delta *diff_delta__merge_like_cgit( static git_diff_delta *diff_delta__merge_like_cgit(
const git_diff_delta *a, const git_diff_delta *b, git_pool *pool) uint16_t flags,
const git_diff_delta *a,
const git_diff_delta *b,
git_pool *pool)
{ {
git_diff_delta *dup; git_diff_delta *dup;
...@@ -112,26 +115,28 @@ int git_diff_merge( ...@@ -112,26 +115,28 @@ int git_diff_merge(
if (!from->deltas.length) if (!from->deltas.length)
return 0; return 0;
if ((onto->opts.flags & GIT_DIFF_IGNORE_CASE) !=
(from->opts.flags & GIT_DIFF_IGNORE_CASE) ||
(onto->opts.flags & GIT_DIFF_REVERSE) !=
(from->opts.flags & GIT_DIFF_REVERSE))
{
giterr_set(GITERR_INVALID,
"Attempt to merge diffs created with conflicting options");
return -1;
}
if (git_vector_init( if (git_vector_init(
&onto_new, onto->deltas.length, git_diff_delta__cmp) < 0 || &onto_new, onto->deltas.length, git_diff_delta__cmp) < 0 ||
git_pool_init(&onto_pool, 1, 0) < 0) git_pool_init(&onto_pool, 1, 0) < 0)
return -1; return -1;
if ((onto->opts.flags & GIT_DIFF_IGNORE_CASE) != 0 || ignore_case = ((onto->opts.flags & GIT_DIFF_IGNORE_CASE) != 0);
(from->opts.flags & GIT_DIFF_IGNORE_CASE) != 0)
{
ignore_case = true;
/* This function currently only supports merging diff lists that
* are sorted identically. */
assert((onto->opts.flags & GIT_DIFF_IGNORE_CASE) != 0 &&
(from->opts.flags & GIT_DIFF_IGNORE_CASE) != 0);
}
for (i = 0, j = 0; i < onto->deltas.length || j < from->deltas.length; ) { for (i = 0, j = 0; i < onto->deltas.length || j < from->deltas.length; ) {
git_diff_delta *o = GIT_VECTOR_GET(&onto->deltas, i); git_diff_delta *o = GIT_VECTOR_GET(&onto->deltas, i);
const git_diff_delta *f = GIT_VECTOR_GET(&from->deltas, j); const git_diff_delta *f = GIT_VECTOR_GET(&from->deltas, j);
int cmp = !f ? -1 : !o ? 1 : STRCMP_CASESELECT(ignore_case, o->old_file.path, f->old_file.path); int cmp = !f ? -1 : !o ? 1 :
STRCMP_CASESELECT(ignore_case, o->old_file.path, f->old_file.path);
if (cmp < 0) { if (cmp < 0) {
delta = diff_delta__dup(o, &onto_pool); delta = diff_delta__dup(o, &onto_pool);
...@@ -140,7 +145,8 @@ int git_diff_merge( ...@@ -140,7 +145,8 @@ int git_diff_merge(
delta = diff_delta__dup(f, &onto_pool); delta = diff_delta__dup(f, &onto_pool);
j++; j++;
} else { } else {
delta = diff_delta__merge_like_cgit(o, f, &onto_pool); delta = diff_delta__merge_like_cgit(
onto->opts.flags, o, f, &onto_pool);
i++; i++;
j++; j++;
} }
...@@ -160,6 +166,10 @@ int git_diff_merge( ...@@ -160,6 +166,10 @@ int git_diff_merge(
if (!error) { if (!error) {
git_vector_swap(&onto->deltas, &onto_new); git_vector_swap(&onto->deltas, &onto_new);
git_pool_swap(&onto->pool, &onto_pool); git_pool_swap(&onto->pool, &onto_pool);
if ((onto->opts.flags & GIT_DIFF_REVERSE) != 0)
onto->old_src = from->old_src;
else
onto->new_src = from->new_src; onto->new_src = from->new_src;
/* prefix strings also come from old pool, so recreate those.*/ /* prefix strings also come from old pool, so recreate those.*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment