From: Phil Hord <phil.hord@xxxxxxxxx> Expand the rebase edit switches to include the break switch. This switch lets the user add a "break" instruction to the todo-list before the mentioned reference. This switch is a little different from the ones added so far because it adds a new instruction between commits in the todo-list instead of changing the command used to include a commit. It is a little like "exec" in this regard, except it doesn't add the command after every commit. It is not immediately clear whether we should add the break command before or after the referenced commit. That is, when the user says '--break ref', does she mean to break after ref is picked or before it? The answer comes when we realize that a 'break' after a ref is functionally the same as '--edit ref'. Since the user didn't say '--edit ref', clearly she must have wanted to break _before_ ref is picked. So, insert the break before the mentioned ref. Annoyingly, however, when git stops at a break, it declares that the previous commit is the one we stopped on, which is always different from the one the user specified. Does anyone care? Should --break effectively be an alias for --edit? '--break <ref>' to stop the rebase before the mentioned commit Signed-off-by: Phil Hord <phil.hord@xxxxxxxxx> --- builtin/rebase--interactive.c | 3 +++ builtin/rebase.c | 4 ++++ sequencer.c | 7 +++++++ sequencer.h | 1 + 4 files changed, 15 insertions(+) diff --git a/builtin/rebase--interactive.c b/builtin/rebase--interactive.c index 9285d05443..a81fa9c1c5 100644 --- a/builtin/rebase--interactive.c +++ b/builtin/rebase--interactive.c @@ -164,6 +164,7 @@ static int resolve_commit_list(const struct string_list *str, static int resolve_edits_commit_list(struct sequence_edits *edits) { return resolve_commit_list(&edits->drop, &edits->revs) || + resolve_commit_list(&edits->breaks, &edits->revs) || resolve_commit_list(&edits->edit, &edits->revs) || resolve_commit_list(&edits->reword, &edits->revs); } @@ -302,6 +303,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix) N_("restrict-revision"), N_("restrict revision")), OPT_STRING(0, "squash-onto", &squash_onto, N_("squash-onto"), N_("squash onto")), + OPT_STRING_LIST(0, "break", &edits.breaks, N_("revision"), + N_("stop before the mentioned ref")), OPT_STRING_LIST(0, "drop", &edits.drop, N_("revision"), N_("drop the mentioned ref from the " "todo list")), diff --git a/builtin/rebase.c b/builtin/rebase.c index a8101630cf..02079c4172 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -1053,6 +1053,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) NULL }; const char *gpg_sign = NULL; struct string_list exec = STRING_LIST_INIT_NODUP; + struct string_list breaks = STRING_LIST_INIT_NODUP; struct string_list reword = STRING_LIST_INIT_NODUP; struct string_list edit = STRING_LIST_INIT_NODUP; struct string_list drop = STRING_LIST_INIT_NODUP; @@ -1138,6 +1139,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) OPT_STRING_LIST('x', "exec", &exec, N_("exec"), N_("add exec lines after each commit of the " "editable list")), + OPT_STRING_LIST(0, "break", &breaks, N_("revision"), + N_("stop before the mentioned ref")), OPT_STRING_LIST(0, "drop", &drop, N_("revision"), N_("drop the mentioned ref from the " "todo list")), @@ -1404,6 +1407,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) options.cmd = xstrdup(buf.buf); } + forward_switches(&options, "--break", &breaks); forward_switches(&options, "--drop", &drop); forward_switches(&options, "--edit", &edit); forward_switches(&options, "--reword", &reword); diff --git a/sequencer.c b/sequencer.c index d7384d987c..4a1a371757 100644 --- a/sequencer.c +++ b/sequencer.c @@ -4261,6 +4261,7 @@ static const char *label_oid(struct object_id *oid, const char *label, void free_sequence_edits(struct sequence_edits *edits) { + string_list_clear(&edits->breaks, 0); string_list_clear(&edits->drop, 0); string_list_clear(&edits->edit, 0); string_list_clear(&edits->reword, 0); @@ -4294,6 +4295,7 @@ static int check_unused_refs(const struct string_list *refs) static int check_unused_edits(const struct sequence_edits *edits) { return check_unused_refs(&edits->drop) || + check_unused_refs(&edits->breaks) || check_unused_refs(&edits->edit) || check_unused_refs(&edits->reword); } @@ -4320,6 +4322,11 @@ static void add_edit_todo_inst(struct strbuf *buf, const struct object_id *oid, { enum todo_command cmd = TODO_PICK; + if (consume_oid(oid, &edits->breaks)) { + add_todo_cmd(buf, TODO_BREAK, flags); + strbuf_addstr(buf, "\n"); + } + if (consume_oid(oid, &edits->drop)) cmd = TODO_DROP; else if (consume_oid(oid, &edits->edit)) diff --git a/sequencer.h b/sequencer.h index 7887509fea..310829f222 100644 --- a/sequencer.h +++ b/sequencer.h @@ -139,6 +139,7 @@ int sequencer_remove_state(struct replay_opts *opts); */ struct sequence_edits { struct commit_list *revs; + struct string_list breaks; struct string_list drop; struct string_list edit; struct string_list reword; -- 2.20.1