From: Phillip Wood Date: Thu, 11 May 2023 14:13:44 GMT Subject: Re: [PATCH 2/2] rebase -r: fix the total number shown in the progress Message-ID: In-Reply-To: Hi Dscho On 10/05/2023 23:55, Johannes Schindelin via GitGitGadget wrote: > From: Johannes Schindelin > > For regular, non-`--rebase-merges` runs, there is very little work to do > for the parser when determining the total number of commands in a rebase > script: it is simply the number of lines after stripping the commented > lines and then trimming the trailing empty line, if any. > > The `--rebase-merges` mode complicates things by introducing empty lines > and comments in the middle of the script. These should _not_ be counted > as commands, and indeed, when an interactive rebase is interrupted and > subsequently resumed, the total number of commands can magically shrink, > sometimes dramatically. > > The reason for this strange behavior is that empty lines _are_ counted > in `edit_todo_list()` (but not the comments, as they are stripped via > `strbuf_stripspace(..., 1)`, which is a bug. > > Let's fix this so that the correct total number is shown from the > get-go, by carefully adjusting it according to what's in the rebase > script. Extra care needs to be taken in case the user edits the script: > the number of commands might be different after the user edited than > beforehand. > > Note: Even though commented lines are skipped in `edit_todo_list()`, we > still need to handle `TODO_COMMENT` items by decrementing the > already-incremented `total_nr` again: empty lines are also marked as > `TODO_COMMENT`. > > Signed-off-by: Johannes Schindelin > --- > sequencer.c | 12 ++++++++---- > t/t3430-rebase-merges.sh | 7 +++++++ > 2 files changed, 15 insertions(+), 4 deletions(-) > > diff --git a/sequencer.c b/sequencer.c > index f5d89abdc5e..46dd07df0f2 100644 > --- a/sequencer.c > +++ b/sequencer.c > @@ -2609,7 +2609,7 @@ int todo_list_parse_insn_buffer(struct repository *r, char *buf, > char *p = buf, *next_p; > int i, res = 0, fixup_okay = file_exists(rebase_path_done()); > > - todo_list->current = todo_list->nr = 0; > + todo_list->current = todo_list->nr = todo_list->total_nr = 0; > > for (i = 1; *p; i++, p = next_p) { > char *eol = strchrnul(p, '\n'); > @@ -2628,7 +2628,8 @@ int todo_list_parse_insn_buffer(struct repository *r, char *buf, > item->arg_offset = p - buf; > item->arg_len = (int)(eol - p); > item->commit = NULL; > - } > + } else if (item->command == TODO_COMMENT) > + todo_list->total_nr--; This feels a bit fragile, I think it would be better to count the commands properly in the first place rather than adjusting the total here. We could do that by not incrementing "todo_list->total_nr" in append_new_todo() and then doing if (item->command != TODO_COMMENT) todo_list->total_nr++; here. We may want to stop counting invalid commands as well by only counting commands whre "item->command < TODO_COMMENT". > > if (fixup_okay) > ; /* do nothing */ > @@ -6039,7 +6040,7 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla > struct todo_list new_todo = TODO_LIST_INIT; > struct strbuf *buf = &todo_list->buf, buf2 = STRBUF_INIT; > struct object_id oid = onto->object.oid; > - int res; > + int new_total_nr, res; > > find_unique_abbrev_r(shortonto, &oid, DEFAULT_ABBREV); > > @@ -6066,6 +6067,7 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla > return error(_("nothing to do")); > } > > + new_total_nr = todo_list->total_nr - count_commands(todo_list); > res = edit_todo_list(r, todo_list, &new_todo, shortrevisions, > shortonto, flags); > if (res == -1) > @@ -6088,11 +6090,13 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla > return -1; > } > > + new_total_nr += count_commands(&new_todo); > + new_todo.total_nr = new_total_nr; > + > /* Expand the commit IDs */ > todo_list_to_strbuf(r, &new_todo, &buf2, -1, 0); > strbuf_swap(&new_todo.buf, &buf2); > strbuf_release(&buf2); > - new_todo.total_nr -= new_todo.nr; I think if we just change this line to new_todo.total_nr = 0; we don't need any other changes to this function. This is because complete_action() is only called at the start of a rebase so we don't need to worry about "total_nr" including commands that have already been executed. The reason we need to set it to zero here is that we re-parse the todo list below which increments "total_nr" by the number of commands parsed. Thanks for working on this. Best Wishes Phillip > if (todo_list_parse_insn_buffer(r, new_todo.buf.buf, &new_todo) < 0) > BUG("invalid todo list after expanding IDs:\n%s", > new_todo.buf.buf); > diff --git a/t/t3430-rebase-merges.sh b/t/t3430-rebase-merges.sh > index f351701fec2..8da99a075dc 100755 > --- a/t/t3430-rebase-merges.sh > +++ b/t/t3430-rebase-merges.sh > @@ -517,4 +517,11 @@ test_expect_success '--rebase-merges with message matched with onto label' ' > EOF > ' > > +test_expect_success 'progress shows the correct total' ' > + git checkout -b progress H && > + git rebase --rebase-merges --force-rebase --verbose A 2> err && > + grep "^Rebasing.*14.$" err >progress && > + test_line_count = 14 progress > +' > + > test_done