sequencer: refactor skip_unnecessary_picks() to work on a todo_list
This refactors skip_unnecessary_picks() to work on a todo_list. As this function is only called by complete_action() (and thus is not used by rebase -p), the file-handling logic is completely dropped here. Instead of truncating the todo list’s buffer, the items are moved to the beginning of the list, eliminating the need to reparse the list. This also means its buffer cannot be directly written to the disk. rewrite_file() is then removed, as it is now unused. Signed-off-by: Alban Gruin <alban.gruin@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Alban Gruin committed
Mar 5, 2019 at 20:18 UTC
6bfeb7f1b503cf3fa0fd5690c0c98a9813c7c875
1 file changed
+19
-63
sequencer.c
+19
-63
@@ -4700,52 +4700,22 @@ out:
4700
return res;
4701
}
4702
4703
-static int rewrite_file(const char *path, const char *buf, size_t len)
4704
-{
4705
- int rc = 0;
4706
- int fd = open(path, O_WRONLY | O_TRUNC);
4707
- if (fd < 0)
4708
- return error_errno(_("could not open '%s' for writing"), path);
4709
- if (write_in_full(fd, buf, len) < 0)
4710
- rc = error_errno(_("could not write to '%s'"), path);
4711
- if (close(fd) && !rc)
4712
- rc = error_errno(_("could not close '%s'"), path);
4713
- return rc;
4714
-}
4715
-
4703
/* skip picking commits whose parents are unchanged */
4717
-static int skip_unnecessary_picks(struct repository *r, struct object_id *output_oid)
4704
+static int skip_unnecessary_picks(struct repository *r,
4705
+ struct todo_list *todo_list,
4706
+ struct object_id *base_oid)
4707
{
4719
- const char *todo_file = rebase_path_todo();
4720
- struct strbuf buf = STRBUF_INIT;
4721
- struct todo_list todo_list = TODO_LIST_INIT;
4708
struct object_id *parent_oid;
4723
- int fd, i;
4724
-
4725
- if (!read_oneliner(&buf, rebase_path_onto(), 0))
4726
- return error(_("could not read 'onto'"));
4727
- if (get_oid(buf.buf, output_oid)) {
4728
- strbuf_release(&buf);
4729
- return error(_("need a HEAD to fixup"));
4730
- }
4731
- strbuf_release(&buf);
4732
-
4733
- if (strbuf_read_file_or_whine(&todo_list.buf, todo_file) < 0)
4734
- return -1;
4735
- if (todo_list_parse_insn_buffer(r, todo_list.buf.buf, &todo_list) < 0) {
4736
- todo_list_release(&todo_list);
4737
- return -1;
4738
- }
4709
+ int i;
4710
4740
- for (i = 0; i < todo_list.nr; i++) {
4741
- struct todo_item *item = todo_list.items + i;
4711
+ for (i = 0; i < todo_list->nr; i++) {
4712
+ struct todo_item *item = todo_list->items + i;
4713
4714
if (item->command >= TODO_NOOP)
4715
continue;
4716
if (item->command != TODO_PICK)
4717
break;
4718
if (parse_commit(item->commit)) {
4748
- todo_list_release(&todo_list);
4719
return error(_("could not parse commit '%s'"),
4720
oid_to_hex(&item->commit->object.oid));
4721
}
@@ -4754,42 +4724,26 @@ static int skip_unnecessary_picks(struct repository *r, struct object_id *output
4724
if (item->commit->parents->next)
4725
break; /* merge commit */
4726
parent_oid = &item->commit->parents->item->object.oid;
4757
- if (!oideq(parent_oid, output_oid))
4727
+ if (!oideq(parent_oid, base_oid))
4728
break;
4759
- oidcpy(output_oid, &item->commit->object.oid);
4729
+ oidcpy(base_oid, &item->commit->object.oid);
4730
}
4731
if (i > 0) {
4762
- int offset = get_item_line_offset(&todo_list, i);
4732
const char *done_path = rebase_path_done();
4733
4765
- fd = open(done_path, O_CREAT | O_WRONLY | O_APPEND, 0666);
4766
- if (fd < 0) {
4767
- error_errno(_("could not open '%s' for writing"),
4768
- done_path);
4769
- todo_list_release(&todo_list);
4770
- return -1;
4771
- }
4772
- if (write_in_full(fd, todo_list.buf.buf, offset) < 0) {
4734
+ if (todo_list_write_to_file(r, todo_list, done_path, NULL, NULL, i, 0)) {
4735
error_errno(_("could not write to '%s'"), done_path);
4774
- todo_list_release(&todo_list);
4775
- close(fd);
4736
return -1;
4737
}
4778
- close(fd);
4738
4780
- if (rewrite_file(rebase_path_todo(), todo_list.buf.buf + offset,
4781
- todo_list.buf.len - offset) < 0) {
4782
- todo_list_release(&todo_list);
4783
- return -1;
4784
- }
4739
+ MOVE_ARRAY(todo_list->items, todo_list->items + i, todo_list->nr - i);
4740
+ todo_list->nr -= i;
4741
+ todo_list->current = 0;
4742
4786
- todo_list.current = i;
4787
- if (is_fixup(peek_command(&todo_list, 0)))
4788
- record_in_rewritten(output_oid, peek_command(&todo_list, 0));
4743
+ if (is_fixup(peek_command(todo_list, 0)))
4744
+ record_in_rewritten(base_oid, peek_command(todo_list, 0));
4745
}
4746
4791
- todo_list_release(&todo_list);
4792
-
4747
return 0;
4748
}
4749
@@ -4860,6 +4814,11 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
4814
return -1;
4815
}
4816
4817
+ if (opts->allow_ff && skip_unnecessary_picks(r, &new_todo, &oid)) {
4818
+ todo_list_release(&new_todo);
4819
+ return error(_("could not skip unnecessary pick commands"));
4820
+ }
4821
+
4822
if (todo_list_write_to_file(r, &new_todo, todo_file, NULL, NULL, -1,
4823
flags & ~(TODO_LIST_SHORTEN_IDS))) {
4824
todo_list_release(&new_todo);
@@ -4868,9 +4827,6 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
4827
4828
todo_list_release(&new_todo);
4829
4871
- if (opts->allow_ff && skip_unnecessary_picks(r, &oid))
4872
- return error(_("could not skip unnecessary pick commands"));
4873
-
4830
if (checkout_onto(opts, onto_name, oid_to_hex(&oid), orig_head))
4831
return -1;
4832