git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Alex Henrie <alexhenrie24@gmail.com>
To: git@vger.kernel.org, gitster@pobox.com, bert.wesarg@googlemail.com
Cc: Alex Henrie <alexhenrie24@gmail.com>
Subject: [PATCH v2 0/1] apply: support --ours, --theirs, and --union for three-way merges
Date: Mon,  9 Sep 2024 08:10:57 -0600	[thread overview]
Message-ID: <20240909141109.3102-1-alexhenrie24@gmail.com> (raw)
In-Reply-To: <20240906044222.4881-1-alexhenrie24@gmail.com>

Changes from v1:
- Use OPT_SET_INT_F instead of OPT_CALLBACK_F
- Remove the special message and instead always say that the patch
  applied cleanly when these options are used

Thanks to Junio for your feedback.

Alex Henrie (1):
  apply: support --ours, --theirs, and --union for three-way merges

 Documentation/git-apply.txt |  9 ++++++++-
 apply.c                     | 20 +++++++++++++++++--
 apply.h                     |  1 +
 t/t4108-apply-threeway.sh   | 40 +++++++++++++++++++++++++++++++++++++
 4 files changed, 67 insertions(+), 3 deletions(-)

Range-diff against v1:
1:  e0e4000d47 ! 1:  9307dc5a1b apply: support --ours, --theirs, and --union for three-way merges
    @@ Documentation/git-apply.txt: OPTIONS
      	for each blob to help identify the original version that
     
      ## apply.c ##
    -@@ apply.c: int init_apply_state(struct apply_state *state,
    - 	state->prefix = prefix;
    - 	state->repo = repo;
    - 	state->apply = 1;
    -+	state->merge_opts.conflict_style = -1;
    - 	state->line_termination = '\n';
    - 	state->p_value = 1;
    - 	state->p_context = UINT_MAX;
     @@ apply.c: static int three_way_merge(struct apply_state *state,
    + 			   const struct object_id *theirs)
    + {
    + 	mmfile_t base_file, our_file, their_file;
    ++	struct ll_merge_options merge_opts = LL_MERGE_OPTIONS_INIT;
    + 	mmbuffer_t result = { NULL };
    + 	enum ll_merge_result status;
    + 
    +@@ apply.c: static int three_way_merge(struct apply_state *state,
    + 	read_mmblob(&base_file, base);
    + 	read_mmblob(&our_file, ours);
    + 	read_mmblob(&their_file, theirs);
    ++	merge_opts.variant = state->merge_variant;
    + 	status = ll_merge(&result, path,
    + 			  &base_file, "base",
      			  &our_file, "ours",
      			  &their_file, "theirs",
      			  state->repo->index,
     -			  NULL);
    -+			  &state->merge_opts);
    ++			  &merge_opts);
      	if (status == LL_MERGE_BINARY_CONFLICT)
      		warning("Cannot merge binary files: %s (%s vs. %s)",
      			path, "ours", "theirs");
    -@@ apply.c: static int try_threeway(struct apply_state *state,
    - 		return status;
    - 	}
    - 
    --	if (status) {
    -+	if (state->merge_opts.variant) {
    -+		/*
    -+		 * XDL_MERGE_FAVOR_(OURS|THEIRS|UNION) automatically resolves
    -+		 * conflicts, but the ll_merge function is not yet smart enough
    -+		 * to report whether or not there were conflicts, so just print
    -+		 * a generic message.
    -+		 */
    -+		fprintf(stderr, _("Applied patch to '%s'.\n"), patch->new_name);
    -+	} else if (status) {
    - 		patch->conflicted_threeway = 1;
    - 		if (patch->is_new)
    - 			oidclr(&patch->threeway_stage[0], the_repository->hash_algo);
    -@@ apply.c: static int apply_option_parse_space_change(const struct option *opt,
    - 	return 0;
    - }
    - 
    -+static int apply_option_parse_favorite(const struct option *opt,
    -+				       const char *arg, int unset)
    -+{
    -+	struct apply_state *state = opt->value;
    -+
    -+	BUG_ON_OPT_ARG(arg);
    -+	BUG_ON_OPT_NEG(unset);
    -+
    -+	if (!strcmp(opt->long_name, "ours"))
    -+		state->merge_opts.variant = XDL_MERGE_FAVOR_OURS;
    -+	else if (!strcmp(opt->long_name, "theirs"))
    -+		state->merge_opts.variant = XDL_MERGE_FAVOR_THEIRS;
    -+	else
    -+		state->merge_opts.variant = XDL_MERGE_FAVOR_UNION;
    -+	return 0;
    -+}
    -+
    - static int apply_option_parse_whitespace(const struct option *opt,
    - 					 const char *arg, int unset)
    - {
     @@ apply.c: int apply_parse_options(int argc, const char **argv,
      			N_("also apply the patch (use with --stat/--summary/--check)")),
      		OPT_BOOL('3', "3way", &state->threeway,
      			 N_( "attempt three-way merge, fall back on normal patch if that fails")),
    -+		OPT_CALLBACK_F(0, "ours", state, NULL,
    ++		OPT_SET_INT_F(0, "ours", &state->merge_variant,
     +			N_("for conflicts, use our version"),
    -+			PARSE_OPT_NOARG | PARSE_OPT_NONEG,
    -+			apply_option_parse_favorite),
    -+		OPT_CALLBACK_F(0, "theirs", state, NULL,
    ++			XDL_MERGE_FAVOR_OURS, PARSE_OPT_NONEG),
    ++		OPT_SET_INT_F(0, "theirs", &state->merge_variant,
     +			N_("for conflicts, use their version"),
    -+			PARSE_OPT_NOARG | PARSE_OPT_NONEG,
    -+			apply_option_parse_favorite),
    -+		OPT_CALLBACK_F(0, "union", state, NULL,
    ++			XDL_MERGE_FAVOR_THEIRS, PARSE_OPT_NONEG),
    ++		OPT_SET_INT_F(0, "union", &state->merge_variant,
     +			N_("for conflicts, use a union version"),
    -+			PARSE_OPT_NOARG | PARSE_OPT_NONEG,
    -+			apply_option_parse_favorite),
    ++			XDL_MERGE_FAVOR_UNION, PARSE_OPT_NONEG),
      		OPT_FILENAME(0, "build-fake-ancestor", &state->fake_ancestor,
      			N_("build a temporary index based on embedded index information")),
      		/* Think twice before adding "--nul" synonym to this */
    @@ apply.c: int apply_parse_options(int argc, const char **argv,
     -	return parse_options(argc, argv, state->prefix, builtin_apply_options, apply_usage, 0);
     +	argc = parse_options(argc, argv, state->prefix, builtin_apply_options, apply_usage, 0);
     +
    -+	if (state->merge_opts.variant && !state->threeway)
    ++	if (state->merge_variant && !state->threeway)
     +		die(_("--ours, --theirs, and --union require --3way"));
     +
     +	return argc;
      }
     
      ## apply.h ##
    -@@
    - 
    - #include "hash.h"
    - #include "lockfile.h"
    -+#include "merge-ll.h"
    - #include "string-list.h"
    - #include "strmap.h"
    - 
     @@ apply.h: struct apply_state {
      	struct repository *repo;
      	const char *index_file;
      	enum apply_verbosity apply_verbosity;
    -+	struct ll_merge_options merge_opts;
    ++	int merge_variant;
      	char *fake_ancestor;
      	const char *patch_input_file;
      	int line_termination;
-- 
2.46.0


  parent reply	other threads:[~2024-09-09 14:11 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-09-06  4:22 [PATCH] apply: support --ours, --theirs, and --union for three-way merges Alex Henrie
2024-09-06 20:49 ` Junio C Hamano
2024-09-09 14:10   ` Alex Henrie
2024-09-09 14:10 ` Alex Henrie [this message]
2024-09-09 14:10   ` [PATCH v2 1/1] " Alex Henrie

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=20240909141109.3102-1-alexhenrie24@gmail.com \
    --to=alexhenrie24@gmail.com \
    --cc=bert.wesarg@googlemail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    /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).