sequencer: unify label lookup

The arguments to the `reset` and `merge` commands may be a label created with a `label` command or an arbitrary commit name. The `merge` command uses the lookup_label() function to lookup its arguments but `reset` has a slightly different version of that function in do_reset(). Reduce this code duplication by calling lookup_label() from do_reset() as well. This change improves the behavior of `reset` when the argument is a tree. Previously `reset` would accept a tree only for the rebase to fail with update_ref failed for ref 'HEAD': cannot update ref 'HEAD': trying to write non-commit object da5497437fd67ca928333aab79c4b4b55036ea66 to branch 'HEAD' Using lookup_label() means do_reset() will now error out straight away if its argument is not a commit. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Taylor Blau <me@ttaylorr.com>

Phillip Wood committed Nov 10, 2022 at 16:43 UTC 82766b29611aea7c3fb42a99debfba1436852d38
2 files changed +33 -24
sequencer.c
+25 -24
@@ -3694,6 +3694,26 @@ static const char *reflog_message(struct replay_opts *opts,
3694 return buf.buf;
3695 }
3696
3697 +static struct commit *lookup_label(const char *label, int len,
3698 + struct strbuf *buf)
3699 +{
3700 + struct commit *commit;
3701 +
3702 + strbuf_reset(buf);
3703 + strbuf_addf(buf, "refs/rewritten/%.*s", len, label);
3704 + commit = lookup_commit_reference_by_name(buf->buf);
3705 + if (!commit) {
3706 + /* fall back to non-rewritten ref or commit */
3707 + strbuf_splice(buf, 0, strlen("refs/rewritten/"), "", 0);
3708 + commit = lookup_commit_reference_by_name(buf->buf);
3709 + }
3710 +
3711 + if (!commit)
3712 + error(_("could not resolve '%s'"), buf->buf);
3713 +
3714 + return commit;
3715 +}
3716 +
3717 static int do_reset(struct repository *r,
3718 const char *name, int len,
3719 struct replay_opts *opts)
@@ -3725,6 +3745,7 @@ static int do_reset(struct repository *r,
3745 oidcpy(&oid, &opts->squash_onto);
3746 } else {
3747 int i;
3748 + struct commit *commit;
3749
3750 /* Determine the length of the label */
3751 for (i = 0; i < len; i++)
@@ -3732,12 +3753,12 @@ static int do_reset(struct repository *r,
3753 break;
3754 len = i;
3755
3735 - strbuf_addf(&ref_name, "refs/rewritten/%.*s", len, name);
3736 - if (get_oid(ref_name.buf, &oid) &&
3737 - get_oid(ref_name.buf + strlen("refs/rewritten/"), &oid)) {
3738 - ret = error(_("could not read '%s'"), ref_name.buf);
3756 + commit = lookup_label(name, len, &ref_name);
3757 + if (!commit) {
3758 + ret = -1;
3759 goto cleanup;
3760 }
3761 + oid = commit->object.oid;
3762 }
3763
3764 setup_unpack_trees_porcelain(&unpack_tree_opts, "reset");
@@ -3784,26 +3805,6 @@ cleanup:
3805 return ret;
3806 }
3807
3787 -static struct commit *lookup_label(const char *label, int len,
3788 - struct strbuf *buf)
3789 -{
3790 - struct commit *commit;
3791 -
3792 - strbuf_reset(buf);
3793 - strbuf_addf(buf, "refs/rewritten/%.*s", len, label);
3794 - commit = lookup_commit_reference_by_name(buf->buf);
3795 - if (!commit) {
3796 - /* fall back to non-rewritten ref or commit */
3797 - strbuf_splice(buf, 0, strlen("refs/rewritten/"), "", 0);
3798 - commit = lookup_commit_reference_by_name(buf->buf);
3799 - }
3800 -
3801 - if (!commit)
3802 - error(_("could not resolve '%s'"), buf->buf);
3803 -
3804 - return commit;
3805 -}
3806 -
3808 static int do_merge(struct repository *r,
3809 struct commit *commit,
3810 const char *arg, int arg_len,
t/t3430-rebase-merges.sh
+8
@@ -138,6 +138,14 @@ test_expect_success '`reset` refuses to overwrite untracked files' '
138 git rebase --abort
139 '
140
141 +test_expect_success '`reset` rejects trees' '
142 + test_when_finished "test_might_fail git rebase --abort" &&
143 + test_must_fail env GIT_SEQUENCE_EDITOR="echo reset A^{tree} >" \
144 + git rebase -i B C >out 2>err &&
145 + grep "object .* is a tree" err &&
146 + test_must_be_empty out
147 +'
148 +
149 test_expect_success 'failed `merge -C` writes patch (may be rescheduled, too)' '
150 test_when_finished "test_might_fail git rebase --abort" &&
151 git checkout -b conflicting-merge A &&