Skip to content

Commit 0b4f726

Browse files
newrengitster
authored andcommitted
merge-ort: maintain expected invariant for priv member
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 <[email protected]> Signed-off-by: Elijah Newren <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent e79bdb4 commit 0b4f726

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

merge-ort.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5050,6 +5050,7 @@ static void merge_ort_nonrecursive_internal(struct merge_options *opt,
50505050
oid_to_hex(&side1->object.oid),
50515051
oid_to_hex(&side2->object.oid));
50525052
result->clean = -1;
5053+
move_opt_priv_to_result_priv(opt, result);
50535054
return;
50545055
}
50555056
trace2_region_leave("merge", "collect_merge_info", opt->repo);
@@ -5080,7 +5081,7 @@ static void merge_ort_nonrecursive_internal(struct merge_options *opt,
50805081
/* existence of conflicted entries implies unclean */
50815082
result->clean &= strmap_empty(&opt->priv->conflicted);
50825083
}
5083-
if (!opt->priv->call_depth)
5084+
if (!opt->priv->call_depth || result->clean < 0)
50845085
move_opt_priv_to_result_priv(opt, result);
50855086
}
50865087

t/t6406-merge-attr.sh

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ test_expect_success !WINDOWS 'custom merge driver that is killed with a signal'
185185
186186
>./please-abort &&
187187
echo "* merge=custom" >.gitattributes &&
188-
test_must_fail git merge main 2>err &&
188+
test_expect_code 2 git merge main 2>err &&
189189
grep "^error: failed to execute internal merge" err &&
190190
git ls-files -u >output &&
191191
git diff --name-only HEAD >>output &&
@@ -261,4 +261,44 @@ test_expect_success 'binary files with union attribute' '
261261
grep -i "warning.*cannot merge.*HEAD vs. bin-main" output
262262
'
263263

264+
test_expect_success !WINDOWS 'custom merge driver that is killed with a signal on recursive merge' '
265+
test_when_finished "rm -f output please-abort" &&
266+
test_when_finished "git checkout side" &&
267+
268+
git reset --hard anchor &&
269+
270+
git checkout -b base-a main^ &&
271+
echo base-a >text &&
272+
git commit -m base-a text &&
273+
274+
git checkout -b base-b main^ &&
275+
echo base-b >text &&
276+
git commit -m base-b text &&
277+
278+
git checkout -b recursive-a base-a &&
279+
test_must_fail git merge base-b &&
280+
echo recursive-a >text &&
281+
git add text &&
282+
git commit -m recursive-a &&
283+
284+
git checkout -b recursive-b base-b &&
285+
test_must_fail git merge base-a &&
286+
echo recursive-b >text &&
287+
git add text &&
288+
git commit -m recursive-b &&
289+
290+
git config --replace-all \
291+
merge.custom.driver "./custom-merge %O %A %B 0 %P %S %X %Y" &&
292+
git config --replace-all \
293+
merge.custom.name "custom merge driver for testing" &&
294+
295+
>./please-abort &&
296+
echo "* merge=custom" >.gitattributes &&
297+
test_expect_code 2 git merge recursive-a 2>err &&
298+
grep "^error: failed to execute internal merge" err &&
299+
git ls-files -u >output &&
300+
git diff --name-only HEAD >>output &&
301+
test_must_be_empty output
302+
'
303+
264304
test_done

0 commit comments

Comments
 (0)