rebase -i: rewrite checkout_onto() in C

This rewrites checkout_onto() from shell to C. A new command (“checkout-onto”) is added to rebase--helper.c. The shell version is then stripped. Signed-off-by: Alban Gruin <alban.gruin@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Alban Gruin committed Aug 10, 2018 at 18:51 UTC 4df66c40b08931eb224964f12decbb0f660cf932
4 files changed +32 -22
builtin/rebase--helper.c
+6 -1
@@ -18,7 +18,8 @@ int cmd_rebase__helper(int argc, const char **argv, const char *prefix)
18 enum {
19 CONTINUE = 1, ABORT, MAKE_SCRIPT, SHORTEN_OIDS, EXPAND_OIDS,
20 CHECK_TODO_LIST, SKIP_UNNECESSARY_PICKS, REARRANGE_SQUASH,
21 - ADD_EXEC, APPEND_TODO_HELP, EDIT_TODO, PREPARE_BRANCH
21 + ADD_EXEC, APPEND_TODO_HELP, EDIT_TODO, PREPARE_BRANCH,
22 + CHECKOUT_ONTO
23 } command = 0;
24 struct option options[] = {
25 OPT_BOOL(0, "ff", &opts.allow_ff, N_("allow fast-forward")),
@@ -54,6 +55,8 @@ int cmd_rebase__helper(int argc, const char **argv, const char *prefix)
55 EDIT_TODO),
56 OPT_CMDMODE(0, "prepare-branch", &command,
57 N_("prepare the branch to be rebased"), PREPARE_BRANCH),
58 + OPT_CMDMODE(0, "checkout-onto", &command,
59 + N_("checkout a commit"), CHECKOUT_ONTO),
60 OPT_END()
61 };
62
@@ -99,5 +102,7 @@ int cmd_rebase__helper(int argc, const char **argv, const char *prefix)
102 return !!edit_todo_list(flags);
103 if (command == PREPARE_BRANCH && argc == 2)
104 return !!prepare_branch_to_be_rebased(&opts, argv[1]);
105 + if (command == CHECKOUT_ONTO && argc == 4)
106 + return !!checkout_onto(&opts, argv[1], argv[2], argv[3]);
107 usage_with_options(builtin_rebase_helper_usage, options);
108 }
git-rebase--interactive.sh
+4 -21
@@ -28,17 +28,6 @@ case "$comment_char" in
28 ;;
29 esac
30
31 -orig_reflog_action="$GIT_REFLOG_ACTION"
32 -
33 -comment_for_reflog () {
34 - case "$orig_reflog_action" in
35 - ''|rebase*)
36 - GIT_REFLOG_ACTION="rebase -i ($1)"
37 - export GIT_REFLOG_ACTION
38 - ;;
39 - esac
40 -}
41 -
31 die_abort () {
32 apply_autostash
33 rm -rf "$state_dir"
@@ -70,14 +59,6 @@ collapse_todo_ids() {
59 git rebase--helper --shorten-ids
60 }
61
73 -# Switch to the branch in $into and notify it in the reflog
74 -checkout_onto () {
75 - comment_for_reflog start
76 - GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $onto_name"
77 - output git checkout $onto || die_abort "$(gettext "could not detach HEAD")"
78 - git update-ref ORIG_HEAD $orig_head
79 -}
80 -
62 get_missing_commit_check_level () {
63 check_level=$(git config --get rebase.missingCommitsCheck)
64 check_level=${check_level:-ignore}
@@ -176,7 +157,8 @@ EOF
157
158 git rebase--helper --check-todo-list || {
159 ret=$?
179 - checkout_onto
160 + git rebase--helper --checkout-onto "$onto_name" "$onto" \
161 + "$orig_head" ${verbose:+--verbose}
162 exit $ret
163 }
164
@@ -186,7 +168,8 @@ EOF
168 onto="$(git rebase--helper --skip-unnecessary-picks)" ||
169 die "Could not skip unnecessary pick commands"
170
189 - checkout_onto
171 + git rebase--helper --checkout-onto "$onto_name" "$onto" "$orig_head" \
172 + ${verbose:+--verbose}
173 require_clean_work_tree "rebase"
174 exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
175 --continue
sequencer.c
+19
@@ -3169,6 +3169,25 @@ int prepare_branch_to_be_rebased(struct replay_opts *opts, const char *commit)
3169 return 0;
3170 }
3171
3172 +int checkout_onto(struct replay_opts *opts,
3173 + const char *onto_name, const char *onto,
3174 + const char *orig_head)
3175 +{
3176 + struct object_id oid;
3177 + const char *action = reflog_message(opts, "start", "checkout %s", onto_name);
3178 +
3179 + if (get_oid(orig_head, &oid))
3180 + return error(_("%s: not a valid OID"), orig_head);
3181 +
3182 + if (run_git_checkout(opts, onto, action)) {
3183 + apply_autostash(opts);
3184 + sequencer_remove_state(opts);
3185 + return error(_("could not detach HEAD"));
3186 + }
3187 +
3188 + return update_ref(NULL, "ORIG_HEAD", &oid, NULL, 0, UPDATE_REFS_MSG_ON_ERR);
3189 +}
3190 +
3191 static const char rescheduled_advice[] =
3192 N_("Could not execute the todo command\n"
3193 "\n"
sequencer.h
+3
@@ -110,6 +110,9 @@ void commit_post_rewrite(const struct commit *current_head,
110 const struct object_id *new_head);
111
112 int prepare_branch_to_be_rebased(struct replay_opts *opts, const char *commit);
113 +int checkout_onto(struct replay_opts *opts,
114 + const char *onto_name, const char *onto,
115 + const char *orig_head);
116
117 #define SUMMARY_INITIAL_COMMIT (1 << 0)
118 #define SUMMARY_SHOW_AUTHOR_DATE (1 << 1)