sequencer: factor out parsing of todo commands

Move the code that parses todo commands into a separate function so
that it can be shared with "git status" in the next commit. As we
know the input is NUL terminated we do not pass a pointer to the end
of the line and instead test for a blank line by looking for NUL, CR
LF, or LF. We use starts_with() instead of starts_with_mem() for the
same reason. This results in slightly different behavior when there
a CR at the start of the line that is not followed by LF. Previously
such a line was treated as a comment rather than an invalid line.

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Phillip Wood
2026-06-22 09:36:03 +01:00
committed by Junio C Hamano
parent 94f057755b
commit fba9390be1
2 changed files with 35 additions and 12 deletions

View File

@@ -2627,6 +2627,27 @@ static int is_command(enum todo_command command, const char **bol)
return 0;
}
bool sequencer_parse_todo_command(const char **p, enum todo_command *cmd)
{
const char *s = *p;
for (int i = 0; i < TODO_COMMENT; i++)
if (is_command(i, p)) {
*cmd = i;
return true;
}
if (starts_with(s, comment_line_str)) {
*cmd = TODO_COMMENT;
return true;
} else if (s[0] == '\n' || (s[0] == '\r' && s[1] == '\n') || !s[0]) {
*cmd = TODO_COMMENT;
return true;
}
return false;
}
static int check_label_or_ref_arg(enum todo_command command, const char *arg)
{
switch (command) {
@@ -2716,30 +2737,24 @@ static int parse_insn_line(struct repository *r, struct replay_opts *opts,
{
struct object_id commit_oid;
char *end_of_object_name;
int i, saved, status, padding;
int saved, status, padding;
item->flags = 0;
/* left-trim */
bol += strspn(bol, " \t");
if (bol == eol || *bol == '\r' || starts_with_mem(bol, eol - bol, comment_line_str)) {
item->command = TODO_COMMENT;
if (!sequencer_parse_todo_command(&bol, &item->command))
return error(_("invalid command '%.*s'"),
(int)strcspn(bol, " \t\r\n"), bol);
if (item->command == TODO_COMMENT) {
item->commit = NULL;
item->arg_offset = bol - buf;
item->arg_len = eol - bol;
return 0;
}
for (i = 0; i < TODO_COMMENT; i++)
if (is_command(i, &bol)) {
item->command = i;
break;
}
if (i >= TODO_COMMENT)
return error(_("invalid command '%.*s'"),
(int)strcspn(bol, " \t\r\n"), bol);
/* Eat up extra spaces/ tabs before object name */
padding = strspn(bol, " \t");
bol += padding;

View File

@@ -262,6 +262,14 @@ int read_author_script(const char *path, char **name, char **email, char **date,
int write_basic_state(struct replay_opts *opts, const char *head_name,
struct commit *onto, const struct object_id *orig_head);
void sequencer_post_commit_cleanup(struct repository *r, int verbose);
/*
* Try to parse the todo command pointed to by *p. On success sets cmd,
* advances p and returns true. On failure returns false, leaves p and
* cmd unchanged.
*/
bool sequencer_parse_todo_command(const char **p, enum todo_command *cmd);
int sequencer_get_last_command(struct repository* r,
enum replay_action *action);
int sequencer_determine_whence(struct repository *r, enum commit_whence *whence);