sequencer: clean up pseudo refs with REF_NO_DEREF

When cleaning up the state-tracking pseudorefs CHERRY_PICK_HEAD or REVERT_HEAD we do not set REF_NO_DEREF. In the unlikely case where those refs are a symref we would thus end up deleting the symref targets, and not the symrefs themselves. Harden the code to use REF_NO_DEREF to fix this. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Jan 19, 2024 at 11:39 UTC 821f6632b091dc59562f74a0c74005b34319a2e7
1 file changed +7 -7
sequencer.c
+7 -7
@@ -474,7 +474,7 @@ static void print_advice(struct repository *r, int show_hint,
474 * of the commit itself so remove CHERRY_PICK_HEAD
475 */
476 refs_delete_ref(get_main_ref_store(r), "", "CHERRY_PICK_HEAD",
477 - NULL, 0);
477 + NULL, REF_NO_DEREF);
478 return;
479 }
480
@@ -1667,7 +1667,7 @@ static int do_commit(struct repository *r,
1667 strbuf_release(&sb);
1668 if (!res) {
1669 refs_delete_ref(get_main_ref_store(r), "",
1670 - "CHERRY_PICK_HEAD", NULL, 0);
1670 + "CHERRY_PICK_HEAD", NULL, REF_NO_DEREF);
1671 unlink(git_path_merge_msg(r));
1672 if (!is_rebase_i(opts))
1673 print_commit_summary(r, NULL, &oid,
@@ -2406,7 +2406,7 @@ static int do_pick_commit(struct repository *r,
2406 } else if (allow == 2) {
2407 drop_commit = 1;
2408 refs_delete_ref(get_main_ref_store(r), "", "CHERRY_PICK_HEAD",
2409 - NULL, 0);
2409 + NULL, REF_NO_DEREF);
2410 unlink(git_path_merge_msg(r));
2411 unlink(git_path_auto_merge(r));
2412 fprintf(stderr,
@@ -2802,7 +2802,7 @@ void sequencer_post_commit_cleanup(struct repository *r, int verbose)
2802
2803 if (refs_ref_exists(get_main_ref_store(r), "CHERRY_PICK_HEAD")) {
2804 if (!refs_delete_ref(get_main_ref_store(r), "",
2805 - "CHERRY_PICK_HEAD", NULL, 0) &&
2805 + "CHERRY_PICK_HEAD", NULL, REF_NO_DEREF) &&
2806 verbose)
2807 warning(_("cancelling a cherry picking in progress"));
2808 opts.action = REPLAY_PICK;
@@ -2811,7 +2811,7 @@ void sequencer_post_commit_cleanup(struct repository *r, int verbose)
2811
2812 if (refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD")) {
2813 if (!refs_delete_ref(get_main_ref_store(r), "", "REVERT_HEAD",
2814 - NULL, 0) &&
2814 + NULL, REF_NO_DEREF) &&
2815 verbose)
2816 warning(_("cancelling a revert in progress"));
2817 opts.action = REPLAY_REVERT;
@@ -4116,7 +4116,7 @@ static int do_merge(struct repository *r,
4116
4117 strbuf_release(&ref_name);
4118 refs_delete_ref(get_main_ref_store(r), "", "CHERRY_PICK_HEAD",
4119 - NULL, 0);
4119 + NULL, REF_NO_DEREF);
4120 rollback_lock_file(&lock);
4121
4122 ret = run_command(&cmd);
@@ -5108,7 +5108,7 @@ static int commit_staged_changes(struct repository *r,
5108 if (refs_ref_exists(get_main_ref_store(r),
5109 "CHERRY_PICK_HEAD") &&
5110 refs_delete_ref(get_main_ref_store(r), "",
5111 - "CHERRY_PICK_HEAD", NULL, 0))
5111 + "CHERRY_PICK_HEAD", NULL, REF_NO_DEREF))
5112 return error(_("could not remove CHERRY_PICK_HEAD"));
5113 if (unlink(git_path_merge_msg(r)) && errno != ENOENT)
5114 return error_errno(_("could not remove '%s'"),