summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@microsoft.com>2014-01-19 01:20:25 -0800
committerEdward Thomson <ethomson@microsoft.com>2014-01-20 17:15:12 -0500
commit6b92c99bcbf32de131754a4f750278f84bf5b766 (patch)
treed926d73f374fa89f2a343a601c87cabbc6d4b7f6 /src
parentc1d648c5c6361edfb1aa85a31656b628672c7616 (diff)
downloadlibgit2-6b92c99bcbf32de131754a4f750278f84bf5b766.tar.gz
Don't try to merge binary files
Diffstat (limited to 'src')
-rw-r--r--src/checkout.c47
-rw-r--r--src/merge.c43
-rw-r--r--src/merge.h2
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 */