From: Phillip Wood Date: Tue, 23 Jun 2026 15:53:56 +0000 (+0100) Subject: sequencer: factor out parsing of todo commands X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=10c2678a2bfbd2a3e8d0a3623d1b71b6cc916253;p=thirdparty%2Fgit.git 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 Signed-off-by: Junio C Hamano --- diff --git a/sequencer.c b/sequencer.c index b7d8dca47f..b8e860434a 100644 --- a/sequencer.c +++ b/sequencer.c @@ -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; diff --git a/sequencer.h b/sequencer.h index a6fa670c7c..28fabef926 100644 --- a/sequencer.h +++ b/sequencer.h @@ -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);