Commit e7c85120 by Russell Belfer

More tests and fixed for merging reversed diffs

There were a lot more cases to deal with to make sure that our
merged (i.e. workdir-to-tree-to-index) diffs were matching the
output of core Git.
parent a5c16f3c
......@@ -46,7 +46,6 @@ fail:
}
static git_diff_delta *diff_delta__merge_like_cgit(
uint16_t flags,
const git_diff_delta *a,
const git_diff_delta *b,
git_pool *pool)
......@@ -99,15 +98,46 @@ static git_diff_delta *diff_delta__merge_like_cgit(
return dup;
}
int git_diff_merge(
git_diff *onto,
const git_diff *from)
static git_diff_delta *diff_delta__merge_like_cgit_reversed(
const git_diff_delta *a,
const git_diff_delta *b,
git_pool *pool)
{
git_diff_delta *dup;
/* reversed version of above logic */
if (a->status == GIT_DELTA_UNMODIFIED)
return diff_delta__dup(b, pool);
if ((dup = diff_delta__dup(a, pool)) == NULL)
return NULL;
if (b->status == GIT_DELTA_UNMODIFIED || b->status == GIT_DELTA_UNTRACKED)
return dup;
if (dup->status == GIT_DELTA_DELETED) {
if (b->status == GIT_DELTA_ADDED)
dup->status = GIT_DELTA_UNMODIFIED;
} else {
dup->status = b->status;
}
git_oid_cpy(&dup->old_file.oid, &b->old_file.oid);
dup->old_file.mode = b->old_file.mode;
dup->old_file.size = b->old_file.size;
dup->old_file.flags = b->old_file.flags;
return dup;
}
int git_diff_merge(git_diff *onto, const git_diff *from)
{
int error = 0;
git_pool onto_pool;
git_vector onto_new;
git_diff_delta *delta;
bool ignore_case = false;
bool ignore_case, reversed;
unsigned int i, j;
assert(onto && from);
......@@ -115,11 +145,11 @@ int git_diff_merge(
if (!from->deltas.length)
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))
{
ignore_case = ((onto->opts.flags & GIT_DIFF_IGNORE_CASE) != 0);
reversed = ((onto->opts.flags & GIT_DIFF_REVERSE) != 0);
if (ignore_case != ((from->opts.flags & GIT_DIFF_IGNORE_CASE) != 0) ||
reversed != ((from->opts.flags & GIT_DIFF_REVERSE) != 0)) {
giterr_set(GITERR_INVALID,
"Attempt to merge diffs created with conflicting options");
return -1;
......@@ -130,8 +160,6 @@ int git_diff_merge(
git_pool_init(&onto_pool, 1, 0) < 0)
return -1;
ignore_case = ((onto->opts.flags & GIT_DIFF_IGNORE_CASE) != 0);
for (i = 0, j = 0; i < onto->deltas.length || j < from->deltas.length; ) {
git_diff_delta *o = GIT_VECTOR_GET(&onto->deltas, i);
const git_diff_delta *f = GIT_VECTOR_GET(&from->deltas, j);
......@@ -145,8 +173,9 @@ int git_diff_merge(
delta = diff_delta__dup(f, &onto_pool);
j++;
} else {
delta = diff_delta__merge_like_cgit(
onto->opts.flags, o, f, &onto_pool);
delta = reversed ?
diff_delta__merge_like_cgit_reversed(o, f, &onto_pool) :
diff_delta__merge_like_cgit(o, f, &onto_pool);
i++;
j++;
}
......
......@@ -196,6 +196,38 @@ void test_diff_workdir__to_tree(void)
git_diff_free(diff);
/* Let's try that once more with a reversed diff */
opts.flags |= GIT_DIFF_REVERSE;
cl_git_pass(git_diff_tree_to_index(&diff, g_repo, b, NULL, &opts));
cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, NULL, &opts));
cl_git_pass(git_diff_merge(diff, diff2));
git_diff_free(diff2);
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(16, exp.files);
cl_assert_equal_i(5, exp.file_status[GIT_DELTA_DELETED]);
cl_assert_equal_i(4, exp.file_status[GIT_DELTA_ADDED]);
cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]);
cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]);
cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]);
cl_assert_equal_i(12, exp.hunks);
cl_assert_equal_i(19, exp.lines);
cl_assert_equal_i(3, exp.line_ctxt);
cl_assert_equal_i(12, exp.line_dels);
cl_assert_equal_i(4, exp.line_adds);
git_diff_free(diff);
/* all done now */
git_tree_free(a);
git_tree_free(b);
}
......
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