Skip to content

Commit 16b3880

Browse files
phillipwoodgitster
authored andcommitted
rebase -i: check labels and refs when parsing todo list
Check that the argument to the "label" and "update-ref" commands is a valid refname when the todo list is parsed rather than waiting until the command is executed. This means that the user can deal with any errors at the beginning of the rebase rather than having it stop halfway through due to a typo in a label name. The "update-ref" command is changed to reject single level refs as it is all to easy to type "update-ref branch" which is incorrect rather than "update-ref refs/heads/branch" Note that it is not straight forward to check the arguments to "reset" and "merge" commands as they may be any revision, not just a refname and we do not have an equivalent of check_refname_format() for revisions. Helped-by: Derrick Stolee <[email protected]> Signed-off-by: Phillip Wood <[email protected]> Acked-by: Derrick Stolee <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent d9d677b commit 16b3880

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

sequencer.c

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2487,6 +2487,34 @@ static int is_command(enum todo_command command, const char **bol)
24872487
(*bol = p));
24882488
}
24892489

2490+
static int check_label_or_ref_arg(enum todo_command command, const char *arg)
2491+
{
2492+
switch (command) {
2493+
case TODO_LABEL:
2494+
/*
2495+
* '#' is not a valid label as the merge command uses it to
2496+
* separate merge parents from the commit subject.
2497+
*/
2498+
if (!strcmp(arg, "#") ||
2499+
check_refname_format(arg, REFNAME_ALLOW_ONELEVEL))
2500+
return error(_("'%s' is not a valid label"), arg);
2501+
break;
2502+
2503+
case TODO_UPDATE_REF:
2504+
if (check_refname_format(arg, REFNAME_ALLOW_ONELEVEL))
2505+
return error(_("'%s' is not a valid refname"), arg);
2506+
if (check_refname_format(arg, 0))
2507+
return error(_("update-ref requires a fully qualified "
2508+
"refname e.g. refs/heads/%s"), arg);
2509+
break;
2510+
2511+
default:
2512+
BUG("unexpected todo_command");
2513+
}
2514+
2515+
return 0;
2516+
}
2517+
24902518
static int parse_insn_line(struct repository *r, struct todo_item *item,
24912519
const char *buf, const char *bol, char *eol)
24922520
{
@@ -2535,10 +2563,19 @@ static int parse_insn_line(struct repository *r, struct todo_item *item,
25352563

25362564
if (item->command == TODO_EXEC || item->command == TODO_LABEL ||
25372565
item->command == TODO_RESET || item->command == TODO_UPDATE_REF) {
2566+
int ret = 0;
2567+
25382568
item->commit = NULL;
25392569
item->arg_offset = bol - buf;
25402570
item->arg_len = (int)(eol - bol);
2541-
return 0;
2571+
if (item->command == TODO_LABEL ||
2572+
item->command == TODO_UPDATE_REF) {
2573+
saved = *eol;
2574+
*eol = '\0';
2575+
ret = check_label_or_ref_arg(item->command, bol);
2576+
*eol = saved;
2577+
}
2578+
return ret;
25422579
}
25432580

25442581
if (item->command == TODO_FIXUP) {

t/t3404-rebase-interactive.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2072,6 +2072,7 @@ test_expect_success '--update-refs: --edit-todo with no update-ref lines' '
20722072
'
20732073

20742074
test_expect_success '--update-refs: check failed ref update' '
2075+
test_when_finished "test_might_fail git rebase --abort" &&
20752076
git checkout -B update-refs-error no-conflict-branch &&
20762077
git branch -f base HEAD~4 &&
20772078
git branch -f first HEAD~3 &&
@@ -2123,6 +2124,28 @@ test_expect_success '--update-refs: check failed ref update' '
21232124
test_cmp expect err.trimmed
21242125
'
21252126

2127+
test_expect_success 'bad labels and refs rejected when parsing todo list' '
2128+
test_when_finished "test_might_fail git rebase --abort" &&
2129+
cat >todo <<-\EOF &&
2130+
exec >execed
2131+
label #
2132+
label :invalid
2133+
update-ref :bad
2134+
update-ref topic
2135+
EOF
2136+
rm -f execed &&
2137+
(
2138+
set_replace_editor todo &&
2139+
test_must_fail git rebase -i HEAD 2>err
2140+
) &&
2141+
grep "'\''#'\'' is not a valid label" err &&
2142+
grep "'\'':invalid'\'' is not a valid label" err &&
2143+
grep "'\'':bad'\'' is not a valid refname" err &&
2144+
grep "update-ref requires a fully qualified refname e.g. refs/heads/topic" \
2145+
err &&
2146+
test_path_is_missing execed
2147+
'
2148+
21262149
# This must be the last test in this file
21272150
test_expect_success '$EDITOR and friends are unchanged' '
21282151
test_editor_unchanged

0 commit comments

Comments
 (0)