{"thread":{"id":"49072","subject":"[GSoC] [PATCH 0/7] builtin rebase actions","startedAt":"2018-08-08T15:08:36Z","lastAt":"2018-08-08T15:09:02Z","messageCount":8,"participants":["Pratik Karki"],"isPatch":true,"patchVersion":1,"patchTotal":7},"messages":[{"id":"354813","messageId":"20180808150622.9614-1-predatoramigo@gmail.com","threadId":"49072","inReplyTo":null,"subject":"[GSoC] [PATCH 0/7] builtin rebase actions","fromName":"Pratik Karki","fromEmail":"predatoramigo@gmail.com","sentAt":"2018-08-08T15:06:15Z","receivedAt":"2018-08-08T15:08:36Z","isPatch":true,"sender":{"key":"predatoramigo@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12194950?v=4"},"body":"The previous patch series implemented essential options and neccessary\nconfigurations. This patch series teaches all the rebase actions like\n`--continue`, `--skip`, `--abort`, et al. to builtin rebase.\n\nThese actions are important to operation of `git rebase` hence, are kept\nin a patch series of their own.\n\nIt adds the rebase actions to the previous patch series,\n(https://public-inbox.org/git/20180808134830.19949-1-predatoramigo@gmail.com/).\n\nThis is the third patch series that brings us more closer to a builtin\n\"git rebase\".\n\nIf you like to view the development branch, you can view\n(https://github.com/git/git/pull/505), where I have kept my commits up to date\nand leveraged Travis(there is sporadic failures in t5520 for macos gcc and\nisn't due to my patches) for extra testing other than my system.\n\nThe next in line patch series which I'll be sending out today are:\n\nbuiltin rebase options: The builtin rebase will add all the options supported\nby original rebase.\nbuiltin rebase rest: The builtin rebase will convert all the remaining shell\nscripts from the original rebase to C.\ndefault to builtin rebase: This will turn on the feature-complete builtin\nrebase to on.\n\nThese patch series are built on top of each other, i.e. they depend on this\norder.\n\nPratik Karki (7):\n  builtin rebase: support --continue\n  builtin rebase: support --skip\n  builtin rebase: support --abort\n  builtin rebase: support --quit\n  builtin rebase: support --edit-todo and --show-current-patch\n  builtin rebase: actions require a rebase in progress\n  builtin rebase: stop if `git am` is in progress\n\n builtin/rebase.c | 193 ++++++++++++++++++++++++++++++++++++++++++++++-\n strbuf.c         |   9 +++\n strbuf.h         |   3 +\n 3 files changed, 201 insertions(+), 4 deletions(-)\n\n-- \n2.18.0\n\n"},{"id":"354814","messageId":"20180808150622.9614-2-predatoramigo@gmail.com","threadId":"49072","inReplyTo":"20180808150622.9614-1-predatoramigo@gmail.com","subject":"[PATCH 1/7] builtin rebase: support --continue","fromName":"Pratik Karki","fromEmail":"predatoramigo@gmail.com","sentAt":"2018-08-08T15:06:16Z","receivedAt":"2018-08-08T15:08:41Z","isPatch":true,"sender":{"key":"predatoramigo@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12194950?v=4"},"body":"This commit adds the option `--continue` which is used to resume\nrebase after merge conflicts. The code tries to stay as close to\nthe equivalent shell scripts found in `git-legacy-rebase.sh` as\npossible.\n\nWhen continuing a rebase, the state variables are read from state_dir.\nSome of the state variables are not actually stored there, such as\n`upstream`. The shell script version simply does not set them, but for\nconsistency, we unset them in the builtin version.\n\nSigned-off-by: Pratik Karki <predatoramigo@gmail.com>\n---\n builtin/rebase.c | 115 +++++++++++++++++++++++++++++++++++++++++++++--\n strbuf.c         |   9 ++++\n strbuf.h         |   3 ++\n 3 files changed, 123 insertions(+), 4 deletions(-)\n\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex b2ddfa8dbf..10da4c978b 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -91,6 +91,7 @@ struct rebase_options {\n \t\tREBASE_INTERACTIVE_EXPLICIT = 1<<4,\n \t} flags;\n \tstruct strbuf git_am_opt;\n+\tconst char *action;\n };\n \n static int is_interactive(struct rebase_options *opts)\n@@ -115,6 +116,62 @@ static const char *state_dir_path(const char *filename, struct rebase_options *o\n \treturn path.buf;\n }\n \n+/* Read one file, then strip line endings */\n+static int read_one(const char *path, struct strbuf *buf)\n+{\n+\tif (strbuf_read_file(buf, path, 0) < 0)\n+\t\treturn error_errno(_(\"could not read '%s'\"), path);\n+\tstrbuf_trim_trailing_newline(buf);\n+\treturn 0;\n+}\n+\n+/* Initialize the rebase options from the state directory. */\n+static int read_basic_state(struct rebase_options *opts)\n+{\n+\tstruct strbuf head_name = STRBUF_INIT;\n+\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct object_id oid;\n+\n+\tif (read_one(state_dir_path(\"head-name\", opts), &head_name) ||\n+\t    read_one(state_dir_path(\"onto\", opts), &buf))\n+\t\treturn -1;\n+\topts->head_name = starts_with(head_name.buf, \"refs/\") ?\n+\t\txstrdup(head_name.buf) : NULL;\n+\tstrbuf_release(&head_name);\n+\tif (get_oid(buf.buf, &oid))\n+\t\treturn error(_(\"could not get 'onto': '%s'\"), buf.buf);\n+\topts->onto = lookup_commit_or_die(&oid, buf.buf);\n+\n+\t/*\n+\t * We always write to orig-head, but interactive rebase used to write to\n+\t * head. Fall back to reading from head to cover for the case that the\n+\t * user upgraded git with an ongoing interactive rebase.\n+\t */\n+\tstrbuf_reset(&buf);\n+\tif (file_exists(state_dir_path(\"orig-head\", opts))) {\n+\t\tif (read_one(state_dir_path(\"orig-head\", opts), &buf))\n+\t\t\treturn -1;\n+\t} else if (read_one(state_dir_path(\"head\", opts), &buf))\n+\t\treturn -1;\n+\tif (get_oid(buf.buf, &opts->orig_head))\n+\t\treturn error(_(\"invalid orig-head: '%s'\"), buf.buf);\n+\n+\tstrbuf_reset(&buf);\n+\tif (read_one(state_dir_path(\"quiet\", opts), &buf))\n+\t\treturn -1;\n+\tif (buf.len)\n+\t\topts->flags &= ~REBASE_NO_QUIET;\n+\telse\n+\t\topts->flags |= REBASE_NO_QUIET;\n+\n+\tif (file_exists(state_dir_path(\"verbose\", opts)))\n+\t\topts->flags |= REBASE_VERBOSE;\n+\n+\tstrbuf_release(&buf);\n+\n+\treturn 0;\n+}\n+\n static int finish_rebase(struct rebase_options *opts)\n {\n \tstruct strbuf dir = STRBUF_INIT;\n@@ -168,12 +225,13 @@ static int run_specific_rebase(struct rebase_options *opts)\n \tadd_var(&script_snippet, \"state_dir\", opts->state_dir);\n \n \tadd_var(&script_snippet, \"upstream_name\", opts->upstream_name);\n-\tadd_var(&script_snippet, \"upstream\",\n-\t\t\t\t oid_to_hex(&opts->upstream->object.oid));\n+\tadd_var(&script_snippet, \"upstream\", opts->upstream ?\n+\t\toid_to_hex(&opts->upstream->object.oid) : NULL);\n \tadd_var(&script_snippet, \"head_name\",\n \t\topts->head_name ? opts->head_name : \"detached HEAD\");\n \tadd_var(&script_snippet, \"orig_head\", oid_to_hex(&opts->orig_head));\n-\tadd_var(&script_snippet, \"onto\", oid_to_hex(&opts->onto->object.oid));\n+\tadd_var(&script_snippet, \"onto\", opts->onto ?\n+\t\toid_to_hex(&opts->onto->object.oid) : NULL);\n \tadd_var(&script_snippet, \"onto_name\", opts->onto_name);\n \tadd_var(&script_snippet, \"revisions\", opts->revisions);\n \tadd_var(&script_snippet, \"restrict_revision\", opts->restrict_revision ?\n@@ -189,6 +247,7 @@ static int run_specific_rebase(struct rebase_options *opts)\n \t\topts->flags & REBASE_FORCE ? \"t\" : \"\");\n \tif (opts->switch_to)\n \t\tadd_var(&script_snippet, \"switch_to\", opts->switch_to);\n+\tadd_var(&script_snippet, \"action\", opts->action ? opts->action : \"\");\n \n \tswitch (opts->type) {\n \tcase REBASE_AM:\n@@ -400,12 +459,16 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t.git_am_opt = STRBUF_INIT,\n \t};\n \tconst char *branch_name;\n-\tint ret, flags, in_progress = 0;\n+\tint ret, flags, total_argc, in_progress = 0;\n \tint ok_to_skip_pre_rebase = 0;\n \tstruct strbuf msg = STRBUF_INIT;\n \tstruct strbuf revisions = STRBUF_INIT;\n \tstruct strbuf buf = STRBUF_INIT;\n \tstruct object_id merge_base;\n+\tenum {\n+\t\tNO_ACTION,\n+\t\tACTION_CONTINUE,\n+\t} action = NO_ACTION;\n \tstruct option builtin_rebase_options[] = {\n \t\tOPT_STRING(0, \"onto\", &options.onto_name,\n \t\t\t   N_(\"revision\"),\n@@ -427,6 +490,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tOPT_BIT(0, \"no-ff\", &options.flags,\n \t\t\tN_(\"cherry-pick all commits, even if unchanged\"),\n \t\t\tREBASE_FORCE),\n+\t\tOPT_CMDMODE(0, \"continue\", &action, N_(\"continue\"),\n+\t\t\t    ACTION_CONTINUE),\n \t\tOPT_END(),\n \t};\n \n@@ -480,14 +545,55 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \tif (options.type != REBASE_UNSPECIFIED)\n \t\tin_progress = 1;\n \n+\ttotal_argc = argc;\n \targc = parse_options(argc, argv, prefix,\n \t\t\t     builtin_rebase_options,\n \t\t\t     builtin_rebase_usage, 0);\n \n+\tif (action != NO_ACTION && total_argc != 2) {\n+\t\tusage_with_options(builtin_rebase_usage,\n+\t\t\t\t   builtin_rebase_options);\n+\t}\n+\n \tif (argc > 2)\n \t\tusage_with_options(builtin_rebase_usage,\n \t\t\t\t   builtin_rebase_options);\n \n+\tswitch (action) {\n+\tcase ACTION_CONTINUE: {\n+\t\tstruct object_id head;\n+\t\tstruct lock_file lock_file = LOCK_INIT;\n+\t\tint fd;\n+\n+\t\toptions.action = \"continue\";\n+\n+\t\t/* Sanity check */\n+\t\tif (get_oid(\"HEAD\", &head))\n+\t\t\tdie(_(\"Cannot read HEAD\"));\n+\n+\t\tfd = hold_locked_index(&lock_file, 0);\n+\t\tif (read_index(the_repository->index) < 0)\n+\t\t\tdie(_(\"could not read index\"));\n+\t\trefresh_index(the_repository->index, REFRESH_QUIET, NULL, NULL,\n+\t\t\t      NULL);\n+\t\tif (0 <= fd)\n+\t\t\tupdate_index_if_able(the_repository->index,\n+\t\t\t\t\t     &lock_file);\n+\t\trollback_lock_file(&lock_file);\n+\n+\t\tif (has_unstaged_changes(1)) {\n+\t\t\tputs(_(\"You must edit all merge conflicts and then\\n\"\n+\t\t\t       \"mark them as resolved using git add\"));\n+\t\t\texit(1);\n+\t\t}\n+\t\tif (read_basic_state(&options))\n+\t\t\texit(1);\n+\t\tgoto run_rebase;\n+\t}\n+\tdefault:\n+\t\tdie(\"TODO\");\n+\t}\n+\n \t/* Make sure no rebase is in progress */\n \tif (in_progress) {\n \t\tconst char *last_slash = strrchr(options.state_dir, '/');\n@@ -719,6 +825,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \n \toptions.revisions = revisions.buf;\n \n+run_rebase:\n \tret = !!run_specific_rebase(&options);\n \n cleanup:\ndiff --git a/strbuf.c b/strbuf.c\nindex 030556111d..fdc0ffbafb 100644\n--- a/strbuf.c\n+++ b/strbuf.c\n@@ -120,6 +120,15 @@ void strbuf_trim_trailing_dir_sep(struct strbuf *sb)\n \tsb->buf[sb->len] = '\\0';\n }\n \n+void strbuf_trim_trailing_newline(struct strbuf *sb)\n+{\n+\tif (sb->len > 0 && sb->buf[sb->len - 1] == '\\n') {\n+\t\tif (--sb->len > 0 && sb->buf[sb->len - 1] == '\\r')\n+\t\t\t--sb->len;\n+\t\tsb->buf[sb->len] = '\\0';\n+\t}\n+}\n+\n void strbuf_ltrim(struct strbuf *sb)\n {\n \tchar *b = sb->buf;\ndiff --git a/strbuf.h b/strbuf.h\nindex 60a35aef16..b7aea8a966 100644\n--- a/strbuf.h\n+++ b/strbuf.h\n@@ -190,6 +190,9 @@ extern void strbuf_ltrim(struct strbuf *);\n /* Strip trailing directory separators */\n extern void strbuf_trim_trailing_dir_sep(struct strbuf *);\n \n+/* Strip trailing LF or CR/LF */\n+extern void strbuf_trim_trailing_newline(struct strbuf *sb);\n+\n /**\n  * Replace the contents of the strbuf with a reencoded form.  Returns -1\n  * on error, 0 on success.\n-- \n2.18.0\n\n"},{"id":"354815","messageId":"20180808150622.9614-3-predatoramigo@gmail.com","threadId":"49072","inReplyTo":"20180808150622.9614-1-predatoramigo@gmail.com","subject":"[PATCH 2/7] builtin rebase: support --skip","fromName":"Pratik Karki","fromEmail":"predatoramigo@gmail.com","sentAt":"2018-08-08T15:06:17Z","receivedAt":"2018-08-08T15:08:44Z","isPatch":true,"sender":{"key":"predatoramigo@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12194950?v=4"},"body":"This commit adds the option `--skip` which is used to restart\nrebase after skipping the current patch.\n\nSigned-off-by: Pratik Karki <predatoramigo@gmail.com>\n---\n builtin/rebase.c | 18 ++++++++++++++++++\n 1 file changed, 18 insertions(+)\n\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 10da4c978b..7a903838b1 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -21,6 +21,7 @@\n #include \"diff.h\"\n #include \"wt-status.h\"\n #include \"revision.h\"\n+#include \"rerere.h\"\n \n static char const * const builtin_rebase_usage[] = {\n \tN_(\"git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] \"\n@@ -468,6 +469,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \tenum {\n \t\tNO_ACTION,\n \t\tACTION_CONTINUE,\n+\t\tACTION_SKIP,\n \t} action = NO_ACTION;\n \tstruct option builtin_rebase_options[] = {\n \t\tOPT_STRING(0, \"onto\", &options.onto_name,\n@@ -492,6 +494,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\tREBASE_FORCE),\n \t\tOPT_CMDMODE(0, \"continue\", &action, N_(\"continue\"),\n \t\t\t    ACTION_CONTINUE),\n+\t\tOPT_CMDMODE(0, \"skip\", &action,\n+\t\t\t    N_(\"skip current patch and continue\"), ACTION_SKIP),\n \t\tOPT_END(),\n \t};\n \n@@ -590,6 +594,20 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\texit(1);\n \t\tgoto run_rebase;\n \t}\n+\tcase ACTION_SKIP: {\n+\t\tstruct string_list merge_rr = STRING_LIST_INIT_DUP;\n+\n+\t\toptions.action = \"skip\";\n+\n+\t\trerere_clear(&merge_rr);\n+\t\tstring_list_clear(&merge_rr, 1);\n+\n+\t\tif (reset_head(NULL, \"reset\", NULL, 0) < 0)\n+\t\t\tdie(_(\"could not discard worktree changes\"));\n+\t\tif (read_basic_state(&options))\n+\t\t\texit(1);\n+\t\tgoto run_rebase;\n+\t}\n \tdefault:\n \t\tdie(\"TODO\");\n \t}\n-- \n2.18.0\n\n"},{"id":"354816","messageId":"20180808150622.9614-4-predatoramigo@gmail.com","threadId":"49072","inReplyTo":"20180808150622.9614-1-predatoramigo@gmail.com","subject":"[PATCH 3/7] builtin rebase: support --abort","fromName":"Pratik Karki","fromEmail":"predatoramigo@gmail.com","sentAt":"2018-08-08T15:06:18Z","receivedAt":"2018-08-08T15:08:47Z","isPatch":true,"sender":{"key":"predatoramigo@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12194950?v=4"},"body":"This commit teaches the builtin rebase the \"abort\" action, which a user\ncan call to roll back a rebase that is in progress.\n\nSigned-off-by: Pratik Karki <predatoramigo@gmail.com>\n---\n builtin/rebase.c | 20 ++++++++++++++++++++\n 1 file changed, 20 insertions(+)\n\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 7a903838b1..8e94f6cc85 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -470,6 +470,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tNO_ACTION,\n \t\tACTION_CONTINUE,\n \t\tACTION_SKIP,\n+\t\tACTION_ABORT,\n \t} action = NO_ACTION;\n \tstruct option builtin_rebase_options[] = {\n \t\tOPT_STRING(0, \"onto\", &options.onto_name,\n@@ -496,6 +497,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\t    ACTION_CONTINUE),\n \t\tOPT_CMDMODE(0, \"skip\", &action,\n \t\t\t    N_(\"skip current patch and continue\"), ACTION_SKIP),\n+\t\tOPT_CMDMODE(0, \"abort\", &action,\n+\t\t\t    N_(\"abort and check out the original branch\"),\n+\t\t\t    ACTION_ABORT),\n \t\tOPT_END(),\n \t};\n \n@@ -608,6 +612,22 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\texit(1);\n \t\tgoto run_rebase;\n \t}\n+\tcase ACTION_ABORT: {\n+\t\tstruct string_list merge_rr = STRING_LIST_INIT_DUP;\n+\t\toptions.action = \"abort\";\n+\n+\t\trerere_clear(&merge_rr);\n+\t\tstring_list_clear(&merge_rr, 1);\n+\n+\t\tif (read_basic_state(&options))\n+\t\t\texit(1);\n+\t\tif (reset_head(&options.orig_head, \"reset\",\n+\t\t\t       options.head_name, 0) < 0)\n+\t\t\tdie(_(\"could not move back to %s\"),\n+\t\t\t    oid_to_hex(&options.orig_head));\n+\t\tret = finish_rebase(&options);\n+\t\tgoto cleanup;\n+\t}\n \tdefault:\n \t\tdie(\"TODO\");\n \t}\n-- \n2.18.0\n\n"},{"id":"354817","messageId":"20180808150622.9614-5-predatoramigo@gmail.com","threadId":"49072","inReplyTo":"20180808150622.9614-1-predatoramigo@gmail.com","subject":"[PATCH 4/7] builtin rebase: support --quit","fromName":"Pratik Karki","fromEmail":"predatoramigo@gmail.com","sentAt":"2018-08-08T15:06:19Z","receivedAt":"2018-08-08T15:08:51Z","isPatch":true,"sender":{"key":"predatoramigo@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12194950?v=4"},"body":"With this patch, the builtin rebase handles the `--quit` action which\ncan be used to abort a rebase without rolling back any changes performed\nduring the rebase (this is useful when a user forgot that they were in\nthe middle of a rebase and continued working normally).\n\nSigned-off-by: Pratik Karki <predatoramigo@gmail.com>\n---\n builtin/rebase.c | 11 +++++++++++\n 1 file changed, 11 insertions(+)\n\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 8e94f6cc85..0d805480a1 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -471,6 +471,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tACTION_CONTINUE,\n \t\tACTION_SKIP,\n \t\tACTION_ABORT,\n+\t\tACTION_QUIT,\n \t} action = NO_ACTION;\n \tstruct option builtin_rebase_options[] = {\n \t\tOPT_STRING(0, \"onto\", &options.onto_name,\n@@ -500,6 +501,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tOPT_CMDMODE(0, \"abort\", &action,\n \t\t\t    N_(\"abort and check out the original branch\"),\n \t\t\t    ACTION_ABORT),\n+\t\tOPT_CMDMODE(0, \"quit\", &action,\n+\t\t\t    N_(\"abort but keep HEAD where it is\"), ACTION_QUIT),\n \t\tOPT_END(),\n \t};\n \n@@ -628,6 +631,14 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tret = finish_rebase(&options);\n \t\tgoto cleanup;\n \t}\n+\tcase ACTION_QUIT: {\n+\t\tstrbuf_reset(&buf);\n+\t\tstrbuf_addstr(&buf, options.state_dir);\n+\t\tret = !!remove_dir_recursively(&buf, 0);\n+\t\tif (ret)\n+\t\t\tdie(_(\"could not remove '%s'\"), options.state_dir);\n+\t\tgoto cleanup;\n+\t}\n \tdefault:\n \t\tdie(\"TODO\");\n \t}\n-- \n2.18.0\n\n"},{"id":"354818","messageId":"20180808150622.9614-6-predatoramigo@gmail.com","threadId":"49072","inReplyTo":"20180808150622.9614-1-predatoramigo@gmail.com","subject":"[PATCH 5/7] builtin rebase: support --edit-todo and --show-current-patch","fromName":"Pratik Karki","fromEmail":"predatoramigo@gmail.com","sentAt":"2018-08-08T15:06:20Z","receivedAt":"2018-08-08T15:08:55Z","isPatch":true,"sender":{"key":"predatoramigo@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12194950?v=4"},"body":"While these sub-commands are very different in spirit, their\nimplementation is almost identical, so we convert them in one go.\n\nAnd since those are the last sub-commands that needed to be converted,\nnow we can also turn that `default:` case into a bug (because we should\nnow handle all the actions).\n\nSigned-off-by: Pratik Karki <predatoramigo@gmail.com>\n---\n builtin/rebase.c | 23 ++++++++++++++++++++++-\n 1 file changed, 22 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 0d805480a1..e3dd2f511e 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -472,6 +472,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tACTION_SKIP,\n \t\tACTION_ABORT,\n \t\tACTION_QUIT,\n+\t\tACTION_EDIT_TODO,\n+\t\tACTION_SHOW_CURRENT_PATCH,\n \t} action = NO_ACTION;\n \tstruct option builtin_rebase_options[] = {\n \t\tOPT_STRING(0, \"onto\", &options.onto_name,\n@@ -503,6 +505,11 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\t    ACTION_ABORT),\n \t\tOPT_CMDMODE(0, \"quit\", &action,\n \t\t\t    N_(\"abort but keep HEAD where it is\"), ACTION_QUIT),\n+\t\tOPT_CMDMODE(0, \"edit-todo\", &action, N_(\"edit the todo list \"\n+\t\t\t    \"during an interactive rebase\"), ACTION_EDIT_TODO),\n+\t\tOPT_CMDMODE(0, \"show-current-patch\", &action,\n+\t\t\t    N_(\"show the patch file being applied or merged\"),\n+\t\t\t    ACTION_SHOW_CURRENT_PATCH),\n \t\tOPT_END(),\n \t};\n \n@@ -570,6 +577,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tusage_with_options(builtin_rebase_usage,\n \t\t\t\t   builtin_rebase_options);\n \n+\tif (action == ACTION_EDIT_TODO && !is_interactive(&options))\n+\t\tdie(_(\"The --edit-todo action can only be used during \"\n+\t\t      \"interactive rebase.\"));\n+\n \tswitch (action) {\n \tcase ACTION_CONTINUE: {\n \t\tstruct object_id head;\n@@ -639,8 +650,18 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\tdie(_(\"could not remove '%s'\"), options.state_dir);\n \t\tgoto cleanup;\n \t}\n+\tcase ACTION_EDIT_TODO:\n+\t\toptions.action = \"edit-todo\";\n+\t\toptions.dont_finish_rebase = 1;\n+\t\tgoto run_rebase;\n+\tcase ACTION_SHOW_CURRENT_PATCH:\n+\t\toptions.action = \"show-current-patch\";\n+\t\toptions.dont_finish_rebase = 1;\n+\t\tgoto run_rebase;\n+\tcase NO_ACTION:\n+\t\tbreak;\n \tdefault:\n-\t\tdie(\"TODO\");\n+\t\tBUG(\"action: %d\", action);\n \t}\n \n \t/* Make sure no rebase is in progress */\n-- \n2.18.0\n\n"},{"id":"354819","messageId":"20180808150622.9614-7-predatoramigo@gmail.com","threadId":"49072","inReplyTo":"20180808150622.9614-1-predatoramigo@gmail.com","subject":"[PATCH 6/7] builtin rebase: actions require a rebase in progress","fromName":"Pratik Karki","fromEmail":"predatoramigo@gmail.com","sentAt":"2018-08-08T15:06:21Z","receivedAt":"2018-08-08T15:08:58Z","isPatch":true,"sender":{"key":"predatoramigo@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12194950?v=4"},"body":"This commit prevents actions (such as --continue, --skip) from running\nwhen there is no rebase in progress.\n\nSigned-off-by: Pratik Karki <predatoramigo@gmail.com>\n---\n builtin/rebase.c | 3 +++\n 1 file changed, 3 insertions(+)\n\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex e3dd2f511e..1344e071f3 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -577,6 +577,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tusage_with_options(builtin_rebase_usage,\n \t\t\t\t   builtin_rebase_options);\n \n+\tif (action != NO_ACTION && !in_progress)\n+\t\tdie(_(\"No rebase in progress?\"));\n+\n \tif (action == ACTION_EDIT_TODO && !is_interactive(&options))\n \t\tdie(_(\"The --edit-todo action can only be used during \"\n \t\t      \"interactive rebase.\"));\n-- \n2.18.0\n\n"},{"id":"354820","messageId":"20180808150622.9614-8-predatoramigo@gmail.com","threadId":"49072","inReplyTo":"20180808150622.9614-1-predatoramigo@gmail.com","subject":"[PATCH 7/7] builtin rebase: stop if `git am` is in progress","fromName":"Pratik Karki","fromEmail":"predatoramigo@gmail.com","sentAt":"2018-08-08T15:06:22Z","receivedAt":"2018-08-08T15:09:02Z","isPatch":true,"sender":{"key":"predatoramigo@gmail.com","avatar":"https://avatars.githubusercontent.com/u/12194950?v=4"},"body":"This commit checks for the file `applying` used by `git am` in\n`rebase-apply/` and if the file is present it means `git am` is in\nprogress so it errors out.\n\nSigned-off-by: Pratik Karki <predatoramigo@gmail.com>\n---\n builtin/rebase.c | 5 +++++\n 1 file changed, 5 insertions(+)\n\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 1344e071f3..75c4ac66e0 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -539,6 +539,11 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \n \tgit_config(rebase_config, &options);\n \n+\tstrbuf_reset(&buf);\n+\tstrbuf_addf(&buf, \"%s/applying\", apply_dir());\n+\tif(file_exists(buf.buf))\n+\t\tdie(_(\"It looks like 'git am' is in progress. Cannot rebase.\"));\n+\n \tif (is_directory(apply_dir())) {\n \t\toptions.type = REBASE_AM;\n \t\toptions.state_dir = apply_dir();\n-- \n2.18.0\n\n"}]}