Commit 6b92c99b by Edward Thomson

Don't try to merge binary files

parent c1d648c5
......@@ -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)
......
......@@ -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;
......
......@@ -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 */
......
......@@ -489,3 +489,40 @@ void test_merge_workdir_simple__unrelated_with_conflicts(void)
git_merge_result_free(result);
}
void test_merge_workdir_simple__binary(void)
{
git_oid our_oid, their_oid, our_file_oid;
git_commit *our_commit;
git_merge_head *their_head;
git_merge_result *result;
const git_index_entry *binary_entry;
git_merge_opts opts = GIT_MERGE_OPTS_INIT;
struct merge_index_entry merge_index_entries[] = {
{ 0100644, "1c51d885170f57a0c4e8c69ff6363d91a5b51f85", 1, "binary" },
{ 0100644, "23ed141a6ae1e798b2f721afedbe947c119111ba", 2, "binary" },
{ 0100644, "836b8b82b26cab22eaaed8820877c76d6c8bca19", 3, "binary" },
};
cl_git_pass(git_oid_fromstr(&our_oid, "cc338e4710c9b257106b8d16d82f86458d5beaf1"));
cl_git_pass(git_oid_fromstr(&their_oid, "ad01aebfdf2ac13145efafe3f9fcf798882f1730"));
cl_git_pass(git_commit_lookup(&our_commit, repo, &our_oid));
cl_git_pass(git_reset(repo, (git_object *)our_commit, GIT_RESET_HARD));
cl_git_pass(git_merge_head_from_oid(&their_head, repo, &their_oid));
cl_git_pass(git_merge(&result, repo, (const git_merge_head **)&their_head, 1, &opts));
cl_assert(merge_test_index(repo_index, merge_index_entries, 3));
cl_git_pass(git_index_add_bypath(repo_index, "binary"));
cl_assert((binary_entry = git_index_get_bypath(repo_index, "binary", 0)) != NULL);
cl_git_pass(git_oid_fromstr(&our_file_oid, "23ed141a6ae1e798b2f721afedbe947c119111ba"));
cl_assert(git_oid_cmp(&binary_entry->oid, &our_file_oid) == 0);
git_merge_head_free(their_head);
git_merge_result_free(result);
git_commit_free(our_commit);
}
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