Re: [PATCH v7 07/16] sequencer: refactor sequencer_add_exec_commands() to work on a todo_list
From: Alban Gruin <hidden>
Date: 2019-02-12 15:21:35
Hi Phillip, Le 12/02/2019 à 11:52, Phillip Wood a écrit :
Hi Alban I think this is almost there, I've got a couple of small comments below. On 10/02/2019 13:26, Alban Gruin wrote:quoted
-%<-diff --git a/builtin/rebase--interactive.c b/builtin/rebase--interactive.c index df19ccaeb9..c131fd4a27 100644 --- a/builtin/rebase--interactive.c +++ b/builtin/rebase--interactive.c -%<-@@ -221,6 +222,11 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix) warning(_("--[no-]rebase-cousins has no effect without " "--rebase-merges")); + if (cmd && *cmd) { + string_list_split(&commands, cmd, '\n', -1);I'd suggest a comment along the lines of /* As cmd always ends with a newline the last item is empty */quoted
+ --commands.nr;Style: commands.nr--quoted
+ } + switch (command) { case NONE: if (!onto && !upstream)@@ -228,7 +234,7 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix) ret = do_interactive_rebase(&opts, flags, switch_to, upstream, onto, onto_name, squash_onto, head_name, restrict_revision, - raw_strategies, cmd, autosquash); + raw_strategies, &commands, autosquash); break; case SKIP: { struct string_list merge_rr = STRING_LIST_INIT_DUP;@@ -262,11 +268,12 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix) ret = rearrange_squash(the_repository); break; case ADD_EXEC: - ret = sequencer_add_exec_commands(the_repository, cmd); + ret = sequencer_add_exec_commands(the_repository, &commands); break; default: BUG("invalid command '%d'", command); }Before freeing the string list it would be good to reset the number of items with commands.nr++ (with a comment explaining why) so the NUL in the last item gets freed.quoted
+ string_list_clear(&commands, 1);As we don't use item.util I think the second argument would be better as 0.quoted
return !!ret; }
FWIW I just stumbled across string_list_remove_empty_items(), which seems to do exactly the same thing, but that way we don’t have to do this kind of hacks.
quoted
diff --git a/sequencer.c b/sequencer.c index 99e12c751e..82ca3432cd 100644 --- a/sequencer.c +++ b/sequencer.c@@ -4505,21 +4505,27 @@ int sequencer_make_script(struct repository *r, FILE *out, * Add commands after pick and (series of) squash/fixup commands * in the todo list. */ -int sequencer_add_exec_commands(struct repository *r, - const char *commands) +static void todo_list_add_exec_commands(struct todo_list *todo_list, + struct string_list *commands) { - const char *todo_file = rebase_path_todo(); - struct todo_list todo_list = TODO_LIST_INIT; - struct strbuf *buf = &todo_list.buf; - size_t offset = 0, commands_len = strlen(commands); - int i, insert; + struct strbuf *buf = &todo_list->buf; + size_t base_offset = buf->len; + int i, insert, nr = 0, alloc = 0; + struct todo_item *items = NULL, *base_items = NULL; - if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0) - return error(_("could not read '%s'."), todo_file); + base_items = xcalloc(commands->nr, sizeof(struct todo_item)); + for (i = 0; i < commands->nr; i++) { + size_t command_len = strlen(commands->items[i].string); - if (todo_list_parse_insn_buffer(r, todo_list.buf.buf, &todo_list)) { - todo_list_release(&todo_list); - return error(_("unusable todo list: '%s'"), todo_file); + strbuf_addstr(buf, commands->items[i].string); + strbuf_addch(buf, '\n'); + + base_items[i].command = TODO_EXEC; + base_items[i].offset_in_buf = base_offset; + base_items[i].arg_offset = base_offset + strlen("exec "); + base_items[i].arg_len = command_len - strlen("exec "); + + base_offset += command_len + 1; } /*@@ -4527,39 +4533,60 @@ int sequencer_add_exec_commands(struct repository *r, * are considered part of the pick, so we insert the commands *after* * those chains if there are any. */ - insert = -1; - for (i = 0; i < todo_list.nr; i++) { - enum todo_command command = todo_list.items[i].command; - - if (insert >= 0) { - /* skip fixup/squash chains */ - if (command == TODO_COMMENT) - continue; - else if (is_fixup(command)) { - insert = i + 1; - continue; - } - strbuf_insert(buf, - todo_list.items[insert].offset_in_buf + - offset, commands, commands_len); - offset += commands_len; - insert = -1;I like the simplification of using insert as a flag. Perhaps we should document the assumptions. Maybe something like We insert the exec commands immediately after rearranging any fixups and before the user edits the list. This means that a fixup chain can never contain comments (any comments are empty picks that have been commented out the the user did not specify --keep-empty) and so it is safe to insert the exec command without looking at the command following the comment.
I slightly reworded this and added it to the existing comment just before the for loop: /* * Insert <commands> after every pick. Here, fixup/squash chains * are considered part of the pick, so we insert the commands *after* * those chains if there are any. * * As we insert the exec commands immediatly after rearranging * any fixups and before the user edits the list, a fixup chain * can never contain comments (any comments are empty picks that * have been commented out because the user did not specify * --keep-empty). So, it is safe to insert an exec command * without looking at the command following a comment. */
quoted
+ insert = 0; + for (i = 0; i < todo_list->nr; i++) { + enum todo_command command = todo_list->items[i].command; + if (insert && !is_fixup(command)) { + ALLOC_GROW(items, nr + commands->nr, alloc); + COPY_ARRAY(items + nr, base_items, commands->nr); + nr += commands->nr; + + insert = 0; } - if (command == TODO_PICK || command == TODO_MERGE) - insert = i + 1; + ALLOC_GROW(items, nr + 1, alloc); + items[nr++] = todo_list->items[i]; + + if (command == TODO_PICK || command == TODO_MERGE || is_fixup(command))I'm not sure what the is_fixup() is for, if the command is a fixup then it will have been preceded by a pick or merge so insert will already be 1 I feel a bit mean suggesting a reroll when we're on v7 already but I think these clean-ups would improve the maintainability of the code. I'll take a look at the rest of the changes to this series sometime this week. Best Wishes Phillip
Cheers, Alban