git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Elijah Newren <newren@gmail.com>
To: git@vger.kernel.org
Cc: Junio C Hamano <gitster@pobox.com>,
	Johannes Schindelin <Johannes.Schindelin@gmx.de>,
	Derrick Stolee <stolee@gmail.com>,
	Elijah Newren <newren@gmail.com>
Subject: [PATCH v3 00/24] Clean up merge API
Date: Thu, 15 Aug 2019 14:40:29 -0700	[thread overview]
Message-ID: <20190815214053.16594-1-newren@gmail.com> (raw)
In-Reply-To: <20190726155258.28561-1-newren@gmail.com>

Before writing a replacement merge strategy for recursive, I decided
to first cleanup the merge API -- streamlining merge-recursive.h and
making it more readable.

Thanks to Dscho and Junio for feedback on v1 & v2.

Changes since v2:
  * Addressed feedback from Junio and Dscho
    * splitting a couple patches they highlighted as needing splitting
    * fixed up several commit messages
    * refactored cache-tree write-index-as-tree functions to share code
    * created a separate commit with more sanity checks for merge_options
  * Rebased on master (due to en/disable-dir-rename-in-recursive-merge)
  * Found and fixed a minor bug in checkout; put this and related patches
    at the beginning of the series
  * Incorporated a patch from Stolee, though I removed the repo-settings
    bits to make our patch series independent, and modified it to update
    more existing code to use the new enum values.

Things I'd like reviewers to focus on, in priority order:
  * Patch 12 -- I'm still unsure about cache-tree stuff
  * The new patches (2, 3, 5, 23); in more detail:
    * Patch 5 from Stolee -- I modified his original patch a fair amount
      but left him as author; it's a simple patch, but extra eyes to
      verify I didn't blame him for some nasty mistake of mine would be
      good.
    * Patch 2 fixes a minor issue with checkout -m
    * Patch 23 is the more thorough sanity checks Junio suggested
    * Patch 3 was mostly split out from what is now patch 4, so it was
      mostly reviewed before but it now ties in nicely with patch 2.

Derrick Stolee (1):
  merge-recursive: introduce an enum for detect_directory_renames values

Elijah Newren (23):
  merge-recursive: be consistent with assert
  checkout: provide better conflict hunk description with detached HEAD
  merge-recursive: enforce opt->ancestor != NULL when calling
    merge_trees()
  merge-recursive: provide a better label for diff3 common ancestor
  merge-recursive: future-proof update_file_flags() against memory leaks
  merge-recursive: remove another implicit dependency on the_repository
  Ensure index matches head before invoking merge machinery, round N
  merge-recursive: exit early if index != head
  merge-recursive: remove useless parameter in merge_trees()
  merge-recursive: don't force external callers to do our logging
  cache-tree: share code between functions writing an index as a tree
  merge-recursive: fix some overly long lines
  merge-recursive: use common name for ancestors/common/base_list
  merge-recursive: rename 'mrtree' to 'result_tree', for clarity
  merge-recursive: rename merge_options argument to opt in header
  merge-recursive: move some definitions around to clean up the header
  merge-recursive: consolidate unnecessary fields in merge_options
  merge-recursive: comment and reorder the merge_options fields
  merge-recursive: avoid losing output and leaking memory holding that
    output
  merge-recursive: split internal fields into a separate struct
  merge-recursive: rename MERGE_RECURSIVE_* to MERGE_VARIANT_*
  merge-recursive: add sanity checks for relevant merge_options
  merge-recursive: alphabetize include list

 builtin/am.c                      |   2 +-
 builtin/checkout.c                |  14 +-
 builtin/merge-recursive.c         |   4 +
 builtin/stash.c                   |   2 +
 cache-tree.c                      |  81 +++--
 cache-tree.h                      |   3 +-
 merge-recursive.c                 | 571 ++++++++++++++++++------------
 merge-recursive.h                 | 164 +++++----
 sequencer.c                       |   5 +-
 t/t3030-merge-recursive.sh        |   9 +-
 t/t6036-recursive-corner-cases.sh |   8 +-
 t/t6047-diff3-conflict-markers.sh | 189 ++++++++++
 12 files changed, 718 insertions(+), 334 deletions(-)
 create mode 100755 t/t6047-diff3-conflict-markers.sh

Range-diff:
19:  d6158e555d =  1:  21f1e04dc9 merge-recursive: be consistent with assert
 -:  ---------- >  2:  ac24702773 checkout: provide better conflict hunk description with detached HEAD
 -:  ---------- >  3:  fd14ed9490 merge-recursive: enforce opt->ancestor != NULL when calling merge_trees()
20:  814a65ecab !  4:  540a1d17d7 merge-recursive: provide a better label for diff3 common ancestor
    @@ Commit message
             1:   <abbreviated commit hash>
             0:   "<empty tree>"
     
    -    Also, the code in merge_3way making use of opt->ancestor was overly
    -    complex because it tried to handle the case of opt->ancestor being NULL.
    -    We always set it first, though, so just add an assert that opt->ancestor
    -    is not NULL and simplify the surrounding code.
    -
         Tests have also been added to check that we get the right ancestor name
         for each of the three cases.
     
    +    Also, since merge_recursive() and merge_trees() have polar opposite
    +    pre-conditions for opt->ancestor, document merge_recursive()'s
    +    pre-condition with an assertion.  (An assertion was added to
    +    merge_trees() already a few commits ago.)  The differences in
    +    pre-conditions stem from two factors: (1) merge_trees() does not recurse
    +    and thus does not have multiple sub-merges to worry about -- each of
    +    which would require a different value for opt->ancestor, (2)
    +    merge_trees() is only passed trees rather than commits and thus cannot
    +    internally guess as good of a label.  Thus, while external callers of
    +    merge_trees() are required to provide a non-NULL opt->ancestor,
    +    merge_recursive() expects to set this value itself.
    +
         Signed-off-by: Elijah Newren <newren@gmail.com>
     
      ## merge-recursive.c ##
    -@@ merge-recursive.c: static int merge_3way(struct merge_options *opt,
    - {
    - 	mmfile_t orig, src1, src2;
    - 	struct ll_merge_options ll_opts = {0};
    --	char *base_name, *name1, *name2;
    -+	char *base, *name1, *name2;
    - 	int merge_status;
    - 
    - 	ll_opts.renormalize = opt->renormalize;
    -@@ merge-recursive.c: static int merge_3way(struct merge_options *opt,
    - 		}
    - 	}
    - 
    --	assert(a->path && b->path && o->path);
    --	if (strcmp(a->path, b->path) ||
    --	    (opt->ancestor != NULL && strcmp(a->path, o->path) != 0)) {
    --		base_name = opt->ancestor == NULL ? NULL :
    --			mkpathdup("%s:%s", opt->ancestor, o->path);
    -+	assert(a->path && b->path && o->path && opt->ancestor);
    -+	if (strcmp(a->path, b->path) || strcmp(a->path, o->path) != 0) {
    -+		base  = mkpathdup("%s:%s", opt->ancestor, o->path);
    - 		name1 = mkpathdup("%s:%s", branch1, a->path);
    - 		name2 = mkpathdup("%s:%s", branch2, b->path);
    - 	} else {
    --		base_name = opt->ancestor == NULL ? NULL :
    --			mkpathdup("%s", opt->ancestor);
    -+		base  = mkpathdup("%s", opt->ancestor);
    - 		name1 = mkpathdup("%s", branch1);
    - 		name2 = mkpathdup("%s", branch2);
    - 	}
    -@@ merge-recursive.c: static int merge_3way(struct merge_options *opt,
    - 	read_mmblob(&src1, &a->oid);
    - 	read_mmblob(&src2, &b->oid);
    - 
    --	merge_status = ll_merge(result_buf, a->path, &orig, base_name,
    -+	merge_status = ll_merge(result_buf, a->path, &orig, base,
    - 				&src1, name1, &src2, name2,
    - 				opt->repo->index, &ll_opts);
    - 
    --	free(base_name);
    -+	free(base);
    - 	free(name1);
    - 	free(name2);
    - 	free(orig.ptr);
    -@@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt,
    - 	struct commit *merged_merge_bases;
    - 	struct tree *result_tree;
    +@@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
    + 	struct commit *merged_common_ancestors;
    + 	struct tree *mrtree;
      	int clean;
     +	int num_merge_bases;
     +	struct strbuf merge_base_abbrev = STRBUF_INIT;
    ++
    ++	if (!opt->call_depth)
    ++		assert(opt->ancestor == NULL);
      
      	if (show(opt, 4)) {
      		output(opt, 4, _("Merging:"));
    -@@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt,
    +@@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
      			output_commit_title(opt, iter->item);
      	}
      
    -+	num_merge_bases = commit_list_count(merge_bases);
    - 	merged_merge_bases = pop_commit(&merge_bases);
    - 	if (merged_merge_bases == NULL) {
    ++	num_merge_bases = commit_list_count(ca);
    + 	merged_common_ancestors = pop_commit(&ca);
    + 	if (merged_common_ancestors == NULL) {
      		/* if there is no common ancestor, use an empty tree */
    -@@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt,
    - 	if (!opt->priv->call_depth)
    +@@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
    + 	if (!opt->call_depth)
      		repo_read_index(opt->repo);
      
     -	opt->ancestor = "merged common ancestors";
    @@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt
     +		break;
     +	case 1:
     +		strbuf_add_unique_abbrev(&merge_base_abbrev,
    -+					 &merged_merge_bases->object.oid,
    ++					 &merged_common_ancestors->object.oid,
     +					 DEFAULT_ABBREV);
     +		opt->ancestor = merge_base_abbrev.buf;
     +		break;
     +	default:
     +		opt->ancestor = "merged common ancestors";
     +	}
    - 	clean = merge_trees_internal(opt,
    - 				     repo_get_commit_tree(opt->repo, h1),
    - 				     repo_get_commit_tree(opt->repo, h2),
    - 				     repo_get_commit_tree(opt->repo,
    - 							  merged_merge_bases),
    - 				     &result_tree);
    + 	clean = merge_trees(opt, get_commit_tree(h1), get_commit_tree(h2),
    + 			    get_commit_tree(merged_common_ancestors),
    + 			    &mrtree);
     +	strbuf_release(&merge_base_abbrev);
      	if (clean < 0) {
      		flush_output(opt);
      		return clean;
    -@@ merge-recursive.c: int merge_trees(struct merge_options *opt,
    - 	int clean;
    - 	struct tree *ignored;
    - 
    -+	assert(opt->ancestor != NULL);
    -+
    - 	if (merge_start(opt, head))
    - 		return -1;
    - 	clean = merge_trees_internal(opt, head, merge, merge_base, &ignored);
    -@@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
    - {
    - 	int clean;
    - 
    -+	assert(opt->ancestor == NULL);
    -+
    - 	if (merge_start(opt, repo_get_commit_tree(opt->repo, h1)))
    - 		return -1;
    - 	clean = merge_recursive_internal(opt, h1, h2, merge_bases, result);
     
      ## t/t6036-recursive-corner-cases.sh ##
     @@ t/t6036-recursive-corner-cases.sh: test_expect_success 'check nested conflicts' '
 -:  ---------- >  5:  19ff6a9503 merge-recursive: introduce an enum for detect_directory_renames values
 1:  a640f0f2d0 !  6:  5e44146da1 merge-recursive: fix minor memory leak in error condition
    @@ Metadata
     Author: Elijah Newren <newren@gmail.com>
     
      ## Commit message ##
    -    merge-recursive: fix minor memory leak in error condition
    +    merge-recursive: future-proof update_file_flags() against memory leaks
     
    -    Returning before freeing the allocated buffer is suboptimal; as with
    -    elsewhere in the same function, make sure buf gets free'd.
    +    There is a 'free_buf' label to which all but one of the error paths in
    +    update_file_flags() jump; that error case involves a NULL buf and is
    +    thus not a memory leak.  However, make that error case execute the same
    +    deallocation code anyway so that if anyone adds any additional memory
    +    allocations or deallocations, then all error paths correctly deallocate
    +    resources.
     
         Signed-off-by: Elijah Newren <newren@gmail.com>
     
 2:  34f0891d96 <  -:  ---------- merge-recursive: remove another implicit dependency on the_repository
 -:  ---------- >  7:  df210eb029 merge-recursive: remove another implicit dependency on the_repository
 3:  26739a7ed0 !  8:  74dd7b8f59 Ensure index matches head before invoking merge machinery, round N
    @@ Commit message
         So, load the index in builtin/merge-recursive.c, reload the in-memory
         index in builtin/stash.c, and modify the t3030 testcase to correctly
         setup the index and make sure that the test fails in the expected way
    -    (meaning it reports a rename/rename conflict).
    +    (meaning it reports a rename/rename conflict).  This makes sure that
    +    all callers actually make the index match head.  The next commit will
    +    then enforce the condition that index matches head earlier so this
    +    problem doesn't return in the future.
     
         Signed-off-by: Elijah Newren <newren@gmail.com>
     
 4:  76cb459b99 !  9:  f04eba4184 merge-recursive: exit early if index != head
    @@ merge-recursive.c: static int process_entry(struct merge_options *opt,
      	int code, clean;
     -	struct strbuf sb = STRBUF_INIT;
     -
    +-	assert(opt->ancestor != NULL);
    +-
     -	if (!opt->call_depth && repo_index_has_changes(opt->repo, head, &sb)) {
     -		err(opt, _("Your local changes to the following files would be overwritten by merge:\n  %s"),
     -		    sb.buf);
    @@ merge-recursive.c: static struct commit_list *reverse_commit_list(struct commit_
      {
      	struct commit_list *iter;
      	struct commit *merged_common_ancestors;
    +@@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
    + 	int num_merge_bases;
    + 	struct strbuf merge_base_abbrev = STRBUF_INIT;
    + 
    +-	if (!opt->call_depth)
    +-		assert(opt->ancestor == NULL);
    +-
    + 	if (show(opt, 4)) {
    + 		output(opt, 4, _("Merging:"));
    + 		output_commit_title(opt, h1);
     @@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
      		saved_b2 = opt->branch2;
      		opt->branch1 = "Temporary merge branch 1";
    @@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
      			return -1;
      		opt->branch1 = saved_b1;
     @@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
    - 		repo_read_index(opt->repo);
    - 
    - 	opt->ancestor = "merged common ancestors";
    + 	default:
    + 		opt->ancestor = "merged common ancestors";
    + 	}
     -	clean = merge_trees(opt,
     -			    repo_get_commit_tree(opt->repo, h1),
     -			    repo_get_commit_tree(opt->repo, h2),
    @@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
     +				     repo_get_commit_tree(opt->repo,
     +							  merged_common_ancestors),
     +				     &mrtree);
    + 	strbuf_release(&merge_base_abbrev);
      	if (clean < 0) {
      		flush_output(opt);
    - 		return clean;
     @@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
      	return clean;
      }
    @@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
     +{
     +	struct strbuf sb = STRBUF_INIT;
     +
    -+	assert(opt->branch1 && opt->branch2);
    -+
     +	if (repo_index_has_changes(opt->repo, head, &sb)) {
     +		err(opt, _("Your local changes to the following files would be overwritten by merge:\n  %s"),
     +		    sb.buf);
    @@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
     +{
     +	int clean;
     +
    ++	assert(opt->ancestor != NULL);
    ++
     +	if (merge_start(opt, head))
     +		return -1;
     +	clean = merge_trees_internal(opt, head, merge, common, result);
    @@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
     +{
     +	int clean;
     +
    ++	assert(opt->ancestor == NULL);
    ++
     +	if (merge_start(opt, repo_get_commit_tree(opt->repo, h1)))
     +		return -1;
     +	clean = merge_recursive_internal(opt, h1, h2, ca, result);
 5:  2560458522 ! 10:  8688d40739 merge-recursive: remove useless parameter in merge_trees()
    @@ merge-recursive.c: static void merge_finalize(struct merge_options *opt)
      	int clean;
     +	struct tree *ignored;
      
    + 	assert(opt->ancestor != NULL);
    + 
      	if (merge_start(opt, head))
      		return -1;
     -	clean = merge_trees_internal(opt, head, merge, common, result);
 6:  fb340fbe56 ! 11:  a92d460707 merge-recursive: don't force external callers to do our logging
    @@ Commit message
         merge_finalize() function to make sure that all three entry points run
         this function.
     
    +    Note that there are two external callers of merge_trees(), one in
    +    sequencer.c and one in builtin/checkout.c.  The one in sequencer.c is
    +    cleaned up by this patch and just transfers where the call to
    +    diff_warn_rename_limit() is made; the one in builtin/checkout.c is for
    +    switching to a different commit and in the very rare case where the
    +    warning might be triggered, it would probably be helpful to include
    +    (e.g. if someone is modifying a file that has been renamed in moving to
    +    the other commit, but there are so many renames between the commits that
    +    the limit kicks in and none are detected, it may help to have an
    +    explanation about why they got a delete/modify conflict instead of a
    +    proper content merge in a renamed file).
    +
         Signed-off-by: Elijah Newren <newren@gmail.com>
     
      ## merge-recursive.c ##
 7:  884305a3a6 <  -:  ---------- Use write_index_as_tree() in lieu of write_tree_from_memory()
 -:  ---------- > 12:  dec0ea7409 cache-tree: share code between functions writing an index as a tree
 8:  870937b31f = 13:  b51f3d1924 merge-recursive: fix some overly long lines
 9:  5127b75ac4 ! 14:  a069cc4cca merge-recursive: use common name for ancestors/common/base_list
    @@ merge-recursive.c: static struct commit_list *reverse_commit_list(struct commit_
     +	struct commit *merged_merge_bases;
      	struct tree *mrtree;
      	int clean;
    - 
    + 	int num_merge_bases;
     @@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt,
      		output_commit_title(opt, h2);
      	}
    @@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt
      			output_commit_title(opt, iter->item);
      	}
      
    +-	num_merge_bases = commit_list_count(ca);
     -	merged_common_ancestors = pop_commit(&ca);
     -	if (merged_common_ancestors == NULL) {
    ++	num_merge_bases = commit_list_count(merge_bases);
     +	merged_merge_bases = pop_commit(&merge_bases);
     +	if (merged_merge_bases == NULL) {
      		/* if there is no common ancestor, use an empty tree */
    @@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt
      			return err(opt, _("merge returned no commit"));
      	}
      
    +@@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt,
    + 		break;
    + 	case 1:
    + 		strbuf_add_unique_abbrev(&merge_base_abbrev,
    +-					 &merged_common_ancestors->object.oid,
    ++					 &merged_merge_bases->object.oid,
    + 					 DEFAULT_ABBREV);
    + 		opt->ancestor = merge_base_abbrev.buf;
    + 		break;
     @@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt,
      				     repo_get_commit_tree(opt->repo, h1),
      				     repo_get_commit_tree(opt->repo, h2),
    @@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt
     -							  merged_common_ancestors),
     +							  merged_merge_bases),
      				     &mrtree);
    + 	strbuf_release(&merge_base_abbrev);
      	if (clean < 0) {
    - 		flush_output(opt);
     @@ merge-recursive.c: static void merge_finalize(struct merge_options *opt)
      int merge_trees(struct merge_options *opt,
      		struct tree *head,
    @@ merge-recursive.c: static void merge_finalize(struct merge_options *opt)
      {
      	int clean;
      	struct tree *ignored;
    +@@ merge-recursive.c: int merge_trees(struct merge_options *opt,
      
      	if (merge_start(opt, head))
      		return -1;
    @@ merge-recursive.c: int merge_trees(struct merge_options *opt,
      		    struct commit **result)
      {
      	int clean;
    +@@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
      
      	if (merge_start(opt, repo_get_commit_tree(opt->repo, h1)))
      		return -1;
10:  daee364ce1 ! 15:  93a3ce6b88 merge-recursive: rename 'mrtree' to 'result_tree', for clarity
    @@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt
     -	struct tree *mrtree;
     +	struct tree *result_tree;
      	int clean;
    - 
    - 	if (show(opt, 4)) {
    + 	int num_merge_bases;
    + 	struct strbuf merge_base_abbrev = STRBUF_INIT;
     @@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt,
      				     repo_get_commit_tree(opt->repo, h2),
      				     repo_get_commit_tree(opt->repo,
      							  merged_merge_bases),
     -				     &mrtree);
     +				     &result_tree);
    + 	strbuf_release(&merge_base_abbrev);
      	if (clean < 0) {
      		flush_output(opt);
    - 		return clean;
    +@@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt,
      	}
      
      	if (opt->call_depth) {
11:  50a7a6f671 = 16:  1b1df10c11 merge-recursive: rename merge_options argument to opt in header
12:  4e9e774dc5 = 17:  1526977a85 merge-recursive: move some definitions around to clean up the header
13:  bf40502fd8 ! 18:  c90f2f15cd merge-recursive: consolidate unnecessary fields in merge_options
    @@ merge-recursive.c: void init_merge_options(struct merge_options *opt,
     -	opt->diff_detect_rename = -1;
     -	opt->merge_detect_rename = -1;
     +	opt->detect_renames = -1;
    - 	opt->detect_directory_renames = 1;
    + 	opt->detect_directory_renames = MERGE_DIRECTORY_RENAMES_CONFLICT;
      	merge_recursive_config(opt);
      	merge_verbosity = getenv("GIT_MERGE_VERBOSITY");
     @@ merge-recursive.c: int parse_merge_opt(struct merge_options *opt, const char *s)
    @@ merge-recursive.c: int parse_merge_opt(struct merge_options *opt, const char *s)
     
      ## merge-recursive.h ##
     @@ merge-recursive.h: struct merge_options {
    - 	long xdl_opts;
    - 	int verbosity;
    - 	int detect_directory_renames;
    + 		MERGE_DIRECTORY_RENAMES_CONFLICT = 1,
    + 		MERGE_DIRECTORY_RENAMES_TRUE = 2
    + 	} detect_directory_renames;
     -	int diff_detect_rename;
     -	int merge_detect_rename;
     -	int diff_rename_limit;
14:  2c39a4be36 ! 19:  6d930dba72 merge-recursive: comment and reorder the merge_options fields
    @@ merge-recursive.c: void init_merge_options(struct merge_options *opt,
      	opt->repo = repo;
     +
     +	opt->detect_renames = -1;
    -+	opt->detect_directory_renames = 1;
    ++	opt->detect_directory_renames = MERGE_DIRECTORY_RENAMES_CONFLICT;
     +	opt->rename_limit = -1;
     +
      	opt->verbosity = 2;
    @@ merge-recursive.c: void init_merge_options(struct merge_options *opt,
     +
      	opt->renormalize = 0;
     -	opt->detect_renames = -1;
    --	opt->detect_directory_renames = 1;
    +-	opt->detect_directory_renames = MERGE_DIRECTORY_RENAMES_CONFLICT;
     +
     +	string_list_init(&opt->df_conflict_file_set, 1);
     +
    @@ merge-recursive.h: struct commit;
      	const char *ancestor;
      	const char *branch1;
      	const char *branch2;
    +-	enum {
    +-		MERGE_RECURSIVE_NORMAL = 0,
    +-		MERGE_RECURSIVE_OURS,
    +-		MERGE_RECURSIVE_THEIRS
    +-	} recursive_variant;
    +-	const char *subtree_shift;
    +-	unsigned buffer_output; /* 1: output at end, 2: keep buffered */
    +-	unsigned renormalize : 1;
    +-	long xdl_opts;
    +-	int verbosity;
     +
     +	/* rename related options */
     +	int detect_renames;
    -+	int detect_directory_renames;
    -+	int rename_limit;
    -+	int rename_score;
    -+	int show_rename_progress;
    + 	enum {
    + 		MERGE_DIRECTORY_RENAMES_NONE = 0,
    + 		MERGE_DIRECTORY_RENAMES_CONFLICT = 1,
    + 		MERGE_DIRECTORY_RENAMES_TRUE = 2
    + 	} detect_directory_renames;
    +-	int detect_renames;
    + 	int rename_limit;
    + 	int rename_score;
    +-	int needed_rename_limit;
    + 	int show_rename_progress;
     +
     +	/* xdiff-related options (patience, ignore whitespace, ours/theirs) */
     +	long xdl_opts;
    - 	enum {
    - 		MERGE_RECURSIVE_NORMAL = 0,
    - 		MERGE_RECURSIVE_OURS,
    - 		MERGE_RECURSIVE_THEIRS
    - 	} recursive_variant;
    --	const char *subtree_shift;
    ++	enum {
    ++		MERGE_RECURSIVE_NORMAL = 0,
    ++		MERGE_RECURSIVE_OURS,
    ++		MERGE_RECURSIVE_THEIRS
    ++	} recursive_variant;
     +
     +	/* console output related options */
     +	int verbosity;
    - 	unsigned buffer_output; /* 1: output at end, 2: keep buffered */
    ++	unsigned buffer_output; /* 1: output at end, 2: keep buffered */
     +	struct strbuf obuf;     /* output buffer */
     +
     +	/* miscellaneous control options */
     +	const char *subtree_shift;
    - 	unsigned renormalize : 1;
    --	long xdl_opts;
    --	int verbosity;
    --	int detect_directory_renames;
    --	int detect_renames;
    --	int rename_limit;
    --	int rename_score;
    --	int needed_rename_limit;
    --	int show_rename_progress;
    ++	unsigned renormalize : 1;
     +
     +	/* internal fields used by the implementation (do NOT set these) */
      	int call_depth;
15:  c1c71816eb = 20:  ec3e15f6a8 merge-recursive: avoid losing output and leaking memory holding that output
16:  be47a6bfdf ! 21:  7edfac7048 merge-recursive: split internal fields into a separate struct
    @@ merge-recursive.c: static int merge_submodule(struct merge_options *opt,
      	/* store a in result in case we fail */
      	oidcpy(result, a);
     @@ merge-recursive.c: static int handle_rename_via_dir(struct merge_options *opt,
    - 	int mark_conflicted = (opt->detect_directory_renames == 1);
    + 			       MERGE_DIRECTORY_RENAMES_CONFLICT);
      	assert(ren->dir_rename_original_dest);
      
     -	if (!opt->call_depth && would_lose_untracked(opt, dest->path)) {
    @@ merge-recursive.c: static struct diff_queue_struct *get_diffpairs(struct merge_o
      
      	ret = xmalloc(sizeof(*ret));
      	*ret = diff_queued_diff;
    +@@ merge-recursive.c: static int detect_and_process_renames(struct merge_options *opt,
    + 
    + 	if ((opt->detect_directory_renames == MERGE_DIRECTORY_RENAMES_TRUE) ||
    + 	    (opt->detect_directory_renames == MERGE_DIRECTORY_RENAMES_CONFLICT &&
    +-	     !opt->call_depth)) {
    ++	     !opt->priv->call_depth)) {
    + 		dir_re_head = get_directory_renames(head_pairs);
    + 		dir_re_merge = get_directory_renames(merge_pairs);
    + 
     @@ merge-recursive.c: static int handle_content_merge(struct merge_file_info *mfi,
      		reason = _("add/add");
      
    @@ merge-recursive.c: static int merge_trees_internal(struct merge_options *opt,
      
      	unpack_trees_finish(opt);
      
    --	if (opt->call_depth) {
    -+	if (opt->priv->call_depth) {
    - 		struct object_id tree_id;
    - 		if (write_index_as_tree(&tree_id, opt->repo->index, NULL,
    - 					WRITE_TREE_FROM_MEMORY, NULL) ||
    +-	if (opt->call_depth &&
    ++	if (opt->priv->call_depth &&
    + 	    !(*result = write_inmemory_index_as_tree(opt->repo)))
    + 		return -1;
    + 
     @@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt,
      
      	for (iter = merge_bases; iter; iter = iter->next) {
    @@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt
     +	if (!opt->priv->call_depth)
      		repo_read_index(opt->repo);
      
    - 	opt->ancestor = "merged common ancestors";
    + 	switch (num_merge_bases) {
     @@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt,
      		return clean;
      	}
18:  40161dc352 = 22:  9a381873c2 merge-recursive: rename MERGE_RECURSIVE_* to MERGE_VARIANT_*
 -:  ---------- > 23:  c6bc8a196f merge-recursive: add sanity checks for relevant merge_options
17:  f440ee1e64 = 24:  2123e9e4e4 merge-recursive: alphabetize include list
-- 
2.23.0.rc2.32.g2123e9e4e4


  parent reply	other threads:[~2019-08-15 21:41 UTC|newest]

Thread overview: 157+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-25 17:45 [PATCH 00/19] Cleanup merge API Elijah Newren
2019-07-25 17:45 ` [PATCH 01/19] merge-recursive: fix minor memory leak in error condition Elijah Newren
2019-07-25 17:45 ` [PATCH 02/19] merge-recursive: remove another implicit dependency on the_repository Elijah Newren
2019-07-25 17:45 ` [PATCH 03/19] Ensure index matches head before invoking merge machinery, round N Elijah Newren
2019-07-25 19:41   ` Johannes Schindelin
2019-07-25 19:58     ` Elijah Newren
2019-07-26 11:23       ` Johannes Schindelin
2019-07-25 17:45 ` [PATCH 04/19] merge-recursive: exit early if index != head Elijah Newren
2019-07-25 19:51   ` Johannes Schindelin
2019-07-25 20:12     ` Elijah Newren
2019-07-25 17:45 ` [PATCH 05/19] merge-recursive: don't force external callers to do our logging Elijah Newren
2019-07-25 17:45 ` [PATCH 06/19] Change call signature of write_tree_from_memory() Elijah Newren
2019-07-25 19:55   ` Johannes Schindelin
2019-07-26  4:58     ` Elijah Newren
2019-07-25 17:45 ` [PATCH 07/19] Move write_tree_from_memory() from merge-recursive to cache-tree Elijah Newren
2019-07-25 17:46 ` [PATCH 08/19] merge-recursive: fix some overly long lines Elijah Newren
2019-07-25 17:46 ` [PATCH 09/19] merge-recursive: use common name for ancestors/common/base_list Elijah Newren
2019-07-25 17:46 ` [PATCH 10/19] merge-recursive: rename 'mrtree' to 'result_tree', for clarity Elijah Newren
2019-07-25 20:02   ` Johannes Schindelin
2019-07-25 17:46 ` [PATCH 11/19] merge-recursive: rename merge_options argument to opt in header Elijah Newren
2019-07-25 17:46 ` [PATCH 12/19] merge-recursive: move some definitions around to clean up the header Elijah Newren
2019-07-25 17:46 ` [PATCH 13/19] merge-recursive: consolidate unnecessary fields in merge_options Elijah Newren
2019-07-25 17:46 ` [PATCH 14/19] merge-recursive: comment and reorder the merge_options fields Elijah Newren
2019-07-25 17:46 ` [PATCH 15/19] merge-recursive: split internal fields into a separate struct Elijah Newren
2019-07-25 20:12   ` Johannes Schindelin
2019-07-25 20:27     ` Elijah Newren
2019-07-26 11:25       ` Johannes Schindelin
2019-07-26 15:30         ` Elijah Newren
2019-07-25 17:46 ` [PATCH 16/19] merge-recursive: alphabetize include list Elijah Newren
2019-07-25 17:46 ` [PATCH 17/19] merge-recursive: rename MERGE_RECURSIVE_* to MERGE_VARIANT_* Elijah Newren
2019-07-25 17:46 ` [PATCH 18/19] merge-recursive: be consistent with assert Elijah Newren
2019-07-25 17:46 ` [PATCH 19/19] merge-recursive: provide a better label for diff3 common ancestor Elijah Newren
2019-07-25 20:28   ` Johannes Schindelin
2019-07-25 18:12 ` [PATCH 00/19] Cleanup merge API Junio C Hamano
2019-07-25 19:06   ` Elijah Newren
2019-07-25 22:50     ` Junio C Hamano
2019-07-26 14:07       ` Johannes Schindelin
2019-07-25 19:15 ` Johannes Schindelin
2019-07-26 15:15   ` Elijah Newren
2019-07-26 15:52 ` [PATCH v2 00/20] " Elijah Newren
2019-07-26 15:52   ` [PATCH v2 01/20] merge-recursive: fix minor memory leak in error condition Elijah Newren
2019-07-26 18:31     ` Junio C Hamano
2019-07-26 23:19       ` Elijah Newren
2019-07-29 14:13       ` Derrick Stolee
2019-07-26 15:52   ` [PATCH v2 02/20] merge-recursive: remove another implicit dependency on the_repository Elijah Newren
2019-07-26 18:42     ` Junio C Hamano
2019-07-26 15:52   ` [PATCH v2 03/20] Ensure index matches head before invoking merge machinery, round N Elijah Newren
2019-07-26 19:14     ` Junio C Hamano
2019-07-26 23:22       ` Elijah Newren
2019-07-26 15:52   ` [PATCH v2 04/20] merge-recursive: exit early if index != head Elijah Newren
2019-07-26 19:32     ` Junio C Hamano
2019-07-26 23:26       ` Elijah Newren
2019-07-29 15:56         ` Junio C Hamano
2019-07-26 15:52   ` [PATCH v2 05/20] merge-recursive: remove useless parameter in merge_trees() Elijah Newren
2019-07-26 19:37     ` Junio C Hamano
2019-07-26 15:52   ` [PATCH v2 06/20] merge-recursive: don't force external callers to do our logging Elijah Newren
2019-07-26 19:57     ` Junio C Hamano
2019-07-26 23:28       ` Elijah Newren
2019-07-26 15:52   ` [PATCH v2 07/20] Use write_index_as_tree() in lieu of write_tree_from_memory() Elijah Newren
2019-07-26 20:11     ` Junio C Hamano
2019-07-26 23:39       ` Elijah Newren
2019-07-29  4:46         ` Junio C Hamano
2019-07-26 15:52   ` [PATCH v2 08/20] merge-recursive: fix some overly long lines Elijah Newren
2019-07-26 15:52   ` [PATCH v2 09/20] merge-recursive: use common name for ancestors/common/base_list Elijah Newren
2019-07-26 15:52   ` [PATCH v2 10/20] merge-recursive: rename 'mrtree' to 'result_tree', for clarity Elijah Newren
2019-07-26 15:52   ` [PATCH v2 11/20] merge-recursive: rename merge_options argument to opt in header Elijah Newren
2019-07-26 15:52   ` [PATCH v2 12/20] merge-recursive: move some definitions around to clean up the header Elijah Newren
2019-07-26 15:52   ` [PATCH v2 13/20] merge-recursive: consolidate unnecessary fields in merge_options Elijah Newren
2019-07-26 15:52   ` [PATCH v2 14/20] merge-recursive: comment and reorder the merge_options fields Elijah Newren
2019-07-26 15:52   ` [PATCH v2 15/20] merge-recursive: avoid losing output and leaking memory holding that output Elijah Newren
2019-07-26 15:52   ` [PATCH v2 16/20] merge-recursive: split internal fields into a separate struct Elijah Newren
2019-07-26 15:52   ` [PATCH v2 17/20] merge-recursive: alphabetize include list Elijah Newren
2019-07-26 15:52   ` [PATCH v2 18/20] merge-recursive: rename MERGE_RECURSIVE_* to MERGE_VARIANT_* Elijah Newren
2019-07-26 15:52   ` [PATCH v2 19/20] merge-recursive: be consistent with assert Elijah Newren
2019-07-26 15:52   ` [PATCH v2 20/20] merge-recursive: provide a better label for diff3 common ancestor Elijah Newren
2019-08-15 21:40   ` Elijah Newren [this message]
2019-08-15 21:40     ` [PATCH v3 01/24] merge-recursive: be consistent with assert Elijah Newren
2019-08-15 21:40     ` [PATCH v3 02/24] checkout: provide better conflict hunk description with detached HEAD Elijah Newren
2019-08-15 21:40     ` [PATCH v3 03/24] merge-recursive: enforce opt->ancestor != NULL when calling merge_trees() Elijah Newren
2019-08-16 21:05       ` Junio C Hamano
2019-08-15 21:40     ` [PATCH v3 04/24] merge-recursive: provide a better label for diff3 common ancestor Elijah Newren
2019-08-16 21:33       ` Junio C Hamano
2019-08-16 22:39         ` Elijah Newren
2019-08-15 21:40     ` [PATCH v3 05/24] merge-recursive: introduce an enum for detect_directory_renames values Elijah Newren
2019-08-15 21:40     ` [PATCH v3 06/24] merge-recursive: future-proof update_file_flags() against memory leaks Elijah Newren
2019-08-15 21:40     ` [PATCH v3 07/24] merge-recursive: remove another implicit dependency on the_repository Elijah Newren
2019-08-15 21:40     ` [PATCH v3 08/24] Ensure index matches head before invoking merge machinery, round N Elijah Newren
2019-08-15 21:40     ` [PATCH v3 09/24] merge-recursive: exit early if index != head Elijah Newren
2019-08-15 21:40     ` [PATCH v3 10/24] merge-recursive: remove useless parameter in merge_trees() Elijah Newren
2019-08-15 21:40     ` [PATCH v3 11/24] merge-recursive: don't force external callers to do our logging Elijah Newren
2019-08-15 21:40     ` [PATCH v3 12/24] cache-tree: share code between functions writing an index as a tree Elijah Newren
2019-08-16 22:01       ` Junio C Hamano
2019-08-16 22:39         ` Elijah Newren
2019-08-15 21:40     ` [PATCH v3 13/24] merge-recursive: fix some overly long lines Elijah Newren
2019-08-15 21:40     ` [PATCH v3 14/24] merge-recursive: use common name for ancestors/common/base_list Elijah Newren
2019-08-15 21:40     ` [PATCH v3 15/24] merge-recursive: rename 'mrtree' to 'result_tree', for clarity Elijah Newren
2019-08-15 21:40     ` [PATCH v3 16/24] merge-recursive: rename merge_options argument to opt in header Elijah Newren
2019-08-15 21:40     ` [PATCH v3 17/24] merge-recursive: move some definitions around to clean up the header Elijah Newren
2019-08-15 21:40     ` [PATCH v3 18/24] merge-recursive: consolidate unnecessary fields in merge_options Elijah Newren
2019-08-16 22:14       ` Junio C Hamano
2019-08-16 22:59         ` Elijah Newren
2019-08-16 23:24           ` Junio C Hamano
2019-08-15 21:40     ` [PATCH v3 19/24] merge-recursive: comment and reorder the merge_options fields Elijah Newren
2019-08-15 21:40     ` [PATCH v3 20/24] merge-recursive: avoid losing output and leaking memory holding that output Elijah Newren
2019-08-15 21:40     ` [PATCH v3 21/24] merge-recursive: split internal fields into a separate struct Elijah Newren
2019-08-16 21:19       ` SZEDER Gábor
2019-08-16 23:00         ` Elijah Newren
2019-08-16 22:17       ` Junio C Hamano
2019-08-15 21:40     ` [PATCH v3 22/24] merge-recursive: rename MERGE_RECURSIVE_* to MERGE_VARIANT_* Elijah Newren
2019-08-15 21:40     ` [PATCH v3 23/24] merge-recursive: add sanity checks for relevant merge_options Elijah Newren
2019-08-16 19:52       ` Junio C Hamano
2019-08-16 22:08         ` Elijah Newren
2019-08-16 23:15           ` Junio C Hamano
2019-08-16 19:59       ` Junio C Hamano
2019-08-16 22:09         ` Elijah Newren
2019-08-15 21:40     ` [PATCH v3 24/24] merge-recursive: alphabetize include list Elijah Newren
2019-08-17 18:41     ` [PATCH v4 00/24] Clean up merge API Elijah Newren
2019-08-17 18:41       ` [PATCH v4 01/24] merge-recursive: be consistent with assert Elijah Newren
2019-08-17 18:41       ` [PATCH v4 02/24] checkout: provide better conflict hunk description with detached HEAD Elijah Newren
2019-08-17 18:41       ` [PATCH v4 03/24] merge-recursive: enforce opt->ancestor != NULL when calling merge_trees() Elijah Newren
2019-08-17 18:41       ` [PATCH v4 04/24] merge-recursive: provide a better label for diff3 common ancestor Elijah Newren
2019-09-30 21:14         ` Jeff King
2019-09-30 21:19           ` Jeff King
2019-09-30 22:54           ` [PATCH] merge-recursive: fix the diff3 common ancestor label for virtual commits Elijah Newren
2019-10-01  6:56             ` Elijah Newren
2019-10-01  6:58             ` [PATCH v2] " Elijah Newren
2019-10-01 14:49               ` Jeff King
2019-10-01 18:17                 ` [PATCH v3] " Elijah Newren
2019-10-07  2:51                   ` Junio C Hamano
2019-10-07 15:52                     ` [PATCH] merge-recursive: fix the fix to the diff3 common ancestor label Elijah Newren
2019-10-08  2:32                       ` Junio C Hamano
2019-10-08  2:36                       ` Junio C Hamano
2019-10-08 16:16                         ` Elijah Newren
2019-08-17 18:41       ` [PATCH v4 05/24] merge-recursive: introduce an enum for detect_directory_renames values Elijah Newren
2019-08-17 18:41       ` [PATCH v4 06/24] merge-recursive: future-proof update_file_flags() against memory leaks Elijah Newren
2019-08-17 18:41       ` [PATCH v4 07/24] merge-recursive: remove another implicit dependency on the_repository Elijah Newren
2019-08-17 18:41       ` [PATCH v4 08/24] Ensure index matches head before invoking merge machinery, round N Elijah Newren
2019-09-02 23:01         ` Johannes Schindelin
2019-09-03 13:34           ` Johannes Schindelin
2019-09-03 18:17             ` Elijah Newren
2019-08-17 18:41       ` [PATCH v4 09/24] merge-recursive: exit early if index != head Elijah Newren
2019-08-17 18:41       ` [PATCH v4 10/24] merge-recursive: remove useless parameter in merge_trees() Elijah Newren
2019-08-17 18:41       ` [PATCH v4 11/24] merge-recursive: don't force external callers to do our logging Elijah Newren
2019-08-17 18:41       ` [PATCH v4 12/24] cache-tree: share code between functions writing an index as a tree Elijah Newren
2019-08-17 18:41       ` [PATCH v4 13/24] merge-recursive: fix some overly long lines Elijah Newren
2019-08-17 18:41       ` [PATCH v4 14/24] merge-recursive: use common name for ancestors/common/base_list Elijah Newren
2019-08-17 18:41       ` [PATCH v4 15/24] merge-recursive: rename 'mrtree' to 'result_tree', for clarity Elijah Newren
2019-08-17 18:41       ` [PATCH v4 16/24] merge-recursive: rename merge_options argument to opt in header Elijah Newren
2019-08-17 18:41       ` [PATCH v4 17/24] merge-recursive: move some definitions around to clean up the header Elijah Newren
2019-08-17 18:41       ` [PATCH v4 18/24] merge-recursive: consolidate unnecessary fields in merge_options Elijah Newren
2019-08-17 18:41       ` [PATCH v4 19/24] merge-recursive: comment and reorder the merge_options fields Elijah Newren
2019-08-17 18:41       ` [PATCH v4 20/24] merge-recursive: avoid losing output and leaking memory holding that output Elijah Newren
2019-08-17 18:41       ` [PATCH v4 21/24] merge-recursive: split internal fields into a separate struct Elijah Newren
2019-08-19 17:17         ` Junio C Hamano
2019-08-17 18:41       ` [PATCH v4 22/24] merge-recursive: rename MERGE_RECURSIVE_* to MERGE_VARIANT_* Elijah Newren
2019-08-17 18:41       ` [PATCH v4 23/24] merge-recursive: add sanity checks for relevant merge_options Elijah Newren
2019-08-17 18:41       ` [PATCH v4 24/24] merge-recursive: alphabetize include list Elijah Newren

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

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190815214053.16594-1-newren@gmail.com \
    --to=newren@gmail.com \
    --cc=Johannes.Schindelin@gmx.de \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=stolee@gmail.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.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

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 read-only IMAP folder(s) and NNTP newsgroup(s).