mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-30 16:43:16 +00:00
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.
This commit is contained in:
parent
567649f2ad
commit
3940310e29
11
src/diff.c
11
src/diff.c
@ -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(
|
|||||||
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:
|
|||||||
}
|
}
|
||||||
|
|
||||||
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(
|
|||||||
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(
|
|||||||
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(
|
|||||||
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.*/
|
||||||
|
Loading…
Reference in New Issue
Block a user