From patchwork Thu Mar 23 16:22:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oswald Buddenhagen X-Patchwork-Id: 13185849 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3E238C74A5B for ; Thu, 23 Mar 2023 16:47:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231603AbjCWQrb (ORCPT ); Thu, 23 Mar 2023 12:47:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52110 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232453AbjCWQrD (ORCPT ); Thu, 23 Mar 2023 12:47:03 -0400 Received: from bluemchen.kde.org (bluemchen.kde.org [IPv6:2001:470:142:8::100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AE90661AE for ; Thu, 23 Mar 2023 09:46:32 -0700 (PDT) Received: from ugly.fritz.box (localhost [127.0.0.1]) by bluemchen.kde.org (Postfix) with ESMTP id C542224232 for ; Thu, 23 Mar 2023 12:22:35 -0400 (EDT) Received: by ugly.fritz.box (masqmail 0.3.4, from userid 1000) id 1pfNhz-B01-00 for ; Thu, 23 Mar 2023 17:22:35 +0100 From: Oswald Buddenhagen To: git@vger.kernel.org Subject: [PATCH 1/8] rebase: simplify code related to imply_merge() Date: Thu, 23 Mar 2023 17:22:28 +0100 Message-Id: <20230323162235.995574-2-oswald.buddenhagen@gmx.de> X-Mailer: git-send-email 2.40.0.152.g15d061e6df In-Reply-To: <20230323162235.995574-1-oswald.buddenhagen@gmx.de> References: <20230323162235.995574-1-oswald.buddenhagen@gmx.de> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org The code's evolution left in some bits surrounding enum rebase_type that don't really make sense any more. In particular, it makes no sense to invoke imply_merge() if the type is already known not to be REBASE_APPLY, and it makes no sense to assign the type after calling imply_merge(). Signed-off-by: Oswald Buddenhagen --- builtin/rebase.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/builtin/rebase.c b/builtin/rebase.c index 5b7b908b66..8ffea0f0d8 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -372,7 +372,6 @@ static int parse_opt_keep_empty(const struct option *opt, const char *arg, imply_merge(opts, unset ? "--no-keep-empty" : "--keep-empty"); opts->keep_empty = !unset; - opts->type = REBASE_MERGE; return 0; } @@ -1494,9 +1493,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) } } - if (options.type == REBASE_MERGE) - imply_merge(&options, "--merge"); - if (options.root && !options.onto_name) imply_merge(&options, "--root without --onto"); @@ -1534,7 +1530,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) if (options.type == REBASE_UNSPECIFIED) { if (!strcmp(options.default_backend, "merge")) - imply_merge(&options, "--merge"); + options.type = REBASE_MERGE; else if (!strcmp(options.default_backend, "apply")) options.type = REBASE_APPLY; else From patchwork Thu Mar 23 16:22:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oswald Buddenhagen X-Patchwork-Id: 13185850 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CF10FC6FD1C for ; Thu, 23 Mar 2023 16:47:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232453AbjCWQrc (ORCPT ); Thu, 23 Mar 2023 12:47:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52176 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232294AbjCWQrD (ORCPT ); Thu, 23 Mar 2023 12:47:03 -0400 Received: from bluemchen.kde.org (bluemchen.kde.org [IPv6:2001:470:142:8::100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AECBDCC0A for ; Thu, 23 Mar 2023 09:46:32 -0700 (PDT) Received: from ugly.fritz.box (localhost [127.0.0.1]) by bluemchen.kde.org (Postfix) with ESMTP id C78B824235 for ; Thu, 23 Mar 2023 12:22:35 -0400 (EDT) Received: by ugly.fritz.box (masqmail 0.3.4, from userid 1000) id 1pfNhz-B07-00 for ; Thu, 23 Mar 2023 17:22:35 +0100 From: Oswald Buddenhagen To: git@vger.kernel.org Subject: [PATCH 2/8] rebase: move parse_opt_keep_empty() down Date: Thu, 23 Mar 2023 17:22:29 +0100 Message-Id: <20230323162235.995574-3-oswald.buddenhagen@gmx.de> X-Mailer: git-send-email 2.40.0.152.g15d061e6df In-Reply-To: <20230323162235.995574-1-oswald.buddenhagen@gmx.de> References: <20230323162235.995574-1-oswald.buddenhagen@gmx.de> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org This moves it right next to parse_opt_empty(), which is a much more logical place. As a side effect, this removes the need for a forward declaration of imply_merge(). Signed-off-by: Oswald Buddenhagen --- builtin/rebase.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/builtin/rebase.c b/builtin/rebase.c index 8ffea0f0d8..491759db19 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -362,19 +362,6 @@ static int run_sequencer_rebase(struct rebase_options *opts) return ret; } -static void imply_merge(struct rebase_options *opts, const char *option); -static int parse_opt_keep_empty(const struct option *opt, const char *arg, - int unset) -{ - struct rebase_options *opts = opt->value; - - BUG_ON_OPT_ARG(arg); - - imply_merge(opts, unset ? "--no-keep-empty" : "--keep-empty"); - opts->keep_empty = !unset; - return 0; -} - static int is_merge(struct rebase_options *opts) { return opts->type == REBASE_MERGE; @@ -969,6 +956,18 @@ static enum empty_type parse_empty_value(const char *value) die(_("unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and \"ask\"."), value); } +static int parse_opt_keep_empty(const struct option *opt, const char *arg, + int unset) +{ + struct rebase_options *opts = opt->value; + + BUG_ON_OPT_ARG(arg); + + imply_merge(opts, unset ? "--no-keep-empty" : "--keep-empty"); + opts->keep_empty = !unset; + return 0; +} + static int parse_opt_empty(const struct option *opt, const char *arg, int unset) { struct rebase_options *options = opt->value; From patchwork Thu Mar 23 16:22:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oswald Buddenhagen X-Patchwork-Id: 13185860 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 685FBC74A5B for ; Thu, 23 Mar 2023 16:48:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232514AbjCWQsB (ORCPT ); Thu, 23 Mar 2023 12:48:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47842 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232383AbjCWQrG (ORCPT ); Thu, 23 Mar 2023 12:47:06 -0400 Received: from bluemchen.kde.org (bluemchen.kde.org [IPv6:2001:470:142:8::100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7ED0EFF1E for ; Thu, 23 Mar 2023 09:46:34 -0700 (PDT) Received: from ugly.fritz.box (localhost [127.0.0.1]) by bluemchen.kde.org (Postfix) with ESMTP id D5BDF2423F for ; Thu, 23 Mar 2023 12:22:35 -0400 (EDT) Received: by ugly.fritz.box (masqmail 0.3.4, from userid 1000) id 1pfNhz-B0D-00 for ; Thu, 23 Mar 2023 17:22:35 +0100 From: Oswald Buddenhagen To: git@vger.kernel.org Subject: [PATCH 3/8] sequencer: pass around rebase action explicitly Date: Thu, 23 Mar 2023 17:22:30 +0100 Message-Id: <20230323162235.995574-4-oswald.buddenhagen@gmx.de> X-Mailer: git-send-email 2.40.0.152.g15d061e6df In-Reply-To: <20230323162235.995574-1-oswald.buddenhagen@gmx.de> References: <20230323162235.995574-1-oswald.buddenhagen@gmx.de> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org ... instead of deriving it from other arguments. This is a lot cleaner and more extensible. Signed-off-by: Oswald Buddenhagen --- builtin/rebase.c | 25 ++++++++++--------------- rebase-interactive.c | 21 +++++++++++---------- rebase-interactive.h | 16 ++++++++++++++-- sequencer.c | 16 +++++++++------- sequencer.h | 8 +++++--- 5 files changed, 49 insertions(+), 37 deletions(-) diff --git a/builtin/rebase.c b/builtin/rebase.c index 491759db19..a309addd50 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -58,16 +58,6 @@ enum empty_type { EMPTY_ASK }; -enum action { - ACTION_NONE = 0, - ACTION_CONTINUE, - ACTION_SKIP, - ACTION_ABORT, - ACTION_QUIT, - ACTION_EDIT_TODO, - ACTION_SHOW_CURRENT_PATCH -}; - static const char *action_names[] = { "undefined", "continue", @@ -104,7 +94,7 @@ struct rebase_options { REBASE_INTERACTIVE_EXPLICIT = 1<<4, } flags; struct strvec git_am_opts; - enum action action; + enum rebase_action action; char *reflog_action; int signoff; int allow_rerere_autoupdate; @@ -198,9 +188,11 @@ static int edit_todo_file(unsigned flags) return error_errno(_("could not read '%s'."), todo_file); strbuf_stripspace(&todo_list.buf, 1); - res = edit_todo_list(the_repository, &todo_list, &new_todo, NULL, NULL, flags); + res = edit_todo_list(the_repository, &todo_list, &new_todo, NULL, NULL, flags, + ACTION_EDIT_TODO); if (!res && todo_list_write_to_file(the_repository, &new_todo, todo_file, - NULL, NULL, -1, flags & ~(TODO_LIST_SHORTEN_IDS))) + NULL, NULL, -1, flags & ~(TODO_LIST_SHORTEN_IDS), + ACTION_EDIT_TODO)) res = error_errno(_("could not write '%s'"), todo_file); todo_list_release(&todo_list); @@ -294,7 +286,8 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags) ret = complete_action(the_repository, &replay, flags, shortrevisions, opts->onto_name, opts->onto, &opts->orig_head->object.oid, &opts->exec, - opts->autosquash, opts->update_refs, &todo_list); + opts->autosquash, opts->update_refs, &todo_list, + opts->action); } cleanup: @@ -1246,7 +1239,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) else if (options.exec.nr) trace2_cmd_mode("interactive-exec"); else - trace2_cmd_mode(action_names[options.action]); + trace2_cmd_mode( + (BUILD_ASSERT_OR_ZERO(ARRAY_SIZE(action_names) == ACTION_LAST), + action_names[options.action])); } options.reflog_action = getenv(GIT_REFLOG_ACTION_ENVIRONMENT); diff --git a/rebase-interactive.c b/rebase-interactive.c index 7407c59319..111a2071ae 100644 --- a/rebase-interactive.c +++ b/rebase-interactive.c @@ -35,7 +35,7 @@ static enum missing_commit_check_level get_missing_commit_check_level(void) return MISSING_COMMIT_CHECK_IGNORE; } -void append_todo_help(int command_count, +void append_todo_help(int command_count, enum rebase_action action, const char *shortrevisions, const char *shortonto, struct strbuf *buf) { @@ -62,9 +62,8 @@ void append_todo_help(int command_count, " updated at the end of the rebase\n" "\n" "These lines can be re-ordered; they are executed from top to bottom.\n"); - unsigned edit_todo = !(shortrevisions && shortonto); - if (!edit_todo) { + if (action == ACTION_NONE) { strbuf_addch(buf, '\n'); strbuf_commented_addf(buf, Q_("Rebase %s onto %s (%d command)", "Rebase %s onto %s (%d commands)", @@ -83,7 +82,7 @@ void append_todo_help(int command_count, strbuf_add_commented_lines(buf, msg, strlen(msg)); - if (edit_todo) + if (action == ACTION_EDIT_TODO) msg = _("\nYou are editing the todo file " "of an ongoing interactive rebase.\n" "To continue rebase after editing, run:\n" @@ -97,35 +96,37 @@ void append_todo_help(int command_count, int edit_todo_list(struct repository *r, struct todo_list *todo_list, struct todo_list *new_todo, const char *shortrevisions, - const char *shortonto, unsigned flags) + const char *shortonto, unsigned flags, + enum rebase_action action) { const char *todo_file = rebase_path_todo(), *todo_backup = rebase_path_todo_backup(); - unsigned initial = shortrevisions && shortonto; int incorrect = 0; /* If the user is editing the todo list, we first try to parse * it. If there is an error, we do not return, because the user * might want to fix it in the first place. */ - if (!initial) + if (action != ACTION_NONE) incorrect = todo_list_parse_insn_buffer(r, todo_list->buf.buf, todo_list) | file_exists(rebase_path_dropped()); if (todo_list_write_to_file(r, todo_list, todo_file, shortrevisions, shortonto, - -1, flags | TODO_LIST_SHORTEN_IDS | TODO_LIST_APPEND_TODO_HELP)) + -1, flags | TODO_LIST_SHORTEN_IDS | TODO_LIST_APPEND_TODO_HELP, + action)) return error_errno(_("could not write '%s'"), todo_file); if (!incorrect && todo_list_write_to_file(r, todo_list, todo_backup, shortrevisions, shortonto, -1, - (flags | TODO_LIST_APPEND_TODO_HELP) & ~TODO_LIST_SHORTEN_IDS) < 0) + (flags | TODO_LIST_APPEND_TODO_HELP) & ~TODO_LIST_SHORTEN_IDS, + action) < 0) return error(_("could not write '%s'."), rebase_path_todo_backup()); if (launch_sequence_editor(todo_file, &new_todo->buf, NULL)) return -2; strbuf_stripspace(&new_todo->buf, 1); - if (initial && new_todo->buf.len == 0) + if (action != ACTION_EDIT_TODO && new_todo->buf.len == 0) return -3; if (todo_list_parse_insn_buffer(r, new_todo->buf.buf, new_todo)) { diff --git a/rebase-interactive.h b/rebase-interactive.h index 7239c60f79..d9873d3497 100644 --- a/rebase-interactive.h +++ b/rebase-interactive.h @@ -5,12 +5,24 @@ struct strbuf; struct repository; struct todo_list; -void append_todo_help(int command_count, +enum rebase_action { + ACTION_NONE = 0, + ACTION_CONTINUE, + ACTION_SKIP, + ACTION_ABORT, + ACTION_QUIT, + ACTION_EDIT_TODO, + ACTION_SHOW_CURRENT_PATCH, + ACTION_LAST +}; + +void append_todo_help(int command_count, enum rebase_action action, const char *shortrevisions, const char *shortonto, struct strbuf *buf); int edit_todo_list(struct repository *r, struct todo_list *todo_list, struct todo_list *new_todo, const char *shortrevisions, - const char *shortonto, unsigned flags); + const char *shortonto, unsigned flags, + enum rebase_action action); int todo_list_check(struct todo_list *old_todo, struct todo_list *new_todo); int todo_list_check_against_backup(struct repository *r, diff --git a/sequencer.c b/sequencer.c index 7c275c9a65..f05174d151 100644 --- a/sequencer.c +++ b/sequencer.c @@ -5894,14 +5894,15 @@ static void todo_list_to_strbuf(struct repository *r, struct todo_list *todo_lis int todo_list_write_to_file(struct repository *r, struct todo_list *todo_list, const char *file, const char *shortrevisions, - const char *shortonto, int num, unsigned flags) + const char *shortonto, int num, unsigned flags, + enum rebase_action action) { int res; struct strbuf buf = STRBUF_INIT; todo_list_to_strbuf(r, todo_list, &buf, num, flags); if (flags & TODO_LIST_APPEND_TODO_HELP) - append_todo_help(count_commands(todo_list), + append_todo_help(count_commands(todo_list), action, shortrevisions, shortonto, &buf); res = write_message(buf.buf, buf.len, file, 0); @@ -5941,7 +5942,8 @@ static int skip_unnecessary_picks(struct repository *r, if (i > 0) { const char *done_path = rebase_path_done(); - if (todo_list_write_to_file(r, todo_list, done_path, NULL, NULL, i, 0)) { + if (todo_list_write_to_file(r, todo_list, done_path, NULL, NULL, i, 0, + ACTION_NONE)) { error_errno(_("could not write to '%s'"), done_path); return -1; } @@ -6086,8 +6088,8 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla const char *shortrevisions, const char *onto_name, struct commit *onto, const struct object_id *orig_head, struct string_list *commands, unsigned autosquash, - unsigned update_refs, - struct todo_list *todo_list) + unsigned update_refs, struct todo_list *todo_list, + enum rebase_action action) { char shortonto[GIT_MAX_HEXSZ + 1]; const char *todo_file = rebase_path_todo(); @@ -6122,7 +6124,7 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla } res = edit_todo_list(r, todo_list, &new_todo, shortrevisions, - shortonto, flags); + shortonto, flags, action); if (res == -1) return -1; else if (res == -2) { @@ -6158,7 +6160,7 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla } if (todo_list_write_to_file(r, &new_todo, todo_file, NULL, NULL, -1, - flags & ~(TODO_LIST_SHORTEN_IDS))) { + flags & ~(TODO_LIST_SHORTEN_IDS), action)) { todo_list_release(&new_todo); return error_errno(_("could not write '%s'"), todo_file); } diff --git a/sequencer.h b/sequencer.h index 33dbaf5b66..1a3e616af2 100644 --- a/sequencer.h +++ b/sequencer.h @@ -4,6 +4,7 @@ #include "strbuf.h" #include "wt-status.h" +enum rebase_action; struct commit; struct index_state; struct repository; @@ -134,7 +135,8 @@ int todo_list_parse_insn_buffer(struct repository *r, char *buf, struct todo_list *todo_list); int todo_list_write_to_file(struct repository *r, struct todo_list *todo_list, const char *file, const char *shortrevisions, - const char *shortonto, int num, unsigned flags); + const char *shortonto, int num, unsigned flags, + enum rebase_action action); void todo_list_release(struct todo_list *todo_list); const char *todo_item_get_arg(struct todo_list *todo_list, struct todo_item *item); @@ -187,8 +189,8 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla const char *shortrevisions, const char *onto_name, struct commit *onto, const struct object_id *orig_head, struct string_list *commands, unsigned autosquash, - unsigned update_refs, - struct todo_list *todo_list); + unsigned update_refs, struct todo_list *todo_list, + enum rebase_action action); int todo_list_rearrange_squash(struct todo_list *todo_list); /* From patchwork Thu Mar 23 16:22:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oswald Buddenhagen X-Patchwork-Id: 13185858 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8F22DC761AF for ; Thu, 23 Mar 2023 16:47:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232508AbjCWQrw (ORCPT ); Thu, 23 Mar 2023 12:47:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55170 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229553AbjCWQrG (ORCPT ); Thu, 23 Mar 2023 12:47:06 -0400 Received: from bluemchen.kde.org (bluemchen.kde.org [209.51.188.41]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3562DEB66 for ; Thu, 23 Mar 2023 09:46:33 -0700 (PDT) Received: from ugly.fritz.box (localhost [127.0.0.1]) by bluemchen.kde.org (Postfix) with ESMTP id D82B324245 for ; Thu, 23 Mar 2023 12:22:35 -0400 (EDT) Received: by ugly.fritz.box (masqmail 0.3.4, from userid 1000) id 1pfNhz-B0J-00 for ; Thu, 23 Mar 2023 17:22:35 +0100 From: Oswald Buddenhagen To: git@vger.kernel.org Subject: [PATCH 4/8] sequencer: create enum for edit_todo_list() return value Date: Thu, 23 Mar 2023 17:22:31 +0100 Message-Id: <20230323162235.995574-5-oswald.buddenhagen@gmx.de> X-Mailer: git-send-email 2.40.0.152.g15d061e6df In-Reply-To: <20230323162235.995574-1-oswald.buddenhagen@gmx.de> References: <20230323162235.995574-1-oswald.buddenhagen@gmx.de> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org This is a lot cleaner than open-coding magic numbers. Signed-off-by: Oswald Buddenhagen --- rebase-interactive.c | 15 ++++++++------- rebase-interactive.h | 11 ++++++++++- sequencer.c | 8 ++++---- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/rebase-interactive.c b/rebase-interactive.c index 111a2071ae..a3d8925b06 100644 --- a/rebase-interactive.c +++ b/rebase-interactive.c @@ -94,7 +94,8 @@ void append_todo_help(int command_count, enum rebase_action action, strbuf_add_commented_lines(buf, msg, strlen(msg)); } -int edit_todo_list(struct repository *r, struct todo_list *todo_list, +enum edit_todo_result edit_todo_list( + struct repository *r, struct todo_list *todo_list, struct todo_list *new_todo, const char *shortrevisions, const char *shortonto, unsigned flags, enum rebase_action action) @@ -123,37 +124,37 @@ int edit_todo_list(struct repository *r, struct todo_list *todo_list, return error(_("could not write '%s'."), rebase_path_todo_backup()); if (launch_sequence_editor(todo_file, &new_todo->buf, NULL)) - return -2; + return EDIT_TODO_FAILED; strbuf_stripspace(&new_todo->buf, 1); if (action != ACTION_EDIT_TODO && new_todo->buf.len == 0) - return -3; + return EDIT_TODO_ABORT; if (todo_list_parse_insn_buffer(r, new_todo->buf.buf, new_todo)) { fprintf(stderr, _(edit_todo_list_advice)); - return -4; + return EDIT_TODO_INCORRECT; } if (incorrect) { if (todo_list_check_against_backup(r, new_todo)) { write_file(rebase_path_dropped(), "%s", ""); - return -4; + return EDIT_TODO_INCORRECT; } if (incorrect > 0) unlink(rebase_path_dropped()); } else if (todo_list_check(todo_list, new_todo)) { write_file(rebase_path_dropped(), "%s", ""); - return -4; + return EDIT_TODO_INCORRECT; } /* * See if branches need to be added or removed from the update-refs * file based on the new todo list. */ todo_list_filter_update_refs(r, new_todo); - return 0; + return EDIT_TODO_OK; } define_commit_slab(commit_seen, unsigned char); diff --git a/rebase-interactive.h b/rebase-interactive.h index d9873d3497..5aa4111b4f 100644 --- a/rebase-interactive.h +++ b/rebase-interactive.h @@ -16,10 +16,19 @@ enum rebase_action { ACTION_LAST }; +enum edit_todo_result { + EDIT_TODO_OK = 0, // must be 0 + EDIT_TODO_IOERROR = -1, // generic i/o error; must be -1 + EDIT_TODO_FAILED = -2, // editing failed + EDIT_TODO_ABORT = -3, // user requested abort + EDIT_TODO_INCORRECT = -4 // file violates syntax or constraints +}; + void append_todo_help(int command_count, enum rebase_action action, const char *shortrevisions, const char *shortonto, struct strbuf *buf); -int edit_todo_list(struct repository *r, struct todo_list *todo_list, +enum edit_todo_result edit_todo_list( + struct repository *r, struct todo_list *todo_list, struct todo_list *new_todo, const char *shortrevisions, const char *shortonto, unsigned flags, enum rebase_action action); diff --git a/sequencer.c b/sequencer.c index f05174d151..b1c29c8802 100644 --- a/sequencer.c +++ b/sequencer.c @@ -6125,20 +6125,20 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla res = edit_todo_list(r, todo_list, &new_todo, shortrevisions, shortonto, flags, action); - if (res == -1) + if (res == EDIT_TODO_IOERROR) return -1; - else if (res == -2) { + else if (res == EDIT_TODO_FAILED) { apply_autostash(rebase_path_autostash()); sequencer_remove_state(opts); return -1; - } else if (res == -3) { + } else if (res == EDIT_TODO_ABORT) { apply_autostash(rebase_path_autostash()); sequencer_remove_state(opts); todo_list_release(&new_todo); return error(_("nothing to do")); - } else if (res == -4) { + } else if (res == EDIT_TODO_INCORRECT) { checkout_onto(r, opts, onto_name, &onto->object.oid, orig_head); todo_list_release(&new_todo); From patchwork Thu Mar 23 16:22:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oswald Buddenhagen X-Patchwork-Id: 13185859 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 85ED8C76196 for ; Thu, 23 Mar 2023 16:47:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232511AbjCWQrx (ORCPT ); Thu, 23 Mar 2023 12:47:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52394 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232378AbjCWQrG (ORCPT ); Thu, 23 Mar 2023 12:47:06 -0400 Received: from bluemchen.kde.org (bluemchen.kde.org [209.51.188.41]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 945DDFF31 for ; Thu, 23 Mar 2023 09:46:34 -0700 (PDT) Received: from ugly.fritz.box (localhost [127.0.0.1]) by bluemchen.kde.org (Postfix) with ESMTP id DAD5024248 for ; Thu, 23 Mar 2023 12:22:35 -0400 (EDT) Received: by ugly.fritz.box (masqmail 0.3.4, from userid 1000) id 1pfNhz-B0P-00 for ; Thu, 23 Mar 2023 17:22:35 +0100 From: Oswald Buddenhagen To: git@vger.kernel.org Subject: [PATCH 5/8] rebase: preserve interactive todo file on checkout failure Date: Thu, 23 Mar 2023 17:22:32 +0100 Message-Id: <20230323162235.995574-6-oswald.buddenhagen@gmx.de> X-Mailer: git-send-email 2.40.0.152.g15d061e6df In-Reply-To: <20230323162235.995574-1-oswald.buddenhagen@gmx.de> References: <20230323162235.995574-1-oswald.buddenhagen@gmx.de> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Creating a suitable todo file is a potentially labor-intensive process, so be less cavalier about discarding it when something goes wrong (e.g., the user messed with the repo while editing the todo). Signed-off-by: Oswald Buddenhagen --- builtin/rebase.c | 1 + sequencer.c | 4 ++++ sequencer.h | 1 + t/t3404-rebase-interactive.sh | 3 ++- 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/builtin/rebase.c b/builtin/rebase.c index a309addd50..728c869db4 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -153,6 +153,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts) replay.keep_redundant_commits = (opts->empty == EMPTY_KEEP); replay.quiet = !(opts->flags & REBASE_NO_QUIET); replay.verbose = opts->flags & REBASE_VERBOSE; + replay.precious_todo = opts->flags & REBASE_INTERACTIVE_EXPLICIT; replay.reschedule_failed_exec = opts->reschedule_failed_exec; replay.committer_date_is_author_date = opts->committer_date_is_author_date; diff --git a/sequencer.c b/sequencer.c index b1c29c8802..f8a7f4e721 100644 --- a/sequencer.c +++ b/sequencer.c @@ -4570,6 +4570,10 @@ static int checkout_onto(struct repository *r, struct replay_opts *opts, .default_reflog_action = sequencer_reflog_action(opts) }; if (reset_head(r, &ropts)) { + // Editing the todo may have been costly; don't just discard it. + if (opts->precious_todo) + exit(1); // Error was already printed + apply_autostash(rebase_path_autostash()); sequencer_remove_state(opts); return error(_("could not detach HEAD")); diff --git a/sequencer.h b/sequencer.h index 1a3e616af2..a1b8ca6eb1 100644 --- a/sequencer.h +++ b/sequencer.h @@ -47,6 +47,7 @@ struct replay_opts { int keep_redundant_commits; int verbose; int quiet; + int precious_todo; int reschedule_failed_exec; int committer_date_is_author_date; int ignore_date; diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index ff0afad63e..c625aad10a 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -288,13 +288,14 @@ test_expect_success 'abort' ' ' test_expect_success 'abort with error when new base cannot be checked out' ' + test_when_finished "git rebase --abort ||:" && git rm --cached file1 && git commit -m "remove file in base" && test_must_fail git rebase -i primary > output 2>&1 && test_i18ngrep "The following untracked working tree files would be overwritten by checkout:" \ output && test_i18ngrep "file1" output && - test_path_is_missing .git/rebase-merge && + test_path_is_dir .git/rebase-merge && rm file1 && git reset --hard HEAD^ ' From patchwork Thu Mar 23 16:22:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oswald Buddenhagen X-Patchwork-Id: 13185861 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DE5C3C6FD1C for ; Thu, 23 Mar 2023 16:48:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230039AbjCWQsC (ORCPT ); Thu, 23 Mar 2023 12:48:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47872 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232386AbjCWQrH (ORCPT ); Thu, 23 Mar 2023 12:47:07 -0400 Received: from bluemchen.kde.org (bluemchen.kde.org [209.51.188.41]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A161710402 for ; Thu, 23 Mar 2023 09:46:36 -0700 (PDT) Received: from ugly.fritz.box (localhost [127.0.0.1]) by bluemchen.kde.org (Postfix) with ESMTP id DCD1E24249 for ; Thu, 23 Mar 2023 12:22:35 -0400 (EDT) Received: by ugly.fritz.box (masqmail 0.3.4, from userid 1000) id 1pfNhz-B0V-00 for ; Thu, 23 Mar 2023 17:22:35 +0100 From: Oswald Buddenhagen To: git@vger.kernel.org Subject: [PATCH 6/8] sequencer: simplify allocation of result array in todo_list_rearrange_squash() Date: Thu, 23 Mar 2023 17:22:33 +0100 Message-Id: <20230323162235.995574-7-oswald.buddenhagen@gmx.de> X-Mailer: git-send-email 2.40.0.152.g15d061e6df In-Reply-To: <20230323162235.995574-1-oswald.buddenhagen@gmx.de> References: <20230323162235.995574-1-oswald.buddenhagen@gmx.de> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org The operation doesn't change the number of elements in the array, so we do not need to allocate the result piecewise. Signed-off-by: Oswald Buddenhagen --- sequencer.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sequencer.c b/sequencer.c index f8a7f4e721..fb224445fa 100644 --- a/sequencer.c +++ b/sequencer.c @@ -6225,7 +6225,7 @@ static int skip_fixupish(const char *subject, const char **p) { int todo_list_rearrange_squash(struct todo_list *todo_list) { struct hashmap subject2item; - int rearranged = 0, *next, *tail, i, nr = 0, alloc = 0; + int rearranged = 0, *next, *tail, i, nr = 0; char **subjects; struct commit_todo_item commit_todo; struct todo_item *items = NULL; @@ -6334,6 +6334,8 @@ int todo_list_rearrange_squash(struct todo_list *todo_list) } if (rearranged) { + items = ALLOC_ARRAY(items, todo_list->nr); + for (i = 0; i < todo_list->nr; i++) { enum todo_command command = todo_list->items[i].command; int cur = i; @@ -6346,16 +6348,15 @@ int todo_list_rearrange_squash(struct todo_list *todo_list) continue; while (cur >= 0) { - ALLOC_GROW(items, nr + 1, alloc); items[nr++] = todo_list->items[cur]; cur = next[cur]; } } + assert(nr == todo_list->nr); + todo_list->alloc = nr; FREE_AND_NULL(todo_list->items); todo_list->items = items; - todo_list->nr = nr; - todo_list->alloc = alloc; } free(next); From patchwork Thu Mar 23 16:22:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oswald Buddenhagen X-Patchwork-Id: 13185862 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 13DFFC761AF for ; Thu, 23 Mar 2023 16:48:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232459AbjCWQsE (ORCPT ); Thu, 23 Mar 2023 12:48:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47896 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229842AbjCWQrH (ORCPT ); Thu, 23 Mar 2023 12:47:07 -0400 Received: from bluemchen.kde.org (bluemchen.kde.org [209.51.188.41]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A146D10253 for ; Thu, 23 Mar 2023 09:46:36 -0700 (PDT) Received: from ugly.fritz.box (localhost [127.0.0.1]) by bluemchen.kde.org (Postfix) with ESMTP id DEFA82424A for ; Thu, 23 Mar 2023 12:22:35 -0400 (EDT) Received: by ugly.fritz.box (masqmail 0.3.4, from userid 1000) id 1pfNhz-B0b-00 for ; Thu, 23 Mar 2023 17:22:35 +0100 From: Oswald Buddenhagen To: git@vger.kernel.org Subject: [PATCH 7/8] sequencer: pass `onto` to complete_action() as object-id Date: Thu, 23 Mar 2023 17:22:34 +0100 Message-Id: <20230323162235.995574-8-oswald.buddenhagen@gmx.de> X-Mailer: git-send-email 2.40.0.152.g15d061e6df In-Reply-To: <20230323162235.995574-1-oswald.buddenhagen@gmx.de> References: <20230323162235.995574-1-oswald.buddenhagen@gmx.de> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org ... instead of as a commit, which makes the purpose clearer and will simplify things later. As a side effect, this change revealed that skip_unnecessary_picks() was butchering the commit object due to missing const-correctness. Slightly adjust its API to rectify this. Signed-off-by: Oswald Buddenhagen --- builtin/rebase.c | 2 +- sequencer.c | 21 ++++++++++----------- sequencer.h | 2 +- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/builtin/rebase.c b/builtin/rebase.c index 728c869db4..e703b29835 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -285,7 +285,7 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags) BUG("unusable todo list"); ret = complete_action(the_repository, &replay, flags, - shortrevisions, opts->onto_name, opts->onto, + shortrevisions, opts->onto_name, &opts->onto->object.oid, &opts->orig_head->object.oid, &opts->exec, opts->autosquash, opts->update_refs, &todo_list, opts->action); diff --git a/sequencer.c b/sequencer.c index fb224445fa..aef42122f1 100644 --- a/sequencer.c +++ b/sequencer.c @@ -2083,7 +2083,7 @@ static void flush_rewritten_pending(void) strbuf_release(&buf); } -static void record_in_rewritten(struct object_id *oid, +static void record_in_rewritten(const struct object_id *oid, enum todo_command next_command) { FILE *out = fopen_or_warn(rebase_path_rewritten_pending(), "a"); @@ -5918,7 +5918,7 @@ int todo_list_write_to_file(struct repository *r, struct todo_list *todo_list, /* skip picking commits whose parents are unchanged */ static int skip_unnecessary_picks(struct repository *r, struct todo_list *todo_list, - struct object_id *base_oid) + const struct object_id **base_oid) { struct object_id *parent_oid; int i; @@ -5939,9 +5939,9 @@ static int skip_unnecessary_picks(struct repository *r, if (item->commit->parents->next) break; /* merge commit */ parent_oid = &item->commit->parents->item->object.oid; - if (!oideq(parent_oid, base_oid)) + if (!oideq(parent_oid, *base_oid)) break; - oidcpy(base_oid, &item->commit->object.oid); + *base_oid = &item->commit->object.oid; } if (i > 0) { const char *done_path = rebase_path_done(); @@ -5958,7 +5958,7 @@ static int skip_unnecessary_picks(struct repository *r, todo_list->done_nr += i; if (is_fixup(peek_command(todo_list, 0))) - record_in_rewritten(base_oid, peek_command(todo_list, 0)); + record_in_rewritten(*base_oid, peek_command(todo_list, 0)); } return 0; @@ -6090,19 +6090,18 @@ static int todo_list_add_update_ref_commands(struct todo_list *todo_list) int complete_action(struct repository *r, struct replay_opts *opts, unsigned flags, const char *shortrevisions, const char *onto_name, - struct commit *onto, const struct object_id *orig_head, + const struct object_id *onto, const struct object_id *orig_head, struct string_list *commands, unsigned autosquash, unsigned update_refs, struct todo_list *todo_list, enum rebase_action action) { char shortonto[GIT_MAX_HEXSZ + 1]; const char *todo_file = rebase_path_todo(); 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; - find_unique_abbrev_r(shortonto, &oid, DEFAULT_ABBREV); + find_unique_abbrev_r(shortonto, onto, DEFAULT_ABBREV); if (buf->len == 0) { struct todo_item *item = append_new_todo(todo_list); @@ -6143,7 +6142,7 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla return error(_("nothing to do")); } else if (res == EDIT_TODO_INCORRECT) { - checkout_onto(r, opts, onto_name, &onto->object.oid, orig_head); + checkout_onto(r, opts, onto_name, onto, orig_head); todo_list_release(&new_todo); return -1; @@ -6158,7 +6157,7 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla BUG("invalid todo list after expanding IDs:\n%s", new_todo.buf.buf); - if (opts->allow_ff && skip_unnecessary_picks(r, &new_todo, &oid)) { + if (opts->allow_ff && skip_unnecessary_picks(r, &new_todo, &onto)) { todo_list_release(&new_todo); return error(_("could not skip unnecessary pick commands")); } @@ -6171,7 +6170,7 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla res = -1; - if (checkout_onto(r, opts, onto_name, &oid, orig_head)) + if (checkout_onto(r, opts, onto_name, onto, orig_head)) goto cleanup; if (require_clean_work_tree(r, "rebase", NULL, 1, 1)) diff --git a/sequencer.h b/sequencer.h index a1b8ca6eb1..24bf71d5db 100644 --- a/sequencer.h +++ b/sequencer.h @@ -188,7 +188,7 @@ int sequencer_make_script(struct repository *r, struct strbuf *out, int argc, int complete_action(struct repository *r, struct replay_opts *opts, unsigned flags, const char *shortrevisions, const char *onto_name, - struct commit *onto, const struct object_id *orig_head, + const struct object_id *onto, const struct object_id *orig_head, struct string_list *commands, unsigned autosquash, unsigned update_refs, struct todo_list *todo_list, enum rebase_action action); From patchwork Thu Mar 23 16:22:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oswald Buddenhagen X-Patchwork-Id: 13185848 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 84713C76196 for ; Thu, 23 Mar 2023 16:47:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232478AbjCWQr2 (ORCPT ); Thu, 23 Mar 2023 12:47:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52100 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232435AbjCWQrB (ORCPT ); Thu, 23 Mar 2023 12:47:01 -0400 Received: from bluemchen.kde.org (bluemchen.kde.org [IPv6:2001:470:142:8::100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8F19ABDC3 for ; Thu, 23 Mar 2023 09:46:30 -0700 (PDT) Received: from ugly.fritz.box (localhost [127.0.0.1]) by bluemchen.kde.org (Postfix) with ESMTP id E14162424B for ; Thu, 23 Mar 2023 12:22:35 -0400 (EDT) Received: by ugly.fritz.box (masqmail 0.3.4, from userid 1000) id 1pfNhz-B0h-00 for ; Thu, 23 Mar 2023 17:22:35 +0100 From: Oswald Buddenhagen To: git@vger.kernel.org Subject: [PATCH 8/8] rebase: improve resumption from incorrect initial todo list Date: Thu, 23 Mar 2023 17:22:35 +0100 Message-Id: <20230323162235.995574-9-oswald.buddenhagen@gmx.de> X-Mailer: git-send-email 2.40.0.152.g15d061e6df In-Reply-To: <20230323162235.995574-1-oswald.buddenhagen@gmx.de> References: <20230323162235.995574-1-oswald.buddenhagen@gmx.de> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org When the user butchers the todo file during rebase -i setup, the --continue which would follow --edit-todo would have skipped the last steps of the setup. Notably, this would bypass the fast-forward over untouched picks (though the actual picking loop would still fast-forward the commits, one by one). Fix this by splitting off the tail of complete_action() to a new start_rebase() function and call that from sequencer_continue() when no commands have been executed yet. More or less as a side effect, we no longer checkout `onto` before exiting when the todo file is bad. This makes aborting cheaper and will simplify things in a later change. Signed-off-by: Oswald Buddenhagen --- builtin/rebase.c | 4 +- builtin/revert.c | 3 +- sequencer.c | 89 ++++++++++++++++++++--------------- sequencer.h | 4 +- t/t3404-rebase-interactive.sh | 31 ++++++++++++ 5 files changed, 91 insertions(+), 40 deletions(-) diff --git a/builtin/rebase.c b/builtin/rebase.c index e703b29835..61e5363ac7 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -333,7 +333,9 @@ static int run_sequencer_rebase(struct rebase_options *opts) case ACTION_CONTINUE: { struct replay_opts replay_opts = get_replay_opts(opts); - ret = sequencer_continue(the_repository, &replay_opts); + ret = sequencer_continue(the_repository, &replay_opts, flags, + opts->onto_name, &opts->onto->object.oid, + &opts->orig_head->object.oid); replay_opts_release(&replay_opts); break; } diff --git a/builtin/revert.c b/builtin/revert.c index 62986a7b1b..00d3e19c62 100644 --- a/builtin/revert.c +++ b/builtin/revert.c @@ -231,7 +231,8 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts) return ret; } if (cmd == 'c') - return sequencer_continue(the_repository, opts); + return sequencer_continue(the_repository, opts, + 0, NULL, NULL, NULL); if (cmd == 'a') return sequencer_rollback(the_repository, opts); if (cmd == 's') diff --git a/sequencer.c b/sequencer.c index aef42122f1..0b4d16b8e8 100644 --- a/sequencer.c +++ b/sequencer.c @@ -3369,7 +3369,7 @@ int sequencer_skip(struct repository *r, struct replay_opts *opts) if (!is_directory(git_path_seq_dir())) return 0; - return sequencer_continue(r, opts); + return sequencer_continue(r, opts, 0, NULL, NULL, NULL); give_advice: error(_("there is nothing to skip")); @@ -5096,7 +5096,13 @@ static int commit_staged_changes(struct repository *r, return 0; } -int sequencer_continue(struct repository *r, struct replay_opts *opts) +static int start_rebase(struct repository *r, struct replay_opts *opts, unsigned flags, + const char *onto_name, const struct object_id *onto, + const struct object_id *orig_head, struct todo_list *todo_list); + +int sequencer_continue(struct repository *r, struct replay_opts *opts, unsigned flags, + const char *onto_name, const struct object_id *onto, + const struct object_id *orig_head) { struct todo_list todo_list = TODO_LIST_INIT; int res; @@ -5117,6 +5123,13 @@ int sequencer_continue(struct repository *r, struct replay_opts *opts) unlink(rebase_path_dropped()); } + if (!todo_list.done_nr) { + res = start_rebase(r, opts, flags, + onto_name, onto, + orig_head, &todo_list); + goto release_todo_list; + } + opts->reflog_message = reflog_message(opts, "continue", NULL); if (commit_staged_changes(r, opts, &todo_list)) { res = -1; @@ -6096,9 +6109,8 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla enum rebase_action action) { char shortonto[GIT_MAX_HEXSZ + 1]; - const char *todo_file = rebase_path_todo(); struct todo_list new_todo = TODO_LIST_INIT; - struct strbuf *buf = &todo_list->buf, buf2 = STRBUF_INIT; + struct strbuf *buf = &todo_list->buf; int res; find_unique_abbrev_r(shortonto, onto, DEFAULT_ABBREV); @@ -6142,49 +6154,52 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla return error(_("nothing to do")); } else if (res == EDIT_TODO_INCORRECT) { - checkout_onto(r, opts, onto_name, onto, orig_head); todo_list_release(&new_todo); return -1; } - /* 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; - 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); - - if (opts->allow_ff && skip_unnecessary_picks(r, &new_todo, &onto)) { - todo_list_release(&new_todo); - return error(_("could not skip unnecessary pick commands")); - } - - if (todo_list_write_to_file(r, &new_todo, todo_file, NULL, NULL, -1, - flags & ~(TODO_LIST_SHORTEN_IDS), action)) { - todo_list_release(&new_todo); - return error_errno(_("could not write '%s'"), todo_file); - } - - res = -1; - - if (checkout_onto(r, opts, onto_name, onto, orig_head)) - goto cleanup; - - if (require_clean_work_tree(r, "rebase", NULL, 1, 1)) - goto cleanup; - - todo_list_write_total_nr(&new_todo); - res = pick_commits(r, &new_todo, opts); - -cleanup: + res = start_rebase(r, opts, flags, onto_name, onto, orig_head, &new_todo); todo_list_release(&new_todo); return res; } +static int start_rebase(struct repository *r, struct replay_opts *opts, unsigned flags, + const char *onto_name, const struct object_id *onto, + const struct object_id *orig_head, struct todo_list *todo_list) +{ + const char *todo_file = rebase_path_todo(); + struct strbuf buf2 = STRBUF_INIT; + + /* Expand the commit IDs */ + todo_list_to_strbuf(r, todo_list, &buf2, -1, 0); + strbuf_swap(&todo_list->buf, &buf2); + strbuf_release(&buf2); + todo_list->total_nr -= todo_list->nr; + if (todo_list_parse_insn_buffer(r, todo_list->buf.buf, todo_list) < 0) + BUG("invalid todo list after expanding IDs:\n%s", + todo_list->buf.buf); + + if (opts->allow_ff && skip_unnecessary_picks(r, todo_list, &onto)) + return error(_("could not skip unnecessary pick commands")); + + if (todo_list_write_to_file(r, todo_list, todo_file, NULL, NULL, -1, + flags & ~(TODO_LIST_SHORTEN_IDS | + TODO_LIST_APPEND_TODO_HELP), + ACTION_CONTINUE)) + return error_errno(_("could not write '%s'"), todo_file); + + if (checkout_onto(r, opts, onto_name, onto, orig_head)) + return -1; + + if (require_clean_work_tree(r, "rebase", NULL, 1, 1)) + return -1; + + todo_list_write_total_nr(todo_list); + return pick_commits(r, todo_list, opts); +} + struct subject2item_entry { struct hashmap_entry entry; int i; diff --git a/sequencer.h b/sequencer.h index 24bf71d5db..33bcff89e0 100644 --- a/sequencer.h +++ b/sequencer.h @@ -158,7 +158,9 @@ void todo_list_filter_update_refs(struct repository *r, void sequencer_init_config(struct replay_opts *opts); int sequencer_pick_revisions(struct repository *repo, struct replay_opts *opts); -int sequencer_continue(struct repository *repo, struct replay_opts *opts); +int sequencer_continue(struct repository *repo, struct replay_opts *opts, unsigned flags, + const char *onto_name, const struct object_id *onto, + const struct object_id *orig_head); int sequencer_rollback(struct repository *repo, struct replay_opts *opts); int sequencer_skip(struct repository *repo, struct replay_opts *opts); void replay_opts_release(struct replay_opts *opts); diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index c625aad10a..dd47f0bbce 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -1597,6 +1597,37 @@ test_expect_success 'static check of bad command' ' test C = $(git cat-file commit HEAD^ | sed -ne \$p) ' + +test_expect_success 'continue after bad first command' ' + test_when_finished "git rebase --abort ||:" && + git checkout primary^0 && + git reflog expire --expire=all HEAD && + ( + set_fake_editor && + test_must_fail env FAKE_LINES="bad 1 pick 1 pick 2 reword 3" \ + git rebase -i HEAD~3 && + test_cmp_rev HEAD primary && + FAKE_LINES="pick 2 pick 3 reword 4" git rebase --edit-todo && + FAKE_COMMIT_MESSAGE="E_reworded" git rebase --continue + ) && + git reflog > reflog && + test $(grep -c fast-forward reflog) = 1 && + test_cmp_rev HEAD~1 primary~1 && + test "$(git log -1 --format=%B)" = "E_reworded" +' + +test_expect_success 'abort after bad first command' ' + test_when_finished "git rebase --abort ||:" && + git checkout primary^0 && + ( + set_fake_editor && + test_must_fail env FAKE_LINES="bad 1 pick 1 pick 2 reword 3" \ + git rebase -i HEAD~3 + ) && + git rebase --abort && + test_cmp_rev HEAD primary +' + test_expect_success 'tabs and spaces are accepted in the todolist' ' rebase_setup_and_clean indented-comment && write_script add-indent.sh <<-\EOF &&