]> git.ipfire.org Git - thirdparty/git.git/commitdiff
sequencer: factor out parsing of todo commands
authorPhillip Wood <phillip.wood@dunelm.org.uk>
Fri, 1 May 2026 15:16:38 +0000 (16:16 +0100)
committerJunio C Hamano <gitster@pobox.com>
Fri, 1 May 2026 22:00:50 +0000 (07:00 +0900)
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>
sequencer.c
sequencer.h

index b7d8dca47f4a58a7b67340dabea99a0f3ace86d0..b8e860434a89054d5ddb99e996874add88848aef 100644 (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;
index a6fa670c7c1f99a8bcd68f58540ee793b67894bc..28fabef926f35126958a7bcace6810a80b2420f2 100644 (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);