Message ID | 0d89c506192a84822a3fbd6c76befac187129ad4.1632410782.git.gitgitgadget@gmail.com (mailing list archive) |
---|---|
State | Accepted |
Commit | 2b88fe0603a93314b96f94b22e197b7b1b838c80 |
Headers | show |
Series | rebase -i: a couple of small improvements | expand |
"Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes: > .... Instead of relying on stat > data this patch simply reads the possibly edited todo list and > compares it to the original with memcmp(). This is much faster than > reparsing the todo list each time. Nice. Is that an egg of Columbus or what ;-) > + if (strbuf_read_file_or_whine(&buf, get_todo_path(opts)) < 0) > + return -1; > + offset = get_item_line_offset(todo_list, todo_list->current + 1); > + if (buf.len != todo_list->buf.len - offset || > + memcmp(buf.buf, todo_list->buf.buf + offset, buf.len)) { > /* Reread the todo file if it has changed. */ > todo_list_release(todo_list); > if (read_populate_todo(r, todo_list, opts)) As we already have the contents of hte file in the buffer, we could further refactor the code around read_populate_todo() to tell it not to reopen and reread the rebase-todo file (which risks toctou race), but that is OK for now, I would think. > @@ -4271,6 +4267,7 @@ static int reread_todo_if_changed(struct repository *r, > /* `current` will be incremented on return */ > todo_list->current = -1; > } > + strbuf_release(&buf); > > return 0; > } > diff --git a/sequencer.h b/sequencer.h > index d57d8ea23d7..cdeb0c6be47 100644 > --- a/sequencer.h > +++ b/sequencer.h > @@ -116,7 +116,6 @@ struct todo_list { > struct todo_item *items; > int nr, alloc, current; > int done_nr, total_nr; > - struct stat_data stat; Good riddance ;-) Will queue. Thanks.
On 24/09/2021 17:13, Junio C Hamano wrote: > "Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes: > >> .... Instead of relying on stat >> data this patch simply reads the possibly edited todo list and >> compares it to the original with memcmp(). This is much faster than >> reparsing the todo list each time. > > Nice. Is that an egg of Columbus or what ;-) > >> + if (strbuf_read_file_or_whine(&buf, get_todo_path(opts)) < 0) >> + return -1; >> + offset = get_item_line_offset(todo_list, todo_list->current + 1); >> + if (buf.len != todo_list->buf.len - offset || >> + memcmp(buf.buf, todo_list->buf.buf + offset, buf.len)) { >> /* Reread the todo file if it has changed. */ >> todo_list_release(todo_list); >> if (read_populate_todo(r, todo_list, opts)) > > As we already have the contents of hte file in the buffer, we could > further refactor the code around read_populate_todo() to tell it not > to reopen and reread the rebase-todo file (which risks toctou race), > but that is OK for now, I would think. I did wonder about doing that but decided to punt it for now, I don't think the race is a concern - if another process is writing to the todo list while rebase is picking commits it is asking for trouble already. I suspect doing this will be easier once git-rebase--preserve-merges.sh is gone from master. >> @@ -4271,6 +4267,7 @@ static int reread_todo_if_changed(struct repository *r, >> /* `current` will be incremented on return */ >> todo_list->current = -1; >> } >> + strbuf_release(&buf); >> >> return 0; >> } >> diff --git a/sequencer.h b/sequencer.h >> index d57d8ea23d7..cdeb0c6be47 100644 >> --- a/sequencer.h >> +++ b/sequencer.h >> @@ -116,7 +116,6 @@ struct todo_list { >> struct todo_item *items; >> int nr, alloc, current; >> int done_nr, total_nr; >> - struct stat_data stat; > > Good riddance ;-) Hear, hear! > Will queue. Thanks. >
diff --git a/sequencer.c b/sequencer.c index a248c886c27..d51440ddcd9 100644 --- a/sequencer.c +++ b/sequencer.c @@ -2671,7 +2671,6 @@ static int read_populate_todo(struct repository *r, struct todo_list *todo_list, struct replay_opts *opts) { - struct stat st; const char *todo_file = get_todo_path(opts); int res; @@ -2679,11 +2678,6 @@ static int read_populate_todo(struct repository *r, if (strbuf_read_file_or_whine(&todo_list->buf, todo_file) < 0) return -1; - res = stat(todo_file, &st); - if (res) - return error(_("could not stat '%s'"), todo_file); - fill_stat_data(&todo_list->stat, &st); - res = todo_list_parse_insn_buffer(r, todo_list->buf.buf, todo_list); if (res) { if (is_rebase_i(opts)) @@ -4258,12 +4252,14 @@ static int reread_todo_if_changed(struct repository *r, struct todo_list *todo_list, struct replay_opts *opts) { - struct stat st; + int offset; + struct strbuf buf = STRBUF_INIT; - if (stat(get_todo_path(opts), &st)) { - return error_errno(_("could not stat '%s'"), - get_todo_path(opts)); - } else if (match_stat_data(&todo_list->stat, &st)) { + if (strbuf_read_file_or_whine(&buf, get_todo_path(opts)) < 0) + return -1; + offset = get_item_line_offset(todo_list, todo_list->current + 1); + if (buf.len != todo_list->buf.len - offset || + memcmp(buf.buf, todo_list->buf.buf + offset, buf.len)) { /* Reread the todo file if it has changed. */ todo_list_release(todo_list); if (read_populate_todo(r, todo_list, opts)) @@ -4271,6 +4267,7 @@ static int reread_todo_if_changed(struct repository *r, /* `current` will be incremented on return */ todo_list->current = -1; } + strbuf_release(&buf); return 0; } diff --git a/sequencer.h b/sequencer.h index d57d8ea23d7..cdeb0c6be47 100644 --- a/sequencer.h +++ b/sequencer.h @@ -116,7 +116,6 @@ struct todo_list { struct todo_item *items; int nr, alloc, current; int done_nr, total_nr; - struct stat_data stat; }; #define TODO_LIST_INIT { STRBUF_INIT }