On Thu, Jun 13, 2024 at 08:25:02PM +0000, Elijah Newren via GitGitGadget wrote: > From: Elijah Newren <newren@xxxxxxxxx> > > 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 codepath dealing with error cases did not s/codepath/&s/ ? > 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 correctly, i.e. with the expected exit code > rather than with an assertion failure. I suspect that this test was flaky, too, since if the assertion errors were compiled out and it died via a segfault, the test would have failed outright as test_must_fail does not allow for segfaults typically. So I'm glad to see us tightening up that area of the test suite. > Reported-by: Matt Cree <matt.cree@xxxxxxxxxxx> > Signed-off-by: Elijah Newren <newren@xxxxxxxxx> > --- > 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 10f5a655f29..6ca7b0f9be4 100644 > --- a/merge-ort.c > +++ b/merge-ort.c > @@ -5015,7 +5015,7 @@ static void move_opt_priv_to_result_priv(struct merge_options *opt, > * to move it. > */ > assert(opt->priv && !result->priv); > - if (!opt->priv->call_depth) { > + if (!opt->priv->call_depth || result->clean < 0) { > result->priv = opt->priv; > result->_properly_initialized = RESULT_INITIALIZED; > opt->priv = NULL; > @@ -5052,6 +5052,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); > 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 && Here and below, do you care about the particular exit code of merging as above? IOW, should these be `test_expect_code`'s as well? Thanks, Taylor