From: Junio C Hamano <gitster@pobox.com>
To: git@vger.kernel.org
Subject: [PATCH v3 13/19] apply: plug the three-way merge logic in
Date: Wed, 13 Jun 2012 12:32:54 -0700 [thread overview]
Message-ID: <1339615980-19727-14-git-send-email-gitster@pobox.com> (raw)
In-Reply-To: <1339615980-19727-1-git-send-email-gitster@pobox.com>
When a patch does not apply to what we have, but we know the preimage the
patch was made against, we apply the patch to the preimage to compute what
the patch author wanted the result to look like, and attempt a three-way
merge between the result and our version, using the intended preimage as
the base version.
When we are applying the patch using the index, we would additionally need
to add the object names of these three blobs involved in the merge, which
is not yet done in this step, but we add a field to "struct patch" so that
later write-out step can use it.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
builtin/apply.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 53 insertions(+), 6 deletions(-)
diff --git a/builtin/apply.c b/builtin/apply.c
index 6936588..5ef8652 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -16,6 +16,8 @@
#include "dir.h"
#include "diff.h"
#include "parse-options.h"
+#include "xdiff-interface.h"
+#include "ll-merge.h"
/*
* --check turns on checking that the working tree matches the
@@ -194,12 +196,16 @@ struct patch {
unsigned int is_copy:1;
unsigned int is_rename:1;
unsigned int recount:1;
+ unsigned int conflicted_threeway:1;
struct fragment *fragments;
char *result;
size_t resultsize;
char old_sha1_prefix[41];
char new_sha1_prefix[41];
struct patch *next;
+
+ /* three-way fallback result */
+ unsigned char threeway_stage[3][20];
};
static void free_fragment_list(struct fragment *list)
@@ -3142,11 +3148,33 @@ static int load_preimage(struct image *image,
static int three_way_merge(struct image *image,
char *path,
- unsigned char *base,
- unsigned char *ours,
- unsigned char *theirs)
+ const unsigned char *base,
+ const unsigned char *ours,
+ const unsigned char *theirs)
{
- return -1; /* for now */
+ mmfile_t base_file, our_file, their_file;
+ mmbuffer_t result = { NULL };
+ int status;
+
+ read_mmblob(&base_file, base);
+ read_mmblob(&our_file, ours);
+ read_mmblob(&their_file, theirs);
+ status = ll_merge(&result, path,
+ &base_file, "base",
+ &our_file, "ours",
+ &their_file, "theirs", NULL);
+ free(base_file.ptr);
+ free(our_file.ptr);
+ free(their_file.ptr);
+ if (status < 0 || !result.ptr) {
+ free(result.ptr);
+ return -1;
+ }
+ clear_image(image);
+ image->buf = result.ptr;
+ image->len = result.size;
+
+ return status;
}
static int try_threeway(struct image *image, struct patch *patch,
@@ -3155,6 +3183,7 @@ static int try_threeway(struct image *image, struct patch *patch,
unsigned char pre_sha1[20], post_sha1[20], our_sha1[20];
struct strbuf buf = STRBUF_INIT;
size_t len;
+ int status;
char *img;
struct image tmp_image;
@@ -3167,6 +3196,9 @@ static int try_threeway(struct image *image, struct patch *patch,
if (get_sha1(patch->old_sha1_prefix, pre_sha1) ||
read_blob_object(&buf, pre_sha1, patch->old_mode))
return error("repository lacks the necessary blob to fall back on 3-way merge.");
+
+ fprintf(stderr, "Falling back to three-way merge...\n");
+
img = strbuf_detach(&buf, &len);
prepare_image(&tmp_image, img, len, 1);
/* Apply the patch to get the post image */
@@ -3186,8 +3218,23 @@ static int try_threeway(struct image *image, struct patch *patch,
clear_image(&tmp_image);
/* in-core three-way merge between post and our using pre as base */
- return three_way_merge(image,
- patch->new_name, pre_sha1, our_sha1, post_sha1);
+ status = three_way_merge(image, patch->new_name,
+ pre_sha1, our_sha1, post_sha1);
+ if (status < 0) {
+ fprintf(stderr, "Failed to fall back on three-way merge...\n");
+ return status;
+ }
+
+ if (status) {
+ patch->conflicted_threeway = 1;
+ hashcpy(patch->threeway_stage[0], pre_sha1);
+ hashcpy(patch->threeway_stage[1], our_sha1);
+ hashcpy(patch->threeway_stage[2], post_sha1);
+ fprintf(stderr, "Applied patch to '%s' with conflicts.\n", patch->new_name);
+ } else {
+ fprintf(stderr, "Applied patch to '%s' cleanly.\n", patch->new_name);
+ }
+ return 0;
}
static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *ce)
--
1.7.11.rc3.30.g3bdace2
next prev parent reply other threads:[~2012-06-13 19:33 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-06-13 19:32 [PATCH v3 00/19] "git apply --3way" Junio C Hamano
2012-06-13 19:32 ` [PATCH v3 01/19] apply: fix an incomplete comment in check_patch() Junio C Hamano
2012-06-13 19:32 ` [PATCH v3 02/19] apply: a bit more comments on PATH_TO_BE_DELETED Junio C Hamano
2012-06-13 19:32 ` [PATCH v3 03/19] apply: clear_image() clears things a bit more Junio C Hamano
2012-06-13 19:32 ` [PATCH v3 04/19] apply: refactor read_file_or_gitlink() Junio C Hamano
2012-06-13 19:32 ` [PATCH v3 05/19] apply: factor out checkout_target() helper function Junio C Hamano
2012-06-13 19:32 ` [PATCH v3 06/19] apply: split load_preimage() helper function out Junio C Hamano
2012-06-13 19:32 ` [PATCH v3 07/19] apply: refactor "previous patch" logic Junio C Hamano
2012-06-13 19:32 ` [PATCH v3 08/19] apply: further split load_preimage() Junio C Hamano
2012-06-13 19:32 ` [PATCH v3 09/19] apply: move check_to_create_blob() closer to its sole caller Junio C Hamano
2012-06-13 19:32 ` [PATCH v3 10/19] apply: move "already exists" logic to check_to_create() Junio C Hamano
2012-06-13 19:32 ` [PATCH v3 11/19] apply: accept -3/--3way command line option Junio C Hamano
2012-06-13 19:32 ` [PATCH v3 12/19] apply: fall back on three-way merge Junio C Hamano
2012-06-13 19:32 ` Junio C Hamano [this message]
2012-06-13 19:32 ` [PATCH v3 14/19] apply: move verify_index_match() higher Junio C Hamano
2012-06-13 19:32 ` [PATCH v3 15/19] apply: --3way with add/add conflict Junio C Hamano
2012-06-13 19:32 ` [PATCH v3 16/19] apply: register conflicted stages to the index Junio C Hamano
2012-06-13 19:32 ` [PATCH v3 17/19] apply: allow rerere() upon --3way results Junio C Hamano
2012-06-13 19:32 ` [PATCH v3 18/19] apply: document --3way option Junio C Hamano
2012-06-13 19:33 ` [PATCH v3 19/19] apply --3way: tests Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1339615980-19727-14-git-send-email-gitster@pobox.com \
--to=gitster@pobox.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).