sequencer: allow editing the commit message on a case-by-case basis

In the upcoming commits, we will implement more and more of rebase -i's functionality inside the sequencer. One particular feature of the commands to come is that some of them allow editing the commit message while others don't, i.e. we cannot define in the replay_opts whether the commit message should be edited or not. Let's add a new parameter to the run_git_commit() function. Previously, it was the duty of the caller to ensure that the opts->edit setting indicates whether to let the user edit the commit message or not, indicating that it is an "all or nothing" setting, i.e. that the sequencer wants to let the user edit *all* commit message, or none at all. In the upcoming rebase -i mode, it will depend on the particular command that is currently executed, though. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johannes Schindelin committed Oct 21, 2016 at 14:25 UTC a1c757623cb94b2a38569a3de77e69ae521091ed
1 file changed +40 -8
sequencer.c
+40 -8
@@ -15,6 +15,7 @@
15 #include "merge-recursive.h"
16 #include "refs.h"
17 #include "argv-array.h"
18 +#include "quote.h"
19
20 #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
21
@@ -33,6 +34,11 @@ static GIT_PATH_FUNC(git_path_head_file, "sequencer/head")
34 * being rebased.
35 */
36 static GIT_PATH_FUNC(rebase_path_author_script, "rebase-merge/author-script")
37 +/*
38 + * The following files are written by git-rebase just after parsing the
39 + * command-line (and are only consumed, not modified, by the sequencer).
40 + */
41 +static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
42
43 /* We will introduce the 'interactive rebase' mode later */
44 static inline int is_rebase_i(const struct replay_opts *opts)
@@ -132,6 +138,16 @@ static int has_conforming_footer(struct strbuf *sb, struct strbuf *sob,
138 return 1;
139 }
140
141 +static const char *gpg_sign_opt_quoted(struct replay_opts *opts)
142 +{
143 + static struct strbuf buf = STRBUF_INIT;
144 +
145 + strbuf_reset(&buf);
146 + if (opts->gpg_sign)
147 + sq_quotef(&buf, "-S%s", opts->gpg_sign);
148 + return buf.buf;
149 +}
150 +
151 int sequencer_remove_state(struct replay_opts *opts)
152 {
153 struct strbuf dir = STRBUF_INIT;
@@ -468,7 +484,7 @@ static char **read_author_script(void)
484 * author metadata.
485 */
486 static int run_git_commit(const char *defmsg, struct replay_opts *opts,
471 - int allow_empty)
487 + int allow_empty, int edit)
488 {
489 char **env = NULL;
490 struct argv_array array;
@@ -477,17 +493,20 @@ static int run_git_commit(const char *defmsg, struct replay_opts *opts,
493
494 if (is_rebase_i(opts)) {
495 env = read_author_script();
480 - if (!env)
496 + if (!env) {
497 + const char *gpg_opt = gpg_sign_opt_quoted(opts);
498 +
499 return error("You have staged changes in your working "
500 "tree. If these changes are meant to be\n"
501 "squashed into the previous commit, run:\n\n"
484 - " git commit --amend $gpg_sign_opt_quoted\n\n"
502 + " git commit --amend %s\n\n"
503 "If they are meant to go into a new commit, "
504 "run:\n\n"
487 - " git commit $gpg_sign_opt_quoted\n\n"
505 + " git commit %s\n\n"
506 "In both cases, once you're done, continue "
507 "with:\n\n"
490 - " git rebase --continue\n");
508 + " git rebase --continue\n", gpg_opt, gpg_opt);
509 + }
510 }
511
512 argv_array_init(&array);
@@ -500,7 +519,7 @@ static int run_git_commit(const char *defmsg, struct replay_opts *opts,
519 argv_array_push(&array, "-s");
520 if (defmsg)
521 argv_array_pushl(&array, "-F", defmsg, NULL);
503 - if (opts->edit)
522 + if (edit)
523 argv_array_push(&array, "-e");
524 else if (!opts->signoff && !opts->record_origin &&
525 git_config_get_value("commit.cleanup", &value))
@@ -767,7 +786,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
786 }
787 if (!opts->no_commit)
788 res = run_git_commit(opts->edit ? NULL : git_path_merge_msg(),
770 - opts, allow);
789 + opts, allow, opts->edit);
790
791 leave:
792 free_message(commit, &msg);
@@ -989,8 +1008,21 @@ static int populate_opts_cb(const char *key, const char *value, void *data)
1008
1009 static int read_populate_opts(struct replay_opts *opts)
1010 {
992 - if (is_rebase_i(opts))
1011 + if (is_rebase_i(opts)) {
1012 + struct strbuf buf = STRBUF_INIT;
1013 +
1014 + if (read_oneliner(&buf, rebase_path_gpg_sign_opt(), 1)) {
1015 + if (!starts_with(buf.buf, "-S"))
1016 + strbuf_reset(&buf);
1017 + else {
1018 + free(opts->gpg_sign);
1019 + opts->gpg_sign = xstrdup(buf.buf + 2);
1020 + }
1021 + }
1022 + strbuf_release(&buf);
1023 +
1024 return 0;
1025 + }
1026
1027 if (!file_exists(git_path_opts_file()))
1028 return 0;