Hi Alban

On 12/02/2019 15:21, Alban Gruin wrote:
> 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:
>>> -%<-
>>> 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 */
>>
>>> +           --commands.nr;
>>
>> Style: commands.nr--
>>
>>> +   }
>>> +
>>>     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.
>>
>>> +   string_list_clear(&commands, 1);
>>
>> As we don't use item.util I think the second argument would be better as 0.
>>
>>>     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.

Good find, that sounds like a much better solution.

> 
>>> 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.
>        */
> 

That sounds good

Best Wishes

Phillip

>>> +   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
> 

Reply via email to