git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 2/7] merge-ort: maintain expected invariant for priv member

From
Elijah Newren via GitGitGadget <gitgitgadget@gmail.com>
Date
Jun 19, 2024, 03:00 UTC
Message-ID
<d1adec6d10556e247c21f94420879724fa2c6436.1718766019.git.gitgitgadget@gmail.com>
In-Reply-To
<pull.1748.v2.git.1718766019.gitgitgadget@gmail.com>
From: Elijah Newren <newren@gmail.com>
The calling convention for the merge machinery is
   One call to          init_merge_options()
   One or more calls to merge_incore_[non]recursive()
   One call to          merge_finalize()
      (possibly indirectly via merge_switch_to_result())
Both merge_switch_to_result() and merge_finalize() expect
   opt->priv == NULL && result->priv != NULL
which is supposed to be set up by our move_opt_priv_to_result_priv()
function.  However, two codepaths dealing with error cases did not
execute this necessary logic, which could result in assertion failures
(or, if assertions were compiled out, could result in segfaults).  Fix
the oversight and add a test that would have caught one of these
problems.
While at it, also tighten an existing test for a non-recursive merge
to verify that it fails with appropriate status.  Most merge tests in
the testsuite check either for success or conflicts; those testing for
neither are rare and it is good to ensure they support the invariant
assumed by builtin/merge.c in this comment:
    /*
     * The backend exits with 1 when conflicts are
     * left to be resolved, with 2 when it does not
     * handle the given merge at all.
     */
So, explicitly check for the exit status of 2 in these cases.
Reported-by: Matt Cree <matt.cree@gearset.com>
Signed-off-by: Elijah Newren <newren@gmail.com>
---
 merge-ort.c           |  3 ++-
 t/t6406-merge-attr.sh | 42 +++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 43 insertions(+), 2 deletions(-)
diff --git a/merge-ort.c b/merge-ort.c
index 700ddfccb90..dc62aaf6d11 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -5050,6 +5050,7 @@ static void merge_ort_nonrecursive_internal(struct merge_options *opt,
 		    oid_to_hex(&side1->object.oid),
 		    oid_to_hex(&side2->object.oid));
 		result->clean = -1;
+		move_opt_priv_to_result_priv(opt, result);
 		return;
 	}
 	trace2_region_leave("merge", "collect_merge_info", opt->repo);
@@ -5080,7 +5081,7 @@ static void merge_ort_nonrecursive_internal(struct merge_options *opt,
 		/* existence of conflicted entries implies unclean */
 		result->clean &= strmap_empty(&opt->priv->conflicted);
 	}
-	if (!opt->priv->call_depth)
+	if (!opt->priv->call_depth || result->clean < 0)
 		move_opt_priv_to_result_priv(opt, result);
 }
 
diff --git a/t/t6406-merge-attr.sh b/t/t6406-merge-attr.sh
index 156a1efacfe..b6db5c2cc36 100755
--- a/t/t6406-merge-attr.sh
+++ b/t/t6406-merge-attr.sh
@@ -185,7 +185,7 @@ test_expect_success !WINDOWS 'custom merge driver that is killed with a signal'
 
 	>./please-abort &&
 	echo "* merge=custom" >.gitattributes &&
-	test_must_fail git merge main 2>err &&
+	test_expect_code 2 git merge main 2>err &&
 	grep "^error: failed to execute internal merge" err &&
 	git ls-files -u >output &&
 	git diff --name-only HEAD >>output &&
@@ -261,4 +261,44 @@ test_expect_success 'binary files with union attribute' '
 	grep -i "warning.*cannot merge.*HEAD vs. bin-main" output
 '
 
+test_expect_success !WINDOWS 'custom merge driver that is killed with a signal on recursive merge' '
+	test_when_finished "rm -f output please-abort" &&
+	test_when_finished "git checkout side" &&
+
+	git reset --hard anchor &&
+
+	git checkout -b base-a main^ &&
+	echo base-a >text &&
+	git commit -m base-a text &&
+
+	git checkout -b base-b main^ &&
+	echo base-b >text &&
+	git commit -m base-b text &&
+
+	git checkout -b recursive-a base-a &&
+	test_must_fail git merge base-b &&
+	echo recursive-a >text &&
+	git add text &&
+	git commit -m recursive-a &&
+
+	git checkout -b recursive-b base-b &&
+	test_must_fail git merge base-a &&
+	echo recursive-b >text &&
+	git add text &&
+	git commit -m recursive-b &&
+
+	git config --replace-all \
+	merge.custom.driver "./custom-merge %O %A %B 0 %P %S %X %Y" &&
+	git config --replace-all \
+	merge.custom.name "custom merge driver for testing" &&
+
+	>./please-abort &&
+	echo "* merge=custom" >.gitattributes &&
+	test_expect_code 2 git merge recursive-a 2>err &&
+	grep "^error: failed to execute internal merge" err &&
+	git ls-files -u >output &&
+	git diff --name-only HEAD >>output &&
+	test_must_be_empty output
+'
+
 test_done
-- 
gitgitgadget
Previous: Elijah Newren via GitGitGadgetNext: Derrick Stolee
Message 18 of 34 in “Fix and improve some error codepaths in merge-ort”
  1. 0/7 Fix and improve some error codepaths in merge-ortElijah Newren via GitGitGadget, Jun 13, 2024
  2. 1/7 merge-ort: extract handling of priv member into reusable functionElijah Newren via GitGitGadget, Jun 13, 2024
  3. Junio C HamanoJun 13, 2024
  4. Taylor BlauJun 13, 2024
  5. 2/7 merge-ort: maintain expected invariant for priv memberElijah Newren via GitGitGadget, Jun 13, 2024
  6. Taylor BlauJun 13, 2024
  7. Elijah NewrenJun 19, 2024
  8. 3/7 merge-ort: fix type of local 'clean' var in handle_content_merge()Elijah Newren via GitGitGadget, Jun 13, 2024
  9. 4/7 merge-ort: clearer propagation of failure-to-function from merge_submoduleElijah Newren via GitGitGadget, Jun 13, 2024
  10. 5/7 merge-ort: loosen commented requirementsElijah Newren via GitGitGadget, Jun 13, 2024
  11. 6/7 merge-ort: upon merge abort, only show messages causing the abortElijah Newren via GitGitGadget, Jun 13, 2024
  12. Eric SunshineJun 14, 2024
  13. Elijah NewrenJun 19, 2024
  14. 7/7 merge-ort: convert more error() cases to path_msg()Elijah Newren via GitGitGadget, Jun 13, 2024
  15. Taylor BlauJun 13, 2024
  16. 0/7 Fix and improve some error codepaths in merge-ortElijah Newren via GitGitGadget, Jun 19, 2024
  17. 1/7 merge-ort: extract handling of priv member into reusable functionElijah Newren via GitGitGadget, Jun 19, 2024
  18. 2/7 merge-ort: maintain expected invariant for priv memberElijah Newren via GitGitGadget, Jun 19, 2024
  19. Derrick StoleeJun 28, 2024
  20. 3/7 merge-ort: fix type of local 'clean' var in handle_content_merge()Elijah Newren via GitGitGadget, Jun 19, 2024
  21. Derrick StoleeJun 28, 2024
  22. 4/7 merge-ort: clearer propagation of failure-to-function from merge_submoduleElijah Newren via GitGitGadget, Jun 19, 2024
  23. Derrick StoleeJun 28, 2024
  24. Elijah NewrenJun 28, 2024
  25. Derrick StoleeJun 28, 2024
  26. 5/7 merge-ort: loosen commented requirementsElijah Newren via GitGitGadget, Jun 19, 2024
  27. 6/7 merge-ort: upon merge abort, only show messages causing the abortElijah Newren via GitGitGadget, Jun 19, 2024
  28. 7/7 merge-ort: convert more error() cases to path_msg()Elijah Newren via GitGitGadget, Jun 19, 2024
  29. Jeff KingJul 2, 2024
  30. Elijah NewrenJul 3, 2024
  31. Junio C HamanoJul 3, 2024
  32. Jeff KingJul 6, 2024
  33. Derrick StoleeJun 28, 2024
  34. Junio C HamanoJun 28, 2024

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.