rebase--helper: add a builtin helper for interactive rebases

Git's interactive rebase is still implemented as a shell script, despite its complexity. This implies that it suffers from the portability point of view, from lack of expressibility, and of course also from performance. The latter issue is particularly serious on Windows, where we pay a hefty price for relying so much on POSIX. Unfortunately, being such a huge shell script also means that we missed the train when it would have been relatively easy to port it to C, and instead piled feature upon feature onto that poor script that originally never intended to be more than a slightly pimped cherry-pick in a loop. To open the road toward better performance (in addition to all the other benefits of C over shell scripts), let's just start *somewhere*. The approach taken here is to add a builtin helper that at first intends to take care of the parts of the interactive rebase that are most affected by the performance penalties mentioned above. In particular, after we spent all those efforts on preparing the sequencer to process rebase -i's git-rebase-todo scripts, we implement the `git rebase -i --continue` functionality as a new builtin, git-rebase--helper. Once that is in place, we can work gradually on tackling the rest of the technical debt. Note that the rebase--helper needs to learn about the transient --ff/--no-ff options of git-rebase, as the corresponding flag is not persisted to, and re-read from, the state directory. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johannes Schindelin committed Feb 9, 2017 at 23:23 UTC 4557f1add261b70887136498084e7491a3f9535f
5 files changed +44
.gitignore
+1
@@ -114,6 +114,7 @@
114 /git-read-tree
115 /git-rebase
116 /git-rebase--am
117 +/git-rebase--helper
118 /git-rebase--interactive
119 /git-rebase--merge
120 /git-receive-pack
Makefile
+1
@@ -932,6 +932,7 @@ BUILTIN_OBJS += builtin/prune.o
932 BUILTIN_OBJS += builtin/pull.o
933 BUILTIN_OBJS += builtin/push.o
934 BUILTIN_OBJS += builtin/read-tree.o
935 +BUILTIN_OBJS += builtin/rebase--helper.o
936 BUILTIN_OBJS += builtin/receive-pack.o
937 BUILTIN_OBJS += builtin/reflog.o
938 BUILTIN_OBJS += builtin/remote.o
builtin.h
+1
@@ -103,6 +103,7 @@ extern int cmd_prune_packed(int argc, const char **argv, const char *prefix);
103 extern int cmd_pull(int argc, const char **argv, const char *prefix);
104 extern int cmd_push(int argc, const char **argv, const char *prefix);
105 extern int cmd_read_tree(int argc, const char **argv, const char *prefix);
106 +extern int cmd_rebase__helper(int argc, const char **argv, const char *prefix);
107 extern int cmd_receive_pack(int argc, const char **argv, const char *prefix);
108 extern int cmd_reflog(int argc, const char **argv, const char *prefix);
109 extern int cmd_remote(int argc, const char **argv, const char *prefix);
builtin/rebase--helper.c new
+40
@@ -0,0 +1,40 @@
1 +#include "builtin.h"
2 +#include "cache.h"
3 +#include "parse-options.h"
4 +#include "sequencer.h"
5 +
6 +static const char * const builtin_rebase_helper_usage[] = {
7 + N_("git rebase--helper [<options>]"),
8 + NULL
9 +};
10 +
11 +int cmd_rebase__helper(int argc, const char **argv, const char *prefix)
12 +{
13 + struct replay_opts opts = REPLAY_OPTS_INIT;
14 + enum {
15 + CONTINUE = 1, ABORT
16 + } command = 0;
17 + struct option options[] = {
18 + OPT_BOOL(0, "ff", &opts.allow_ff, N_("allow fast-forward")),
19 + OPT_CMDMODE(0, "continue", &command, N_("continue rebase"),
20 + CONTINUE),
21 + OPT_CMDMODE(0, "abort", &command, N_("abort rebase"),
22 + ABORT),
23 + OPT_END()
24 + };
25 +
26 + git_config(git_default_config, NULL);
27 +
28 + opts.action = REPLAY_INTERACTIVE_REBASE;
29 + opts.allow_ff = 1;
30 + opts.allow_empty = 1;
31 +
32 + argc = parse_options(argc, argv, NULL, options,
33 + builtin_rebase_helper_usage, PARSE_OPT_KEEP_ARGV0);
34 +
35 + if (command == CONTINUE && argc == 1)
36 + return !!sequencer_continue(&opts);
37 + if (command == ABORT && argc == 1)
38 + return !!sequencer_remove_state(&opts);
39 + usage_with_options(builtin_rebase_helper_usage, options);
40 +}
git.c
+1
@@ -473,6 +473,7 @@ static struct cmd_struct commands[] = {
473 { "pull", cmd_pull, RUN_SETUP | NEED_WORK_TREE },
474 { "push", cmd_push, RUN_SETUP },
475 { "read-tree", cmd_read_tree, RUN_SETUP | SUPPORT_SUPER_PREFIX},
476 + { "rebase--helper", cmd_rebase__helper, RUN_SETUP | NEED_WORK_TREE },
477 { "receive-pack", cmd_receive_pack },
478 { "reflog", cmd_reflog, RUN_SETUP },
479 { "remote", cmd_remote, RUN_SETUP },