From: Elijah Newren <newren@gmail.com>
To: Junio C Hamano <gitster@pobox.com>
Cc: Git Mailing List <git@vger.kernel.org>,
lilinchao@oschina.cn, Jerry Zhang <jerry@skydio.com>
Subject: Re: [PATCH v2] apply: resolve trivial merge without hitting ll-merge with "--3way"
Date: Mon, 6 Sep 2021 11:57:34 -0700 [thread overview]
Message-ID: <CABPp-BGrg7eBCeq7SLvx3N5p7HyKGwS7qwTe=+En6OfiKhiXPQ@mail.gmail.com> (raw)
In-Reply-To: <20210905190657.2906699-1-gitster@pobox.com>
On Sun, Sep 5, 2021 at 12:07 PM Junio C Hamano <gitster@pobox.com> wrote:
>
> The ll_binary_merge() function assumes that the ancestor blob is
> different from either side of the new versions, and always fails
> the merge in conflict, unless -Xours or -Xtheirs is in effect.
>
> The normal "merge" machineries all resolve the trivial cases
> (e.g. if our side changed while their side did not, the result
> is ours) without triggering the file-level merge drivers, so the
> assumption is warranted.
>
> The code path in "git apply --3way", however, does not check for
> the trivial three-way merge situation and always calls the
> file-level merge drivers. This used to be perfectly OK back
> when we always first attempted a straight patch application and
> used the three-way code path only as a fallback. Any binary
> patch that can be applied as a trivial three-way merge (e.g. the
> patch is based exactly on the version we happen to have) would
> always cleanly apply, so the ll_binary_merge() that is not
> prepared to see the trivial case would not have to handle such a
> case.
>
> This no longer is true after we made "--3way" to mean "first try
> three-way and then fall back to straight application", and made
> "git apply -3" on a binary patch that is based on the current
> version no longer apply.
>
> Teach "git apply -3" to first check for the trivial merge cases
> and resolve them without hitting the file-level merge drivers.
>
> Signed-off-by: Jerry Zhang <jerry@skydio.com>
> [jc: stolen tests from Jerry's patch]
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> ---
>
> apply.c | 21 ++++++++++++++++++
> t/t4108-apply-threeway.sh | 45 +++++++++++++++++++++++++++++++++++++++
> 2 files changed, 66 insertions(+)
>
> diff --git a/apply.c b/apply.c
> index 44bc31d6eb..c9f9503e90 100644
> --- a/apply.c
> +++ b/apply.c
> @@ -3467,6 +3467,21 @@ static int load_preimage(struct apply_state *state,
> return 0;
> }
>
> +static int resolve_to(struct image *image, const struct object_id *result_id)
> +{
> + unsigned long size;
> + enum object_type type;
> +
> + clear_image(image);
> +
> + image->buf = read_object_file(result_id, &type, &size);
> + if (!image->buf || type != OBJ_BLOB)
> + die("unable to read blob object %s", oid_to_hex(result_id));
> + image->len = size;
> +
> + return 0;
> +}
> +
> static int three_way_merge(struct apply_state *state,
> struct image *image,
> char *path,
> @@ -3478,6 +3493,12 @@ static int three_way_merge(struct apply_state *state,
> mmbuffer_t result = { NULL };
> int status;
>
> + /* resolve trivial cases first */
> + if (oideq(base, ours))
> + return resolve_to(image, theirs);
> + else if (oideq(base, theirs) || oideq(ours, theirs))
> + return resolve_to(image, ours);
> +
> read_mmblob(&base_file, base);
> read_mmblob(&our_file, ours);
> read_mmblob(&their_file, theirs);
> diff --git a/t/t4108-apply-threeway.sh b/t/t4108-apply-threeway.sh
> index 65147efdea..cc3aa3314a 100755
> --- a/t/t4108-apply-threeway.sh
> +++ b/t/t4108-apply-threeway.sh
> @@ -230,4 +230,49 @@ test_expect_success 'apply with --3way --cached and conflicts' '
> test_cmp expect.diff actual.diff
> '
>
> +test_expect_success 'apply binary file patch' '
> + git reset --hard main &&
> + cp "$TEST_DIRECTORY/test-binary-1.png" bin.png &&
> + git add bin.png &&
> + git commit -m "add binary file" &&
> +
> + cp "$TEST_DIRECTORY/test-binary-2.png" bin.png &&
> +
> + git diff --binary >bin.diff &&
> + git reset --hard &&
> +
> + # Apply must succeed.
> + git apply bin.diff
> +'
> +
> +test_expect_success 'apply binary file patch with 3way' '
> + git reset --hard main &&
> + cp "$TEST_DIRECTORY/test-binary-1.png" bin.png &&
> + git add bin.png &&
> + git commit -m "add binary file" &&
> +
> + cp "$TEST_DIRECTORY/test-binary-2.png" bin.png &&
> +
> + git diff --binary >bin.diff &&
> + git reset --hard &&
> +
> + # Apply must succeed.
> + git apply --3way --index bin.diff
> +'
> +
> +test_expect_success 'apply full-index patch with 3way' '
> + git reset --hard main &&
> + cp "$TEST_DIRECTORY/test-binary-1.png" bin.png &&
> + git add bin.png &&
> + git commit -m "add binary file" &&
> +
> + cp "$TEST_DIRECTORY/test-binary-2.png" bin.png &&
> +
> + git diff --full-index >bin.diff &&
> + git reset --hard &&
> +
> + # Apply must succeed.
> + git apply --3way --index bin.diff
> +'
> +
> test_done
> --
> 2.33.0-408-g8e1aa136b3
Reviewed-by: Elijah Newren <newren@gmail.com>
next prev parent reply other threads:[~2021-09-06 18:57 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-07-28 2:44 [PATCH] git-apply: fix --3way with binary patch Jerry Zhang
2021-07-28 4:29 ` Junio C Hamano
2021-07-28 4:30 ` Junio C Hamano
2021-07-28 17:55 ` [PATCH] ll-merge: teach ll_binary_merge() a trivial three-way merge Junio C Hamano
2021-07-28 23:49 ` Elijah Newren
2021-07-29 1:06 ` Junio C Hamano
2021-09-05 19:06 ` [PATCH v2] apply: resolve trivial merge without hitting ll-merge with "--3way" Junio C Hamano
2021-09-06 18:57 ` Elijah Newren [this message]
2021-09-06 21:59 ` Ævar Arnfjörð Bjarmason
2021-09-07 2:32 ` Junio C Hamano
2021-09-07 20:15 ` Junio C Hamano
2021-07-28 19:38 ` [PATCH] git-apply: fix --3way with binary patch Jerry Zhang
2021-07-28 20:04 ` Jerry Zhang
2021-07-28 20:08 ` Junio C Hamano
2021-07-28 20:37 ` Jerry Zhang
2021-07-28 21:01 ` 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='CABPp-BGrg7eBCeq7SLvx3N5p7HyKGwS7qwTe=+En6OfiKhiXPQ@mail.gmail.com' \
--to=newren@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=jerry@skydio.com \
--cc=lilinchao@oschina.cn \
/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).