diff options
author | Russell Belfer <rb@github.com> | 2013-11-01 22:39:37 +0400 |
---|---|---|
committer | Russell Belfer <rb@github.com> | 2013-11-01 22:39:37 +0400 |
commit | e7c85120eab6c942d15c0f5ed3a2c8b6ec667617 (patch) | |
tree | d23cf50f11f9ee7bd9fabf6fc5b5fd92d1b53824 /src/diff_tform.c | |
parent | a5c16f3cfb92f1129ef13124fc70147480141d69 (diff) |
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.
Diffstat (limited to 'src/diff_tform.c')
-rw-r--r-- | src/diff_tform.c | 57 |
1 files changed, 43 insertions, 14 deletions
diff --git a/src/diff_tform.c b/src/diff_tform.c index 0aec754a4..28a9cc70d 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -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++; } |