Hi Junio,
Le 11/07/2018 à 00:33, Junio C Hamano a écrit :
> Alban Gruin <[email protected]> writes:
>> - complete_action
>> + exec git rebase--helper --complete-action "$shortrevisions"
>> "$onto_name" \
>> + "$shortonto" "$orig_head" "$cmd" $allow_empty_message \
>> + ${autosquash:+--autosquash} ${keep_empty:+--keep-empty} \
>> + ${verbose:+--verbose} ${force_rebase:+--no-ff}
>
> The $allow_empty_message and later options are all dashed ones.
> git-rebase.sh gives us either empty or --allow-empty-message in the
> variable for $allow_empty_message, and if you follow suit to prepare
> all the other variables that way, the ugly ${frotz+=--frotz} dance
> will all become unnecessary here.
>
Good idea.
>> +int complete_action(struct replay_opts *opts, unsigned flags,
>> + const char *shortrevisions, const char *onto_name,
>> + const char *onto, const char *orig_head, const char *cmd,
>> + unsigned autosquash, unsigned keep_empty)
>> +{
>> + const char *shortonto, *todo_file = rebase_path_todo();
>> + struct todo_list todo_list = TODO_LIST_INIT;
>> + struct strbuf *buf = &(todo_list.buf);
>> + struct object_id oid;
>> + struct stat st;
>> +
>> + get_oid(onto, &oid);
>> + shortonto = find_unique_abbrev(&oid, DEFAULT_ABBREV);
>> +
>> + if (!lstat(todo_file, &st) && st.st_size == 0 &&
>> + write_message("noop\n", 5, todo_file, 0))
>> + return error_errno(_("could not write '%s'"), todo_file);
>
> Wait a minute... thinking back to the early "age-old ommission"
> topic, can the todo file be a non-empty file that does not have any
> command (e.g. just a single blank line, or full of comments and
> nothing else)? The original wouldn't have added "noop" and then the
> first "do we have anything to do?" check would still have been
> necessary, which would mean that ff74126c's not removing the first
> check was actually not a bug but was a cautious and sensible thing
> to do, and removal of that exact check by this commit becomes a
> regression. So,... can the todo file be a non-empty file that does
> not have any command in it at this point?
>
Hum, yes, if the commits are empty, and if rebase was invoked without
the `--keep-empty` flag. In this case, it would die with the message
“Nothing to do”, instead of dropping the commit altogether.
I will add a test case in the next iteration.
>> + if (autosquash && rearrange_squash())
>> + return 0;
>
> The original, when rearrange-squash failed, exited with failure,
> like so:
>
> - test -z "$autosquash" || git rebase--helper --rearrange-squash || exit
>
> Now this function returns success when rearrange_squash fails.
> Is that intended?
>
Yes, it is. I just saw in the man page that `exit` returns the last
exit status.
>> + if (cmd && *cmd)
>
> Shouldn't it be a BUG (programming error) if cmd == NULL? I thought
> the caller of complete_action() in this patch insisted that it got
> argc == 6 or something, so *cmd might be NUL but cmd would never be
> NULL if I understand your code correctly. IOW, shouldn't the line
> be more like:
>
> if (!cmd)
> BUG("...");
> if (*cmd)
>
> ?
>
I don’t know, it’s not really problematic if cmd is NULL. And I think
that when interactive rebase will be a builtin, it will be possible for
cmd to be NULL.
>
>> + if (strbuf_read_file(buf, todo_file, 0) < 0)
>> + return error_errno(_("could not read '%s'."), todo_file);
>> + if (parse_insn_buffer(buf->buf, &todo_list)) {
>
> Nice that we have parse* function. We do not have to work with
> stripspace plus "wc -l" ;-).
>
>> + todo_list_release(&todo_list);
>> + return error(_("unusable todo list: '%s'"), todo_file);
>
> When the users see this error message, is it easy for them to
> diagnose what went wrong (e.g. has parse_insn_buffer() already
> issued some message to help pinpoint which insn in the todo list is
> misspelt, for example)?
>
Yes, parse_insn_buffer() will say which line caused the error. But at
this point, the user should not have changed the todo-list, so this
error should never appear.
Perhaps this is a good use case of BUG()?
>> + }
>> +
>> + strbuf_addch(buf, '\n');
>> + strbuf_commented_addf(buf, Q_("Rebase %s onto %s (%d command)",
>> + "Rebase %s onto %s (%d commands)",
>> + todo_list.nr),
>> + shortrevisions, shortonto, todo_list.nr);
>> + append_todo_help(0, keep_empty, buf);
>> +
>> + if (write_message(buf->buf, buf->len, todo_file, 0)) {
>> + todo_list_release(&todo_list);
>> + return error_errno(_("could not write '%s'"), todo_file);
>> + }
>> + copy_file(rebase_path_todo_backup(), todo_file, 0666);
>> + transform_todos(flags | TODO_LIST_SHORTEN_IDS);
>> +
>
> It is a bit sad that we are mostly working on the byte array
> buf->buf (or external file touched by various helper functions we
> call), even though we have a perfectly usable parsed representation
> in todo_list structure in all of the above and the rest of this
> function.
>
> It might be better to grab todo_list.nr into a local simple integer
> variable immediately after parse_insn_buffer() returns and then call
> todo_list_release() on todo_list, as the parsed todo-list is only
> used for two purposes (i.e. detecting format error by seeing if
> parser returns success, and seeing how many insns are on the todo
> list by checking todo_list.nr field) and nothing else. By releasing
> the otherwise unused todo_list early, you do not have to sprinkle
> various error return codepaths with calls to todo_list_release().
>
> That incidentally would manage too high expectation from readers of
> the code as well ;-).
>
Unfortunately, this strbuf is part of the todo_list, and it will be
freed if I call todo_list_release().
:/
Cheers,
Alban