diff options
author | Edward Thomson <ethomson@microsoft.com> | 2014-01-19 01:20:25 -0800 |
---|---|---|
committer | Edward Thomson <ethomson@microsoft.com> | 2014-01-20 17:15:12 -0500 |
commit | 6b92c99bcbf32de131754a4f750278f84bf5b766 (patch) | |
tree | d926d73f374fa89f2a343a601c87cabbc6d4b7f6 /src | |
parent | c1d648c5c6361edfb1aa85a31656b628672c7616 (diff) | |
download | libgit2-6b92c99bcbf32de131754a4f750278f84bf5b766.tar.gz |
Don't try to merge binary files
Diffstat (limited to 'src')
-rw-r--r-- | src/checkout.c | 47 | ||||
-rw-r--r-- | src/merge.c | 43 | ||||
-rw-r--r-- | src/merge.h | 2 |
3 files changed, 90 insertions, 2 deletions
diff --git a/src/checkout.c b/src/checkout.c index cc49800a2..f64aa9a77 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -70,7 +70,8 @@ typedef struct { int name_collision:1, directoryfile:1, - one_to_two:1; + one_to_two:1, + binary:1; } checkout_conflictdata; static int checkout_notify( @@ -681,6 +682,40 @@ GIT_INLINE(bool) conflict_pathspec_match( return false; } +GIT_INLINE(int) checkout_conflict_detect_binary(git_repository *repo, checkout_conflictdata *conflict) +{ + git_blob *ancestor_blob = NULL, *our_blob = NULL, *their_blob = NULL; + int error = 0; + + if (conflict->ancestor) { + if ((error = git_blob_lookup(&ancestor_blob, repo, &conflict->ancestor->oid)) < 0) + goto done; + + conflict->binary = git_blob_is_binary(ancestor_blob); + } + + if (!conflict->binary && conflict->ours) { + if ((error = git_blob_lookup(&our_blob, repo, &conflict->ours->oid)) < 0) + goto done; + + conflict->binary = git_blob_is_binary(our_blob); + } + + if (!conflict->binary && conflict->theirs) { + if ((error = git_blob_lookup(&their_blob, repo, &conflict->theirs->oid)) < 0) + goto done; + + conflict->binary = git_blob_is_binary(their_blob); + } + +done: + git_blob_free(ancestor_blob); + git_blob_free(our_blob); + git_blob_free(their_blob); + + return error; +} + static int checkout_conflicts_load(checkout_data *data, git_iterator *workdir, git_vector *pathspec) { git_index_conflict_iterator *iterator = NULL; @@ -705,6 +740,9 @@ static int checkout_conflicts_load(checkout_data *data, git_iterator *workdir, g conflict->ours = ours; conflict->theirs = theirs; + if ((error = checkout_conflict_detect_binary(data->repo, conflict)) < 0) + goto done; + git_vector_insert(&data->conflicts, conflict); } @@ -1706,6 +1744,7 @@ static int checkout_create_conflicts(checkout_data *data) int error = 0; git_vector_foreach(&data->conflicts, i, conflict) { + /* Both deleted: nothing to do */ if (conflict->ours == NULL && conflict->theirs == NULL) error = 0; @@ -1749,7 +1788,11 @@ static int checkout_create_conflicts(checkout_data *data) else if (S_ISLNK(conflict->theirs->mode)) error = checkout_write_entry(data, conflict, conflict->ours); - else + /* If any side is binary, write the ours side */ + else if (conflict->binary) + error = checkout_write_entry(data, conflict, conflict->ours); + + else if (!error) error = checkout_write_merge(data, conflict); if (error) diff --git a/src/merge.c b/src/merge.c index 3ac9167e3..124befc14 100644 --- a/src/merge.c +++ b/src/merge.c @@ -551,6 +551,10 @@ static int merge_conflict_resolve_automerge( strcmp(conflict->ancestor_entry.path, conflict->their_entry.path) != 0) return 0; + /* Reject binary conflicts */ + if (conflict->binary) + return 0; + if ((error = git_repository_odb(&odb, diff_list->repo)) < 0 || (error = git_merge_file_input_from_index_entry(&ancestor, diff_list->repo, &conflict->ancestor_entry)) < 0 || (error = git_merge_file_input_from_index_entry(&ours, diff_list->repo, &conflict->our_entry)) < 0 || @@ -1150,6 +1154,44 @@ GIT_INLINE(int) merge_diff_detect_type( return 0; } +GIT_INLINE(int) merge_diff_detect_binary( + git_repository *repo, + git_merge_diff *conflict) +{ + git_blob *ancestor_blob = NULL, *our_blob = NULL, *their_blob = NULL; + int error = 0; + + if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry)) { + if ((error = git_blob_lookup(&ancestor_blob, repo, &conflict->ancestor_entry.oid)) < 0) + goto done; + + conflict->binary = git_blob_is_binary(ancestor_blob); + } + + if (!conflict->binary && + GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry)) { + if ((error = git_blob_lookup(&our_blob, repo, &conflict->our_entry.oid)) < 0) + goto done; + + conflict->binary = git_blob_is_binary(our_blob); + } + + if (!conflict->binary && + GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry)) { + if ((error = git_blob_lookup(&their_blob, repo, &conflict->their_entry.oid)) < 0) + goto done; + + conflict->binary = git_blob_is_binary(their_blob); + } + +done: + git_blob_free(ancestor_blob); + git_blob_free(our_blob); + git_blob_free(their_blob); + + return error; +} + GIT_INLINE(int) index_entry_dup( git_index_entry *out, git_pool *pool, @@ -1221,6 +1263,7 @@ static int merge_diff_list_insert_conflict( if ((conflict = merge_diff_from_index_entries(diff_list, tree_items)) == NULL || merge_diff_detect_type(conflict) < 0 || merge_diff_detect_df_conflict(merge_df_data, conflict) < 0 || + merge_diff_detect_binary(diff_list->repo, conflict) < 0 || git_vector_insert(&diff_list->conflicts, conflict) < 0) return -1; diff --git a/src/merge.h b/src/merge.h index b240f6c44..dda023528 100644 --- a/src/merge.h +++ b/src/merge.h @@ -106,6 +106,8 @@ typedef struct { git_index_entry their_entry; git_delta_t their_status; + + int binary:1; } git_merge_diff; /** Internal structure for merge inputs */ |