summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/checkout.c47
-rw-r--r--src/merge.c43
-rw-r--r--src/merge.h2
-rw-r--r--tests/merge/workdir/simple.c37
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/11/aeee27ac45a8402c2fd5b875d66dd844e5df00bin0 -> 51 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/1c/51d885170f57a0c4e8c69ff6363d91a5b51f85bin0 -> 30 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/23/ed141a6ae1e798b2f721afedbe947c119111babin0 -> 30 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/34/8dcd41e2b467991578e92bedd16971b877ef1ebin0 -> 51 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/6e/3b9eb35214d4e31ed5789afc7d520ac798ce55bin0 -> 51 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/83/6b8b82b26cab22eaaed8820877c76d6c8bca19bin0 -> 30 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/ad/01aebfdf2ac13145efafe3f9fcf798882f1730bin0 -> 158 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/cc/338e4710c9b257106b8d16d82f86458d5beaf12
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/d7/308cc367b2cc23f710834ec1fd8ffbacf1b4601
13 files changed, 130 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 */
diff --git a/tests/merge/workdir/simple.c b/tests/merge/workdir/simple.c
index 2142fc4f9..d4f387a26 100644
--- a/tests/merge/workdir/simple.c
+++ b/tests/merge/workdir/simple.c
@@ -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);
+}
diff --git a/tests/resources/merge-resolve/.gitted/objects/11/aeee27ac45a8402c2fd5b875d66dd844e5df00 b/tests/resources/merge-resolve/.gitted/objects/11/aeee27ac45a8402c2fd5b875d66dd844e5df00
new file mode 100644
index 000000000..90e729f6d
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/11/aeee27ac45a8402c2fd5b875d66dd844e5df00
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/1c/51d885170f57a0c4e8c69ff6363d91a5b51f85 b/tests/resources/merge-resolve/.gitted/objects/1c/51d885170f57a0c4e8c69ff6363d91a5b51f85
new file mode 100644
index 000000000..9a21e26c0
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/1c/51d885170f57a0c4e8c69ff6363d91a5b51f85
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/23/ed141a6ae1e798b2f721afedbe947c119111ba b/tests/resources/merge-resolve/.gitted/objects/23/ed141a6ae1e798b2f721afedbe947c119111ba
new file mode 100644
index 000000000..06dee3b23
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/23/ed141a6ae1e798b2f721afedbe947c119111ba
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/34/8dcd41e2b467991578e92bedd16971b877ef1e b/tests/resources/merge-resolve/.gitted/objects/34/8dcd41e2b467991578e92bedd16971b877ef1e
new file mode 100644
index 000000000..fd61b6ce5
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/34/8dcd41e2b467991578e92bedd16971b877ef1e
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/6e/3b9eb35214d4e31ed5789afc7d520ac798ce55 b/tests/resources/merge-resolve/.gitted/objects/6e/3b9eb35214d4e31ed5789afc7d520ac798ce55
new file mode 100644
index 000000000..c6100cb01
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/6e/3b9eb35214d4e31ed5789afc7d520ac798ce55
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/83/6b8b82b26cab22eaaed8820877c76d6c8bca19 b/tests/resources/merge-resolve/.gitted/objects/83/6b8b82b26cab22eaaed8820877c76d6c8bca19
new file mode 100644
index 000000000..99f828649
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/83/6b8b82b26cab22eaaed8820877c76d6c8bca19
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/ad/01aebfdf2ac13145efafe3f9fcf798882f1730 b/tests/resources/merge-resolve/.gitted/objects/ad/01aebfdf2ac13145efafe3f9fcf798882f1730
new file mode 100644
index 000000000..ae3ef8ce3
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/ad/01aebfdf2ac13145efafe3f9fcf798882f1730
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/cc/338e4710c9b257106b8d16d82f86458d5beaf1 b/tests/resources/merge-resolve/.gitted/objects/cc/338e4710c9b257106b8d16d82f86458d5beaf1
new file mode 100644
index 000000000..85b3b8112
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/cc/338e4710c9b257106b8d16d82f86458d5beaf1
@@ -0,0 +1,2 @@
+xK!]s3`bo1 gpWEGmx]6d
+eaΉ碵z.Dv [hD[JﱶwX[.2nuVƉZڳF!x88GPP_?KN \ No newline at end of file
diff --git a/tests/resources/merge-resolve/.gitted/objects/d7/308cc367b2cc23f710834ec1fd8ffbacf1b460 b/tests/resources/merge-resolve/.gitted/objects/d7/308cc367b2cc23f710834ec1fd8ffbacf1b460
new file mode 100644
index 000000000..b02cda4fa
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/d7/308cc367b2cc23f710834ec1fd8ffbacf1b460
@@ -0,0 +1 @@
+xK @]s)Ё7 ]I(x{ ^,nлSo`/X)ٙB@GÔaD 4xwlCv?-79d,hF4Z ;ƝH}= \ No newline at end of file