diff --git a/builtin/rebase--interactive.c b/builtin/rebase--interactive.c index b4190e58e1..ffbe14cef5 100644 --- a/builtin/rebase--interactive.c +++ b/builtin/rebase--interactive.c @@ -71,7 +71,6 @@ static int do_interactive_rebase(struct replay_opts *opts, unsigned flags, const char *head_hash = NULL; char *revisions = NULL, *shortrevisions = NULL; struct argv_array make_script_args = ARGV_ARRAY_INIT; - FILE *todo_list_file; struct todo_list todo_list = TODO_LIST_INIT; if (prepare_branch_to_be_rebased(opts, switch_to)) @@ -94,14 +93,6 @@ static int do_interactive_rebase(struct replay_opts *opts, unsigned flags, if (!upstream && squash_onto) write_file(path_squash_onto(), "%s\n", squash_onto); - todo_list_file = fopen(rebase_path_todo(), "w"); - if (!todo_list_file) { - free(revisions); - free(shortrevisions); - - return error_errno(_("could not open %s"), rebase_path_todo()); - } - argv_array_pushl(&make_script_args, "", revisions, NULL); if (restrict_revision) argv_array_push(&make_script_args, restrict_revision); @@ -109,16 +100,17 @@ static int do_interactive_rebase(struct replay_opts *opts, unsigned flags, ret = sequencer_make_script(the_repository, &todo_list.buf, make_script_args.argc, make_script_args.argv, flags); - fputs(todo_list.buf.buf, todo_list_file); - fclose(todo_list_file); if (ret) error(_("could not generate todo list")); else { discard_cache(); - ret = complete_action(the_repository, opts, flags, - shortrevisions, onto_name, onto, - head_hash, commands, autosquash); + if (todo_list_parse_insn_buffer(the_repository, todo_list.buf.buf, + &todo_list)) + BUG("unusable todo list"); + + ret = complete_action(the_repository, opts, flags, shortrevisions, onto_name, + onto, head_hash, commands, autosquash, &todo_list); } free(revisions); diff --git a/sequencer.c b/sequencer.c index cf716fa5b8..1d5cd2fc27 100644 --- a/sequencer.c +++ b/sequencer.c @@ -4817,93 +4817,82 @@ static int skip_unnecessary_picks(struct repository *r, struct object_id *output return 0; } +static int todo_list_rearrange_squash(struct todo_list *todo_list); + int complete_action(struct repository *r, struct replay_opts *opts, unsigned flags, const char *shortrevisions, const char *onto_name, const char *onto, const char *orig_head, struct string_list *commands, - unsigned autosquash) + unsigned autosquash, struct todo_list *todo_list) { const char *shortonto, *todo_file = rebase_path_todo(); - struct todo_list todo_list = TODO_LIST_INIT; - struct strbuf *buf = &(todo_list.buf); + struct todo_list new_todo = 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 -1; + if (buf->len == 0) { + struct todo_item *item = append_new_todo(todo_list); + item->command = TODO_NOOP; + item->commit = NULL; + item->arg_len = item->arg_offset = item->flags = item->offset_in_buf = 0; + } - if (autosquash && rearrange_squash_in_todo_file(r)) + if (autosquash && todo_list_rearrange_squash(todo_list)) return -1; if (commands->nr) - sequencer_add_exec_commands(r, commands); + todo_list_add_exec_commands(todo_list, commands); - if (strbuf_read_file(buf, todo_file, 0) < 0) - return error_errno(_("could not read '%s'."), todo_file); - - if (todo_list_parse_insn_buffer(r, buf->buf, &todo_list)) { - todo_list_release(&todo_list); - return error(_("unusable todo list: '%s'"), todo_file); - } - - if (count_commands(&todo_list) == 0) { + if (count_commands(todo_list) == 0) { apply_autostash(opts); sequencer_remove_state(opts); - todo_list_release(&todo_list); return error(_("nothing to do")); } - strbuf_addch(buf, '\n'); - strbuf_commented_addf(buf, Q_("Rebase %s onto %s (%d command)", - "Rebase %s onto %s (%d commands)", - count_commands(&todo_list)), - shortrevisions, shortonto, count_commands(&todo_list)); - append_todo_help(0, flags & TODO_LIST_KEEP_EMPTY, buf); - - if (write_message(buf->buf, buf->len, todo_file, 0)) { - todo_list_release(&todo_list); - return -1; - } + if (todo_list_write_to_file(r, todo_list, todo_file, + shortrevisions, shortonto, -1, + flags | TODO_LIST_SHORTEN_IDS | TODO_LIST_APPEND_TODO_HELP)) + return error_errno(_("could not write '%s'"), todo_file); if (copy_file(rebase_path_todo_backup(), todo_file, 0666)) return error(_("could not copy '%s' to '%s'."), todo_file, rebase_path_todo_backup()); - if (transform_todo_file(r, flags | TODO_LIST_SHORTEN_IDS)) - return error(_("could not transform the todo list")); - - strbuf_reset(buf); - - if (launch_sequence_editor(todo_file, buf, NULL)) { + if (launch_sequence_editor(todo_file, &new_todo.buf, NULL)) { apply_autostash(opts); sequencer_remove_state(opts); - todo_list_release(&todo_list); return -1; } - strbuf_stripspace(buf, 1); - if (buf->len == 0) { + strbuf_stripspace(&new_todo.buf, 1); + if (new_todo.buf.len == 0) { apply_autostash(opts); sequencer_remove_state(opts); - todo_list_release(&todo_list); + todo_list_release(&new_todo); return error(_("nothing to do")); } - todo_list_release(&todo_list); - - if (check_todo_list_from_file(r)) { + if (todo_list_parse_insn_buffer(r, new_todo.buf.buf, &new_todo) || + todo_list_check(todo_list, &new_todo)) { + fprintf(stderr, _(edit_todo_list_advice)); checkout_onto(opts, onto_name, onto, orig_head); + todo_list_release(&new_todo); + return -1; } - if (transform_todo_file(r, flags & ~(TODO_LIST_SHORTEN_IDS))) - return error(_("could not transform the todo list")); + if (todo_list_write_to_file(r, &new_todo, todo_file, NULL, NULL, -1, + flags & ~(TODO_LIST_SHORTEN_IDS))) { + todo_list_release(&new_todo); + return error_errno(_("could not write '%s'"), todo_file); + } + + todo_list_release(&new_todo); if (opts->allow_ff && skip_unnecessary_picks(r, &oid)) return error(_("could not skip unnecessary pick commands")); diff --git a/sequencer.h b/sequencer.h index e25f5151d3..7029b39cd6 100644 --- a/sequencer.h +++ b/sequencer.h @@ -152,7 +152,7 @@ int check_todo_list_from_file(struct repository *r); int complete_action(struct repository *r, struct replay_opts *opts, unsigned flags, const char *shortrevisions, const char *onto_name, const char *onto, const char *orig_head, struct string_list *commands, - unsigned autosquash); + unsigned autosquash, struct todo_list *todo_list); int rearrange_squash_in_todo_file(struct repository *r); extern const char sign_off_header[];