blob: 9d1b3e7d4fa3ff44c1b06df9552f2139a433879c [file] [log] [blame]
Ramkumar Ramachandra26ae3372011-08-04 16:09:11 +05301#include "cache.h"
Brandon Williamsb2141fc2017-06-14 11:07:36 -07002#include "config.h"
Michael Haggerty697cc8e2014-10-01 12:28:42 +02003#include "lockfile.h"
Ramkumar Ramachandra26ae3372011-08-04 16:09:11 +05304#include "dir.h"
Stefan Bellercbd53a22018-05-15 16:42:15 -07005#include "object-store.h"
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05306#include "object.h"
7#include "commit.h"
Phillip Wood0505d602017-11-17 11:34:47 +00008#include "sequencer.h"
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05309#include "tag.h"
10#include "run-command.h"
Stefan Bellerd807c4a2018-04-10 14:26:18 -070011#include "exec-cmd.h"
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +053012#include "utf8.h"
13#include "cache-tree.h"
14#include "diff.h"
15#include "revision.h"
16#include "rerere.h"
17#include "merge-recursive.h"
18#include "refs.h"
Neil Hormanb27cfb02012-04-20 10:36:15 -040019#include "argv-array.h"
Johannes Schindelina1c75762016-10-21 14:25:12 +020020#include "quote.h"
Jonathan Tan967dfd42016-11-02 10:29:20 -070021#include "trailer.h"
Johannes Schindelin56dc3ab2017-01-02 16:26:43 +010022#include "log-tree.h"
Johannes Schindelin311af522017-01-02 16:26:47 +010023#include "wt-status.h"
Johannes Schindelinc44a4c62017-07-14 16:45:31 +020024#include "hashmap.h"
Phillip Wooda87a6f32017-11-17 11:34:48 +000025#include "notes-utils.h"
26#include "sigchain.h"
Johannes Schindelin9055e402018-04-25 14:28:47 +020027#include "unpack-trees.h"
28#include "worktree.h"
Johannes Schindelin1644c732018-04-25 14:29:03 +020029#include "oidmap.h"
30#include "oidset.h"
Nguyễn Thái Ngọc Duy8315bd22018-05-19 07:28:22 +020031#include "commit-slab.h"
Nguyễn Thái Ngọc Duy65b5f942018-05-20 20:40:06 +020032#include "alias.h"
Derrick Stolee64043552018-07-20 16:33:04 +000033#include "commit-reach.h"
Alban Gruinb97e1872018-08-28 14:10:36 +020034#include "rebase-interactive.h"
Denton Liu0816f1d2020-04-07 10:28:03 -040035#include "reset.h"
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +053036
37#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
Ramkumar Ramachandra26ae3372011-08-04 16:09:11 +053038
Ramsay Jones5fe81432019-02-11 17:16:58 +000039static const char sign_off_header[] = "Signed-off-by: ";
Brandon Caseycd650a42013-02-12 02:17:32 -080040static const char cherry_picked_prefix[] = "(cherry picked from commit ";
Miklos Vajna5ed75e22012-09-14 08:52:03 +020041
Phillip Wood66618a52018-01-24 12:34:22 +000042GIT_PATH_FUNC(git_path_commit_editmsg, "COMMIT_EDITMSG")
43
Phillip Wood901ba7b2019-12-06 16:06:11 +000044static GIT_PATH_FUNC(git_path_seq_dir, "sequencer")
Johannes Schindelin8a2a0f52016-10-14 15:17:12 +020045
46static GIT_PATH_FUNC(git_path_todo_file, "sequencer/todo")
47static GIT_PATH_FUNC(git_path_opts_file, "sequencer/opts")
48static GIT_PATH_FUNC(git_path_head_file, "sequencer/head")
Stephan Beyer1e412292016-12-07 22:51:32 +010049static GIT_PATH_FUNC(git_path_abort_safety_file, "sequencer/abort-safety")
Jeff Kingf9327292015-08-10 05:38:57 -040050
Johannes Schindelin84583952017-01-02 16:26:28 +010051static GIT_PATH_FUNC(rebase_path, "rebase-merge")
52/*
53 * The file containing rebase commands, comments, and empty lines.
54 * This file is created by "git rebase -i" then edited by the user. As
55 * the lines are processed, they are removed from the front of this
56 * file and written to the tail of 'done'.
57 */
Alban Gruin44b776c2018-08-10 18:51:28 +020058GIT_PATH_FUNC(rebase_path_todo, "rebase-merge/git-rebase-todo")
Alban Gruina930eb02019-03-05 20:18:03 +010059GIT_PATH_FUNC(rebase_path_todo_backup, "rebase-merge/git-rebase-todo.backup")
Alban Gruinb97e1872018-08-28 14:10:36 +020060
Alban Gruin5a5445d2020-01-28 22:12:46 +010061GIT_PATH_FUNC(rebase_path_dropped, "rebase-merge/dropped")
62
Johannes Schindelinb5a67042016-10-21 14:25:04 +020063/*
Johannes Schindelin1df6df02017-01-02 16:27:00 +010064 * The rebase command lines that have already been processed. A line
65 * is moved here when it is first handled, before any associated user
66 * actions.
67 */
68static GIT_PATH_FUNC(rebase_path_done, "rebase-merge/done")
69/*
Johannes Schindelinef800692017-01-02 16:36:20 +010070 * The file to keep track of how many commands were already processed (e.g.
71 * for the prompt).
72 */
Beat Bolli9ad36352018-07-09 21:25:35 +020073static GIT_PATH_FUNC(rebase_path_msgnum, "rebase-merge/msgnum")
Johannes Schindelinef800692017-01-02 16:36:20 +010074/*
75 * The file to keep track of how many commands are to be processed in total
76 * (e.g. for the prompt).
77 */
Beat Bolli9ad36352018-07-09 21:25:35 +020078static GIT_PATH_FUNC(rebase_path_msgtotal, "rebase-merge/end")
Johannes Schindelinef800692017-01-02 16:36:20 +010079/*
Johannes Schindelin6e98de72017-01-02 16:27:07 +010080 * The commit message that is planned to be used for any changes that
81 * need to be committed following a user interaction.
82 */
83static GIT_PATH_FUNC(rebase_path_message, "rebase-merge/message")
84/*
85 * The file into which is accumulated the suggested commit message for
86 * squash/fixup commands. When the first of a series of squash/fixups
87 * is seen, the file is created and the commit message from the
88 * previous commit and from the first squash/fixup commit are written
89 * to it. The commit message for each subsequent squash/fixup commit
90 * is appended to the file as it is processed.
Johannes Schindelin6e98de72017-01-02 16:27:07 +010091 */
92static GIT_PATH_FUNC(rebase_path_squash_msg, "rebase-merge/message-squash")
93/*
94 * If the current series of squash/fixups has not yet included a squash
95 * command, then this file exists and holds the commit message of the
96 * original "pick" commit. (If the series ends without a "squash"
97 * command, then this can be used as the commit message of the combined
98 * commit without opening the editor.)
99 */
100static GIT_PATH_FUNC(rebase_path_fixup_msg, "rebase-merge/message-fixup")
101/*
Johannes Schindeline12a7ef2018-04-27 22:48:21 +0200102 * This file contains the list fixup/squash commands that have been
103 * accumulated into message-fixup or message-squash so far.
104 */
105static GIT_PATH_FUNC(rebase_path_current_fixups, "rebase-merge/current-fixups")
106/*
Johannes Schindelinb5a67042016-10-21 14:25:04 +0200107 * A script to set the GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and
108 * GIT_AUTHOR_DATE that will be used for the commit that is currently
109 * being rebased.
110 */
111static GIT_PATH_FUNC(rebase_path_author_script, "rebase-merge/author-script")
Johannes Schindelina1c75762016-10-21 14:25:12 +0200112/*
Johannes Schindelin56dc3ab2017-01-02 16:26:43 +0100113 * When an "edit" rebase command is being processed, the SHA1 of the
114 * commit to be edited is recorded in this file. When "git rebase
115 * --continue" is executed, if there are any staged changes then they
116 * will be amended to the HEAD commit, but only provided the HEAD
117 * commit is still the commit to be edited. When any other rebase
118 * command is processed, this file is deleted.
119 */
120static GIT_PATH_FUNC(rebase_path_amend, "rebase-merge/amend")
121/*
122 * When we stop at a given patch via the "edit" command, this file contains
123 * the abbreviated commit name of the corresponding patch.
124 */
125static GIT_PATH_FUNC(rebase_path_stopped_sha, "rebase-merge/stopped-sha")
126/*
Johannes Schindelin25cb8df2017-01-02 16:28:16 +0100127 * For the post-rewrite hook, we make a list of rewritten commits and
128 * their new sha1s. The rewritten-pending list keeps the sha1s of
129 * commits that have been processed, but not committed yet,
130 * e.g. because they are waiting for a 'squash' command.
131 */
132static GIT_PATH_FUNC(rebase_path_rewritten_list, "rebase-merge/rewritten-list")
133static GIT_PATH_FUNC(rebase_path_rewritten_pending,
134 "rebase-merge/rewritten-pending")
Johannes Schindelin9055e402018-04-25 14:28:47 +0200135
136/*
Elijah Newren15beaaa2019-11-05 17:07:23 +0000137 * The path of the file containing the OID of the "squash onto" commit, i.e.
Johannes Schindelind87d48b2018-05-04 01:01:17 +0200138 * the dummy commit used for `reset [new root]`.
139 */
140static GIT_PATH_FUNC(rebase_path_squash_onto, "rebase-merge/squash-onto")
141
142/*
Johannes Schindelin9055e402018-04-25 14:28:47 +0200143 * The path of the file listing refs that need to be deleted after the rebase
144 * finishes. This is used by the `label` command to record the need for cleanup.
145 */
146static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
147
Johannes Schindelin25cb8df2017-01-02 16:28:16 +0100148/*
Johannes Schindelina1c75762016-10-21 14:25:12 +0200149 * The following files are written by git-rebase just after parsing the
Alban Gruin65850682018-08-28 14:10:40 +0200150 * command-line.
Johannes Schindelina1c75762016-10-21 14:25:12 +0200151 */
152static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
Johannes Schindelin556907f2017-01-02 16:26:53 +0100153static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
154static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
Elijah Newren899b49c2018-12-11 08:11:36 -0800155static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
Phillip Wooda852ec72018-03-20 11:10:55 +0000156static GIT_PATH_FUNC(rebase_path_signoff, "rebase-merge/signoff")
Johannes Schindelin4b83ce92017-01-02 16:27:53 +0100157static GIT_PATH_FUNC(rebase_path_head_name, "rebase-merge/head-name")
158static GIT_PATH_FUNC(rebase_path_onto, "rebase-merge/onto")
Johannes Schindelin796c7972017-01-02 16:28:27 +0100159static GIT_PATH_FUNC(rebase_path_autostash, "rebase-merge/autostash")
Johannes Schindelinca6c6b42017-01-02 16:28:30 +0100160static GIT_PATH_FUNC(rebase_path_strategy, "rebase-merge/strategy")
161static GIT_PATH_FUNC(rebase_path_strategy_opts, "rebase-merge/strategy_opts")
Phillip Wood9b6d7a62017-08-02 11:44:17 +0100162static GIT_PATH_FUNC(rebase_path_allow_rerere_autoupdate, "rebase-merge/allow_rerere_autoupdate")
Johannes Schindelind421afa2018-12-10 11:04:58 -0800163static GIT_PATH_FUNC(rebase_path_reschedule_failed_exec, "rebase-merge/reschedule-failed-exec")
Elijah Newrene98c4262020-02-15 21:36:25 +0000164static GIT_PATH_FUNC(rebase_path_drop_redundant_commits, "rebase-merge/drop_redundant_commits")
165static GIT_PATH_FUNC(rebase_path_keep_redundant_commits, "rebase-merge/keep_redundant_commits")
Johannes Schindelinb5a67042016-10-21 14:25:04 +0200166
Phillip Wood28d6dae2017-12-13 11:46:21 +0000167static int git_sequencer_config(const char *k, const char *v, void *cb)
168{
169 struct replay_opts *opts = cb;
170 int status;
171
172 if (!strcmp(k, "commit.cleanup")) {
173 const char *s;
174
175 status = git_config_string(&s, k, v);
176 if (status)
177 return status;
178
Phillip Woodd74f3e52019-03-29 11:08:42 +0000179 if (!strcmp(s, "verbatim")) {
Phillip Wood28d6dae2017-12-13 11:46:21 +0000180 opts->default_msg_cleanup = COMMIT_MSG_CLEANUP_NONE;
Phillip Woodd74f3e52019-03-29 11:08:42 +0000181 opts->explicit_cleanup = 1;
182 } else if (!strcmp(s, "whitespace")) {
Phillip Wood28d6dae2017-12-13 11:46:21 +0000183 opts->default_msg_cleanup = COMMIT_MSG_CLEANUP_SPACE;
Phillip Woodd74f3e52019-03-29 11:08:42 +0000184 opts->explicit_cleanup = 1;
185 } else if (!strcmp(s, "strip")) {
Phillip Wood28d6dae2017-12-13 11:46:21 +0000186 opts->default_msg_cleanup = COMMIT_MSG_CLEANUP_ALL;
Phillip Woodd74f3e52019-03-29 11:08:42 +0000187 opts->explicit_cleanup = 1;
188 } else if (!strcmp(s, "scissors")) {
Denton Liu1a2b9852019-04-17 11:23:30 +0100189 opts->default_msg_cleanup = COMMIT_MSG_CLEANUP_SCISSORS;
Phillip Woodd74f3e52019-03-29 11:08:42 +0000190 opts->explicit_cleanup = 1;
191 } else {
Phillip Wood28d6dae2017-12-13 11:46:21 +0000192 warning(_("invalid commit message cleanup mode '%s'"),
193 s);
Phillip Woodd74f3e52019-03-29 11:08:42 +0000194 }
Phillip Wood28d6dae2017-12-13 11:46:21 +0000195
Stefan Bellerf40f3c12018-06-01 13:01:46 -0700196 free((char *)s);
Phillip Wood28d6dae2017-12-13 11:46:21 +0000197 return status;
198 }
199
200 if (!strcmp(k, "commit.gpgsign")) {
Johannes Schindelined1e5282017-12-22 12:50:50 +0100201 opts->gpg_sign = git_config_bool(k, v) ? xstrdup("") : NULL;
Phillip Wood28d6dae2017-12-13 11:46:21 +0000202 return 0;
203 }
204
205 status = git_gpg_config(k, v, NULL);
206 if (status)
207 return status;
208
209 return git_diff_basic_config(k, v, NULL);
210}
211
212void sequencer_init_config(struct replay_opts *opts)
213{
214 opts->default_msg_cleanup = COMMIT_MSG_CLEANUP_NONE;
215 git_config(git_sequencer_config, opts);
216}
217
Johannes Schindelinb5a67042016-10-21 14:25:04 +0200218static inline int is_rebase_i(const struct replay_opts *opts)
219{
Johannes Schindelin84583952017-01-02 16:26:28 +0100220 return opts->action == REPLAY_INTERACTIVE_REBASE;
Johannes Schindelinb5a67042016-10-21 14:25:04 +0200221}
222
Johannes Schindelin285abf52016-10-14 15:17:20 +0200223static const char *get_dir(const struct replay_opts *opts)
224{
Johannes Schindelin84583952017-01-02 16:26:28 +0100225 if (is_rebase_i(opts))
226 return rebase_path();
Johannes Schindelin285abf52016-10-14 15:17:20 +0200227 return git_path_seq_dir();
228}
229
Johannes Schindelinc0246502016-10-21 14:24:32 +0200230static const char *get_todo_path(const struct replay_opts *opts)
231{
Johannes Schindelin84583952017-01-02 16:26:28 +0100232 if (is_rebase_i(opts))
233 return rebase_path_todo();
Johannes Schindelinc0246502016-10-21 14:24:32 +0200234 return git_path_todo_file();
235}
236
Brandon Caseybab4d102013-02-12 02:17:35 -0800237/*
238 * Returns 0 for non-conforming footer
239 * Returns 1 for conforming footer
240 * Returns 2 when sob exists within conforming footer
241 * Returns 3 when sob exists within conforming footer as last entry
242 */
243static int has_conforming_footer(struct strbuf *sb, struct strbuf *sob,
Jeff King66e83d92018-08-22 20:50:51 -0400244 size_t ignore_footer)
Brandon Caseyb971e042013-02-12 02:17:34 -0800245{
Jeff King00a21f52018-08-22 20:46:23 -0400246 struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT;
Jonathan Tan967dfd42016-11-02 10:29:20 -0700247 struct trailer_info info;
Jeff Kinga3b636e2018-08-22 20:45:44 -0400248 size_t i;
Jonathan Tan967dfd42016-11-02 10:29:20 -0700249 int found_sob = 0, found_sob_last = 0;
Brandon Caseyb971e042013-02-12 02:17:34 -0800250
Jeff Kingffce7f52018-08-22 20:50:37 -0400251 opts.no_divider = 1;
252
Jeff King00a21f52018-08-22 20:46:23 -0400253 trailer_info_get(&info, sb->buf, &opts);
Jonathan Tan967dfd42016-11-02 10:29:20 -0700254
255 if (info.trailer_start == info.trailer_end)
Brandon Caseyb971e042013-02-12 02:17:34 -0800256 return 0;
257
Jonathan Tan967dfd42016-11-02 10:29:20 -0700258 for (i = 0; i < info.trailer_nr; i++)
259 if (sob && !strncmp(info.trailers[i], sob->buf, sob->len)) {
260 found_sob = 1;
261 if (i == info.trailer_nr - 1)
262 found_sob_last = 1;
263 }
Brandon Caseyb971e042013-02-12 02:17:34 -0800264
Jonathan Tan967dfd42016-11-02 10:29:20 -0700265 trailer_info_release(&info);
Brandon Caseyb971e042013-02-12 02:17:34 -0800266
Jonathan Tan967dfd42016-11-02 10:29:20 -0700267 if (found_sob_last)
Brandon Caseybab4d102013-02-12 02:17:35 -0800268 return 3;
269 if (found_sob)
270 return 2;
Brandon Caseyb971e042013-02-12 02:17:34 -0800271 return 1;
272}
Ramkumar Ramachandra26ae3372011-08-04 16:09:11 +0530273
Johannes Schindelina1c75762016-10-21 14:25:12 +0200274static const char *gpg_sign_opt_quoted(struct replay_opts *opts)
275{
276 static struct strbuf buf = STRBUF_INIT;
277
278 strbuf_reset(&buf);
279 if (opts->gpg_sign)
280 sq_quotef(&buf, "-S%s", opts->gpg_sign);
281 return buf.buf;
282}
283
Johannes Schindelin28635842016-10-21 14:24:55 +0200284int sequencer_remove_state(struct replay_opts *opts)
Ramkumar Ramachandra26ae3372011-08-04 16:09:11 +0530285{
Johannes Schindelin9055e402018-04-25 14:28:47 +0200286 struct strbuf buf = STRBUF_INIT;
Phillip Wood37e9ee52019-05-14 19:03:48 +0100287 int i, ret = 0;
Johannes Schindelin03a4e262016-10-21 14:24:13 +0200288
Johannes Schindelin9055e402018-04-25 14:28:47 +0200289 if (is_rebase_i(opts) &&
290 strbuf_read_file(&buf, rebase_path_refs_to_delete(), 0) > 0) {
291 char *p = buf.buf;
292 while (*p) {
293 char *eol = strchr(p, '\n');
294 if (eol)
295 *eol = '\0';
Elijah Newrenc2417d32020-02-15 21:36:36 +0000296 if (delete_ref("(rebase) cleanup", p, NULL, 0) < 0) {
Johannes Schindelin9055e402018-04-25 14:28:47 +0200297 warning(_("could not delete '%s'"), p);
Phillip Wood37e9ee52019-05-14 19:03:48 +0100298 ret = -1;
299 }
Johannes Schindelin9055e402018-04-25 14:28:47 +0200300 if (!eol)
301 break;
302 p = eol + 1;
303 }
304 }
305
Johannes Schindelin03a4e262016-10-21 14:24:13 +0200306 free(opts->gpg_sign);
307 free(opts->strategy);
308 for (i = 0; i < opts->xopts_nr; i++)
309 free(opts->xopts[i]);
310 free(opts->xopts);
Johannes Schindeline12a7ef2018-04-27 22:48:21 +0200311 strbuf_release(&opts->current_fixups);
Ramkumar Ramachandra26ae3372011-08-04 16:09:11 +0530312
Johannes Schindelin9055e402018-04-25 14:28:47 +0200313 strbuf_reset(&buf);
314 strbuf_addstr(&buf, get_dir(opts));
Phillip Wood37e9ee52019-05-14 19:03:48 +0100315 if (remove_dir_recursively(&buf, 0))
316 ret = error(_("could not remove '%s'"), buf.buf);
Johannes Schindelin9055e402018-04-25 14:28:47 +0200317 strbuf_release(&buf);
Johannes Schindelin28635842016-10-21 14:24:55 +0200318
Phillip Wood37e9ee52019-05-14 19:03:48 +0100319 return ret;
Ramkumar Ramachandra26ae3372011-08-04 16:09:11 +0530320}
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530321
322static const char *action_name(const struct replay_opts *opts)
323{
Johannes Schindelin84583952017-01-02 16:26:28 +0100324 switch (opts->action) {
325 case REPLAY_REVERT:
326 return N_("revert");
327 case REPLAY_PICK:
328 return N_("cherry-pick");
329 case REPLAY_INTERACTIVE_REBASE:
Elijah Newrenc2417d32020-02-15 21:36:36 +0000330 return N_("rebase");
Johannes Schindelin84583952017-01-02 16:26:28 +0100331 }
Nguyễn Thái Ngọc Duy1a07e592018-07-21 09:49:19 +0200332 die(_("unknown action: %d"), opts->action);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530333}
334
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530335struct commit_message {
336 char *parent_label;
Jeff King7b35eaf2016-02-22 17:44:57 -0500337 char *label;
338 char *subject;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530339 const char *message;
340};
341
Johannes Schindelin39755962016-10-21 14:24:37 +0200342static const char *short_commit_name(struct commit *commit)
343{
brian m. carlsonaab95832018-03-12 02:27:30 +0000344 return find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV);
Johannes Schindelin39755962016-10-21 14:24:37 +0200345}
346
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530347static int get_message(struct commit *commit, struct commit_message *out)
348{
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530349 const char *abbrev, *subject;
Jeff King7b35eaf2016-02-22 17:44:57 -0500350 int subject_len;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530351
Jeff King7b35eaf2016-02-22 17:44:57 -0500352 out->message = logmsg_reencode(commit, NULL, get_commit_output_encoding());
Johannes Schindelin39755962016-10-21 14:24:37 +0200353 abbrev = short_commit_name(commit);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530354
355 subject_len = find_commit_subject(out->message, &subject);
356
Jeff King7b35eaf2016-02-22 17:44:57 -0500357 out->subject = xmemdupz(subject, subject_len);
358 out->label = xstrfmt("%s... %s", abbrev, out->subject);
359 out->parent_label = xstrfmt("parent of %s", out->label);
360
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530361 return 0;
362}
363
Jeff Kingd74a4e52014-06-10 17:39:35 -0400364static void free_message(struct commit *commit, struct commit_message *msg)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530365{
366 free(msg->parent_label);
Jeff King7b35eaf2016-02-22 17:44:57 -0500367 free(msg->label);
368 free(msg->subject);
Jeff Kingb66103c2014-06-10 17:41:39 -0400369 unuse_commit_buffer(commit, msg->message);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530370}
371
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +0100372static void print_advice(struct repository *r, int show_hint,
373 struct replay_opts *opts)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530374{
375 char *msg = getenv("GIT_CHERRY_PICK_HELP");
376
377 if (msg) {
378 fprintf(stderr, "%s\n", msg);
379 /*
Stefano Lattarini41ccfdd2013-04-12 00:36:10 +0200380 * A conflict has occurred but the porcelain
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530381 * (typically rebase --interactive) wants to take care
382 * of the commit itself so remove CHERRY_PICK_HEAD
383 */
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +0100384 unlink(git_path_cherry_pick_head(r));
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530385 return;
386 }
387
Phil Horded727b12012-02-21 19:44:17 -0500388 if (show_hint) {
389 if (opts->no_commit)
390 advise(_("after resolving the conflicts, mark the corrected paths\n"
391 "with 'git add <paths>' or 'git rm <paths>'"));
392 else
393 advise(_("after resolving the conflicts, mark the corrected paths\n"
394 "with 'git add <paths>' or 'git rm <paths>'\n"
395 "and commit the result with 'git commit'"));
396 }
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530397}
398
Alban Gruinddb81e52019-03-05 20:18:01 +0100399static int write_message(const void *buf, size_t len, const char *filename,
400 int append_eol)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530401{
Martin Ågren14bca6c2018-02-27 22:30:09 +0100402 struct lock_file msg_file = LOCK_INIT;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530403
Johannes Schindelin4ef3d8f2016-09-09 16:37:05 +0200404 int msg_fd = hold_lock_file_for_update(&msg_file, filename, 0);
405 if (msg_fd < 0)
Johannes Schindelin93b3df62016-10-21 14:26:25 +0200406 return error_errno(_("could not lock '%s'"), filename);
Johannes Schindelin75871492016-10-21 14:26:05 +0200407 if (write_in_full(msg_fd, buf, len) < 0) {
Johannes Schindelinbf5c0572018-04-25 14:28:17 +0200408 error_errno(_("could not write to '%s'"), filename);
Johannes Schindelin4f66c832016-10-21 14:26:00 +0200409 rollback_lock_file(&msg_file);
Johannes Schindelinbf5c0572018-04-25 14:28:17 +0200410 return -1;
Johannes Schindelin4f66c832016-10-21 14:26:00 +0200411 }
Johannes Schindelinf56fffe2016-10-21 14:26:09 +0200412 if (append_eol && write(msg_fd, "\n", 1) < 0) {
Johannes Schindelinbf5c0572018-04-25 14:28:17 +0200413 error_errno(_("could not write eol to '%s'"), filename);
Johannes Schindelinf56fffe2016-10-21 14:26:09 +0200414 rollback_lock_file(&msg_file);
Johannes Schindelinbf5c0572018-04-25 14:28:17 +0200415 return -1;
Johannes Schindelinf56fffe2016-10-21 14:26:09 +0200416 }
Martin Ågren350292a2018-02-28 20:07:58 +0100417 if (commit_lock_file(&msg_file) < 0)
418 return error(_("failed to finalize '%s'"), filename);
Johannes Schindelin4ef3d8f2016-09-09 16:37:05 +0200419
420 return 0;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530421}
422
Denton Liuc20de8b2020-04-07 10:27:54 -0400423int read_oneliner(struct strbuf *buf,
Denton Liu3442c3d2020-04-07 10:27:52 -0400424 const char *path, unsigned flags)
Johannes Schindelin1dfc84e2016-10-21 14:25:08 +0200425{
426 int orig_len = buf->len;
427
Johannes Schindelin1dfc84e2016-10-21 14:25:08 +0200428 if (strbuf_read_file(buf, path, 0) < 0) {
Denton Liubfa50c22020-04-07 10:27:53 -0400429 if ((flags & READ_ONELINER_WARN_MISSING) ||
430 (errno != ENOENT && errno != ENOTDIR))
Denton Liu5b2f6d92020-04-07 10:27:51 -0400431 warning_errno(_("could not read '%s'"), path);
Johannes Schindelin1dfc84e2016-10-21 14:25:08 +0200432 return 0;
433 }
434
435 if (buf->len > orig_len && buf->buf[buf->len - 1] == '\n') {
436 if (--buf->len > orig_len && buf->buf[buf->len - 1] == '\r')
437 --buf->len;
438 buf->buf[buf->len] = '\0';
439 }
440
Denton Liu3442c3d2020-04-07 10:27:52 -0400441 if ((flags & READ_ONELINER_SKIP_IF_EMPTY) && buf->len == orig_len)
Johannes Schindelin1dfc84e2016-10-21 14:25:08 +0200442 return 0;
443
444 return 1;
445}
446
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +0100447static struct tree *empty_tree(struct repository *r)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530448{
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +0100449 return lookup_tree(r, the_hash_algo->empty_tree);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530450}
451
Nguyễn Thái Ngọc Duye1ff0a32019-01-12 09:13:26 +0700452static int error_dirty_index(struct repository *repo, struct replay_opts *opts)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530453{
Nguyễn Thái Ngọc Duye1ff0a32019-01-12 09:13:26 +0700454 if (repo_read_index_unmerged(repo))
Johannes Schindelinc28cbc52016-10-21 14:26:17 +0200455 return error_resolve_conflict(_(action_name(opts)));
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530456
Johannes Schindelin93b3df62016-10-21 14:26:25 +0200457 error(_("your local changes would be overwritten by %s."),
Johannes Schindelinc28cbc52016-10-21 14:26:17 +0200458 _(action_name(opts)));
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530459
460 if (advice_commit_before_merge)
Johannes Schindelin93b3df62016-10-21 14:26:25 +0200461 advise(_("commit your changes or stash them to proceed."));
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530462 return -1;
463}
464
Stephan Beyer1e412292016-12-07 22:51:32 +0100465static void update_abort_safety_file(void)
466{
467 struct object_id head;
468
469 /* Do nothing on a single-pick */
470 if (!file_exists(git_path_seq_dir()))
471 return;
472
473 if (!get_oid("HEAD", &head))
474 write_file(git_path_abort_safety_file(), "%s", oid_to_hex(&head));
475 else
476 write_file(git_path_abort_safety_file(), "%s", "");
477}
478
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +0100479static int fast_forward_to(struct repository *r,
480 const struct object_id *to,
481 const struct object_id *from,
482 int unborn,
483 struct replay_opts *opts)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530484{
Ronnie Sahlbergd668d162014-04-16 15:37:45 -0700485 struct ref_transaction *transaction;
Ramkumar Ramachandraeb4be1c2013-06-19 13:07:09 +0530486 struct strbuf sb = STRBUF_INIT;
Ronnie Sahlbergd668d162014-04-16 15:37:45 -0700487 struct strbuf err = STRBUF_INIT;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530488
Nguyễn Thái Ngọc Duye1ff0a32019-01-12 09:13:26 +0700489 repo_read_index(r);
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +0100490 if (checkout_fast_forward(r, from, to, 1))
Johannes Schindelin0e408fc2016-09-09 16:37:55 +0200491 return -1; /* the callee should have complained already */
Ronnie Sahlberg651ab9f2014-04-16 11:56:52 -0700492
Johannes Schindelinc28cbc52016-10-21 14:26:17 +0200493 strbuf_addf(&sb, _("%s: fast-forward"), _(action_name(opts)));
Ronnie Sahlbergd668d162014-04-16 15:37:45 -0700494
495 transaction = ref_transaction_begin(&err);
496 if (!transaction ||
497 ref_transaction_update(transaction, "HEAD",
Johannes Schindelind87d48b2018-05-04 01:01:17 +0200498 to, unborn && !is_rebase_i(opts) ?
499 &null_oid : from,
Michael Haggerty1d147bd2015-02-17 18:00:15 +0100500 0, sb.buf, &err) ||
Ronnie Sahlbergdb7516a2014-04-30 12:22:42 -0700501 ref_transaction_commit(transaction, &err)) {
Ronnie Sahlbergd668d162014-04-16 15:37:45 -0700502 ref_transaction_free(transaction);
503 error("%s", err.buf);
504 strbuf_release(&sb);
505 strbuf_release(&err);
506 return -1;
507 }
Ronnie Sahlberg651ab9f2014-04-16 11:56:52 -0700508
Ramkumar Ramachandraeb4be1c2013-06-19 13:07:09 +0530509 strbuf_release(&sb);
Ronnie Sahlbergd668d162014-04-16 15:37:45 -0700510 strbuf_release(&err);
511 ref_transaction_free(transaction);
Stephan Beyer1e412292016-12-07 22:51:32 +0100512 update_abort_safety_file();
Ronnie Sahlbergd668d162014-04-16 15:37:45 -0700513 return 0;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530514}
515
Denton Liuf29cd862019-04-17 11:23:25 +0100516enum commit_msg_cleanup_mode get_cleanup_mode(const char *cleanup_arg,
517 int use_editor)
518{
519 if (!cleanup_arg || !strcmp(cleanup_arg, "default"))
520 return use_editor ? COMMIT_MSG_CLEANUP_ALL :
521 COMMIT_MSG_CLEANUP_SPACE;
522 else if (!strcmp(cleanup_arg, "verbatim"))
523 return COMMIT_MSG_CLEANUP_NONE;
524 else if (!strcmp(cleanup_arg, "whitespace"))
525 return COMMIT_MSG_CLEANUP_SPACE;
526 else if (!strcmp(cleanup_arg, "strip"))
527 return COMMIT_MSG_CLEANUP_ALL;
528 else if (!strcmp(cleanup_arg, "scissors"))
529 return use_editor ? COMMIT_MSG_CLEANUP_SCISSORS :
530 COMMIT_MSG_CLEANUP_SPACE;
531 else
532 die(_("Invalid cleanup mode %s"), cleanup_arg);
533}
534
Phillip Wooddc42e9a2019-04-17 11:23:29 +0100535/*
536 * NB using int rather than enum cleanup_mode to stop clang's
537 * -Wtautological-constant-out-of-range-compare complaining that the comparison
538 * is always true.
539 */
540static const char *describe_cleanup_mode(int cleanup_mode)
541{
542 static const char *modes[] = { "whitespace",
543 "verbatim",
544 "scissors",
545 "strip" };
546
547 if (cleanup_mode < ARRAY_SIZE(modes))
548 return modes[cleanup_mode];
549
550 BUG("invalid cleanup_mode provided (%d)", cleanup_mode);
551}
552
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +0100553void append_conflicts_hint(struct index_state *istate,
Denton Liu1a2b9852019-04-17 11:23:30 +0100554 struct strbuf *msgbuf, enum commit_msg_cleanup_mode cleanup_mode)
Junio C Hamano75c961b2014-10-24 11:34:59 -0700555{
556 int i;
557
Denton Liu1a2b9852019-04-17 11:23:30 +0100558 if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS) {
559 strbuf_addch(msgbuf, '\n');
560 wt_status_append_cut_line(msgbuf);
561 strbuf_addch(msgbuf, comment_line_char);
562 }
563
Junio C Hamano261f3152014-10-28 13:04:38 -0700564 strbuf_addch(msgbuf, '\n');
565 strbuf_commented_addf(msgbuf, "Conflicts:\n");
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +0100566 for (i = 0; i < istate->cache_nr;) {
567 const struct cache_entry *ce = istate->cache[i++];
Junio C Hamano75c961b2014-10-24 11:34:59 -0700568 if (ce_stage(ce)) {
Junio C Hamano261f3152014-10-28 13:04:38 -0700569 strbuf_commented_addf(msgbuf, "\t%s\n", ce->name);
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +0100570 while (i < istate->cache_nr &&
571 !strcmp(ce->name, istate->cache[i]->name))
Junio C Hamano75c961b2014-10-24 11:34:59 -0700572 i++;
573 }
574 }
575}
576
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +0100577static int do_recursive_merge(struct repository *r,
578 struct commit *base, struct commit *next,
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530579 const char *base_label, const char *next_label,
brian m. carlson48be4c62017-05-06 22:10:36 +0000580 struct object_id *head, struct strbuf *msgbuf,
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530581 struct replay_opts *opts)
582{
583 struct merge_options o;
Elijah Newrenb4db8a22019-08-17 11:41:30 -0700584 struct tree *next_tree, *base_tree, *head_tree;
Nguyễn Thái Ngọc Duy03b86642014-06-13 19:19:23 +0700585 int clean;
Jeff Kingd20bc012020-01-29 00:46:47 -0500586 int i;
Martin Ågren14bca6c2018-02-27 22:30:09 +0100587 struct lock_file index_lock = LOCK_INIT;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530588
Nguyễn Thái Ngọc Duy3a95f312019-01-12 09:13:24 +0700589 if (repo_hold_locked_index(r, &index_lock, LOCK_REPORT_ON_ERROR) < 0)
Phillip Woodbd588862017-11-15 10:41:25 +0000590 return -1;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530591
Nguyễn Thái Ngọc Duye1ff0a32019-01-12 09:13:26 +0700592 repo_read_index(r);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530593
Nguyễn Thái Ngọc Duy0d6caa22019-01-12 09:13:29 +0700594 init_merge_options(&o, r);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530595 o.ancestor = base ? base_label : "(empty tree)";
596 o.branch1 = "HEAD";
597 o.branch2 = next ? next_label : "(empty tree)";
Johannes Schindelin62fdb652017-01-02 16:35:39 +0100598 if (is_rebase_i(opts))
599 o.buffer_output = 2;
Elijah Newren9268cf42017-11-13 12:16:00 -0800600 o.show_rename_progress = 1;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530601
602 head_tree = parse_tree_indirect(head);
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +0100603 next_tree = next ? get_commit_tree(next) : empty_tree(r);
604 base_tree = base ? get_commit_tree(base) : empty_tree(r);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530605
Jeff Kingd20bc012020-01-29 00:46:47 -0500606 for (i = 0; i < opts->xopts_nr; i++)
607 parse_merge_opt(&o, opts->xopts[i]);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530608
609 clean = merge_trees(&o,
610 head_tree,
Elijah Newrenb4db8a22019-08-17 11:41:30 -0700611 next_tree, base_tree);
Johannes Schindelin62fdb652017-01-02 16:35:39 +0100612 if (is_rebase_i(opts) && clean <= 0)
613 fputs(o.obuf.buf, stdout);
Johannes Schindelin548009c2016-08-01 13:44:53 +0200614 strbuf_release(&o.obuf);
Martin Ågren64816522018-02-27 22:30:10 +0100615 if (clean < 0) {
616 rollback_lock_file(&index_lock);
Johannes Schindelinf241ff02016-07-26 18:06:02 +0200617 return clean;
Martin Ågren64816522018-02-27 22:30:10 +0100618 }
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530619
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +0100620 if (write_locked_index(r->index, &index_lock,
Martin Ågren61000812018-03-01 21:40:20 +0100621 COMMIT_LOCK | SKIP_IF_UNCHANGED))
Ævar Arnfjörð Bjarmason66f5f6d2017-05-11 21:20:12 +0000622 /*
623 * TRANSLATORS: %s will be "revert", "cherry-pick" or
Elijah Newrenc2417d32020-02-15 21:36:36 +0000624 * "rebase".
Johannes Schindelin84583952017-01-02 16:26:28 +0100625 */
Johannes Schindelinc527b552016-09-09 16:37:10 +0200626 return error(_("%s: Unable to write new index file"),
Johannes Schindelinc28cbc52016-10-21 14:26:17 +0200627 _(action_name(opts)));
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530628
Junio C Hamano75c961b2014-10-24 11:34:59 -0700629 if (!clean)
Denton Liu1a2b9852019-04-17 11:23:30 +0100630 append_conflicts_hint(r->index, msgbuf,
631 opts->default_msg_cleanup);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530632
633 return !clean;
634}
635
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +0100636static struct object_id *get_cache_tree_oid(struct index_state *istate)
Johannes Schindelinba97aea2018-05-04 01:01:15 +0200637{
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +0100638 if (!istate->cache_tree)
639 istate->cache_tree = cache_tree();
Johannes Schindelinba97aea2018-05-04 01:01:15 +0200640
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +0100641 if (!cache_tree_fully_valid(istate->cache_tree))
642 if (cache_tree_update(istate, 0)) {
Johannes Schindelinba97aea2018-05-04 01:01:15 +0200643 error(_("unable to update cache tree"));
644 return NULL;
645 }
646
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +0100647 return &istate->cache_tree->oid;
Johannes Schindelinba97aea2018-05-04 01:01:15 +0200648}
649
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +0100650static int is_index_unchanged(struct repository *r)
Neil Hormanb27cfb02012-04-20 10:36:15 -0400651{
Johannes Schindelinba97aea2018-05-04 01:01:15 +0200652 struct object_id head_oid, *cache_tree_oid;
Neil Hormanb27cfb02012-04-20 10:36:15 -0400653 struct commit *head_commit;
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +0100654 struct index_state *istate = r->index;
Neil Hormanb27cfb02012-04-20 10:36:15 -0400655
brian m. carlson49e61472017-10-15 22:07:09 +0000656 if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, &head_oid, NULL))
Johannes Schindelinaee42e12017-12-23 00:55:43 +0100657 return error(_("could not resolve HEAD commit"));
Neil Hormanb27cfb02012-04-20 10:36:15 -0400658
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +0100659 head_commit = lookup_commit(r, &head_oid);
Neil Horman4b580062012-05-03 08:10:22 -0400660
661 /*
662 * If head_commit is NULL, check_commit, called from
663 * lookup_commit, would have indicated that head_commit is not
664 * a commit object already. parse_commit() will return failure
665 * without further complaints in such a case. Otherwise, if
666 * the commit is invalid, parse_commit() will complain. So
667 * there is nothing for us to say here. Just return failure.
668 */
669 if (parse_commit(head_commit))
670 return -1;
Neil Hormanb27cfb02012-04-20 10:36:15 -0400671
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +0100672 if (!(cache_tree_oid = get_cache_tree_oid(istate)))
Johannes Schindelinba97aea2018-05-04 01:01:15 +0200673 return -1;
Neil Hormanb27cfb02012-04-20 10:36:15 -0400674
Jeff King4a7e27e2018-08-28 17:22:40 -0400675 return oideq(cache_tree_oid, get_commit_tree_oid(head_commit));
Neil Hormanb27cfb02012-04-20 10:36:15 -0400676}
677
Johannes Schindelin0473f282017-01-02 16:27:18 +0100678static int write_author_script(const char *message)
679{
680 struct strbuf buf = STRBUF_INIT;
681 const char *eol;
682 int res;
683
684 for (;;)
685 if (!*message || starts_with(message, "\n")) {
686missing_author:
687 /* Missing 'author' line? */
688 unlink(rebase_path_author_script());
689 return 0;
690 } else if (skip_prefix(message, "author ", &message))
691 break;
692 else if ((eol = strchr(message, '\n')))
693 message = eol + 1;
694 else
695 goto missing_author;
696
697 strbuf_addstr(&buf, "GIT_AUTHOR_NAME='");
698 while (*message && *message != '\n' && *message != '\r')
699 if (skip_prefix(message, " <", &message))
700 break;
701 else if (*message != '\'')
702 strbuf_addch(&buf, *(message++));
703 else
Phillip Wood4aa5ff92018-08-07 10:34:52 +0100704 strbuf_addf(&buf, "'\\%c'", *(message++));
Johannes Schindelin0473f282017-01-02 16:27:18 +0100705 strbuf_addstr(&buf, "'\nGIT_AUTHOR_EMAIL='");
706 while (*message && *message != '\n' && *message != '\r')
707 if (skip_prefix(message, "> ", &message))
708 break;
709 else if (*message != '\'')
710 strbuf_addch(&buf, *(message++));
711 else
Phillip Wood4aa5ff92018-08-07 10:34:52 +0100712 strbuf_addf(&buf, "'\\%c'", *(message++));
Johannes Schindelin0473f282017-01-02 16:27:18 +0100713 strbuf_addstr(&buf, "'\nGIT_AUTHOR_DATE='@");
714 while (*message && *message != '\n' && *message != '\r')
715 if (*message != '\'')
716 strbuf_addch(&buf, *(message++));
717 else
Phillip Wood4aa5ff92018-08-07 10:34:52 +0100718 strbuf_addf(&buf, "'\\%c'", *(message++));
Eric Sunshine0f16c092018-07-31 03:33:29 -0400719 strbuf_addch(&buf, '\'');
Johannes Schindelin0473f282017-01-02 16:27:18 +0100720 res = write_message(buf.buf, buf.len, rebase_path_author_script(), 1);
721 strbuf_release(&buf);
722 return res;
723}
724
Phillip Woodbcd33ec2018-10-31 10:15:55 +0000725/**
726 * Take a series of KEY='VALUE' lines where VALUE part is
727 * sq-quoted, and append <KEY, VALUE> at the end of the string list
Phillip Wood4aa5ff92018-08-07 10:34:52 +0100728 */
Phillip Woodbcd33ec2018-10-31 10:15:55 +0000729static int parse_key_value_squoted(char *buf, struct string_list *list)
Phillip Wood4aa5ff92018-08-07 10:34:52 +0100730{
Phillip Woodbcd33ec2018-10-31 10:15:55 +0000731 while (*buf) {
732 struct string_list_item *item;
733 char *np;
734 char *cp = strchr(buf, '=');
735 if (!cp) {
736 np = strchrnul(buf, '\n');
737 return error(_("no key present in '%.*s'"),
738 (int) (np - buf), buf);
739 }
740 np = strchrnul(cp, '\n');
741 *cp++ = '\0';
742 item = string_list_append(list, buf);
Phillip Wood4aa5ff92018-08-07 10:34:52 +0100743
Phillip Woodbcd33ec2018-10-31 10:15:55 +0000744 buf = np + (*np == '\n');
745 *np = '\0';
746 cp = sq_dequote(cp);
747 if (!cp)
748 return error(_("unable to dequote value of '%s'"),
749 item->string);
750 item->util = xstrdup(cp);
751 }
Phillip Wood4aa5ff92018-08-07 10:34:52 +0100752 return 0;
753}
754
Phillip Woodbcd33ec2018-10-31 10:15:55 +0000755/**
756 * Reads and parses the state directory's "author-script" file, and sets name,
757 * email and date accordingly.
758 * Returns 0 on success, -1 if the file could not be parsed.
759 *
760 * The author script is of the format:
761 *
762 * GIT_AUTHOR_NAME='$author_name'
763 * GIT_AUTHOR_EMAIL='$author_email'
764 * GIT_AUTHOR_DATE='$author_date'
765 *
766 * where $author_name, $author_email and $author_date are quoted. We are strict
Johannes Schindelinc3c003e2019-05-14 04:22:33 -0700767 * with our parsing, as the file was meant to be eval'd in the now-removed
Phillip Woodbcd33ec2018-10-31 10:15:55 +0000768 * git-am.sh/git-rebase--interactive.sh scripts, and thus if the file differs
769 * from what this function expects, it is better to bail out than to do
770 * something that the user does not expect.
771 */
772int read_author_script(const char *path, char **name, char **email, char **date,
773 int allow_missing)
774{
775 struct strbuf buf = STRBUF_INIT;
776 struct string_list kv = STRING_LIST_INIT_DUP;
777 int retval = -1; /* assume failure */
778 int i, name_i = -2, email_i = -2, date_i = -2, err = 0;
779
780 if (strbuf_read_file(&buf, path, 256) <= 0) {
781 strbuf_release(&buf);
782 if (errno == ENOENT && allow_missing)
783 return 0;
784 else
785 return error_errno(_("could not open '%s' for reading"),
786 path);
787 }
788
789 if (parse_key_value_squoted(buf.buf, &kv))
790 goto finish;
791
792 for (i = 0; i < kv.nr; i++) {
793 if (!strcmp(kv.items[i].string, "GIT_AUTHOR_NAME")) {
794 if (name_i != -2)
795 name_i = error(_("'GIT_AUTHOR_NAME' already given"));
796 else
797 name_i = i;
798 } else if (!strcmp(kv.items[i].string, "GIT_AUTHOR_EMAIL")) {
799 if (email_i != -2)
800 email_i = error(_("'GIT_AUTHOR_EMAIL' already given"));
801 else
802 email_i = i;
803 } else if (!strcmp(kv.items[i].string, "GIT_AUTHOR_DATE")) {
804 if (date_i != -2)
805 date_i = error(_("'GIT_AUTHOR_DATE' already given"));
806 else
807 date_i = i;
808 } else {
809 err = error(_("unknown variable '%s'"),
810 kv.items[i].string);
811 }
812 }
813 if (name_i == -2)
814 error(_("missing 'GIT_AUTHOR_NAME'"));
815 if (email_i == -2)
816 error(_("missing 'GIT_AUTHOR_EMAIL'"));
817 if (date_i == -2)
818 error(_("missing 'GIT_AUTHOR_DATE'"));
819 if (date_i < 0 || email_i < 0 || date_i < 0 || err)
820 goto finish;
Junio C Hamano4d924522020-01-12 12:27:41 -0800821 *name = kv.items[name_i].util;
822 *email = kv.items[email_i].util;
823 *date = kv.items[date_i].util;
Phillip Woodbcd33ec2018-10-31 10:15:55 +0000824 retval = 0;
825finish:
826 string_list_clear(&kv, !!retval);
827 strbuf_release(&buf);
828 return retval;
829}
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530830
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530831/*
Phillip Wood4d010a72018-10-31 10:15:56 +0000832 * Read a GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL AND GIT_AUTHOR_DATE from a
833 * file with shell quoting into struct argv_array. Returns -1 on
834 * error, 0 otherwise.
Johannes Schindelinb5a67042016-10-21 14:25:04 +0200835 */
Johannes Schindelina2a20b02017-01-02 16:35:25 +0100836static int read_env_script(struct argv_array *env)
Johannes Schindelinb5a67042016-10-21 14:25:04 +0200837{
Phillip Wood4d010a72018-10-31 10:15:56 +0000838 char *name, *email, *date;
Johannes Schindelinb5a67042016-10-21 14:25:04 +0200839
Phillip Wood4d010a72018-10-31 10:15:56 +0000840 if (read_author_script(rebase_path_author_script(),
841 &name, &email, &date, 0))
Johannes Schindelina2a20b02017-01-02 16:35:25 +0100842 return -1;
Johannes Schindelinb5a67042016-10-21 14:25:04 +0200843
Phillip Wood4d010a72018-10-31 10:15:56 +0000844 argv_array_pushf(env, "GIT_AUTHOR_NAME=%s", name);
845 argv_array_pushf(env, "GIT_AUTHOR_EMAIL=%s", email);
846 argv_array_pushf(env, "GIT_AUTHOR_DATE=%s", date);
847 free(name);
848 free(email);
849 free(date);
Johannes Schindelinb5a67042016-10-21 14:25:04 +0200850
Johannes Schindelina2a20b02017-01-02 16:35:25 +0100851 return 0;
Johannes Schindelinb5a67042016-10-21 14:25:04 +0200852}
853
Phillip Wood356ee462017-11-24 11:07:57 +0000854static char *get_author(const char *message)
855{
856 size_t len;
857 const char *a;
858
859 a = find_commit_header(message, "author", &len);
860 if (a)
861 return xmemdupz(a, len);
862
863 return NULL;
864}
865
Johannes Schindelin791eb872016-10-21 14:26:32 +0200866static const char staged_changes_advice[] =
867N_("you have staged changes in your working tree\n"
868"If these changes are meant to be squashed into the previous commit, run:\n"
869"\n"
870" git commit --amend %s\n"
871"\n"
872"If they are meant to go into a new commit, run:\n"
873"\n"
874" git commit %s\n"
875"\n"
876"In both cases, once you're done, continue with:\n"
877"\n"
878" git rebase --continue\n");
879
Johannes Schindelin789b3ef2017-03-23 17:07:11 +0100880#define ALLOW_EMPTY (1<<0)
881#define EDIT_MSG (1<<1)
882#define AMEND_MSG (1<<2)
883#define CLEANUP_MSG (1<<3)
Johannes Schindelinb92ff6e2017-03-23 17:07:17 +0100884#define VERIFY_MSG (1<<4)
Johannes Schindelind87d48b2018-05-04 01:01:17 +0200885#define CREATE_ROOT_COMMIT (1<<5)
Johannes Schindelin789b3ef2017-03-23 17:07:11 +0100886
Alban Gruin34bec2c2018-08-10 18:51:32 +0200887static int run_command_silent_on_success(struct child_process *cmd)
888{
889 struct strbuf buf = STRBUF_INIT;
890 int rc;
891
892 cmd->stdout_to_stderr = 1;
893 rc = pipe_command(cmd,
894 NULL, 0,
895 NULL, 0,
896 &buf, 0);
897
898 if (rc)
899 fputs(buf.buf, stderr);
900 strbuf_release(&buf);
901 return rc;
902}
903
Johannes Schindelinb5a67042016-10-21 14:25:04 +0200904/*
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530905 * If we are cherry-pick, and if the merge did not result in
906 * hand-editing, we will hit this commit and inherit the original
907 * author date and name.
Johannes Schindelinb5a67042016-10-21 14:25:04 +0200908 *
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530909 * If we are revert, or if our cherry-pick results in a hand merge,
910 * we had better say that the current user is responsible for that.
Johannes Schindelinb5a67042016-10-21 14:25:04 +0200911 *
912 * An exception is when run_git_commit() is called during an
913 * interactive rebase: in that case, we will want to retain the
914 * author metadata.
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530915 */
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +0100916static int run_git_commit(struct repository *r,
917 const char *defmsg,
918 struct replay_opts *opts,
Johannes Schindelin789b3ef2017-03-23 17:07:11 +0100919 unsigned int flags)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530920{
Johannes Schindelin07d968e2017-01-02 16:35:29 +0100921 struct child_process cmd = CHILD_PROCESS_INIT;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530922
Johannes Schindelin07d968e2017-01-02 16:35:29 +0100923 cmd.git_cmd = 1;
924
Alban Gruin34bec2c2018-08-10 18:51:32 +0200925 if (is_rebase_i(opts) && read_env_script(&cmd.env_array)) {
926 const char *gpg_opt = gpg_sign_opt_quoted(opts);
Johannes Schindelin9a757c42017-01-02 16:35:34 +0100927
Alban Gruin34bec2c2018-08-10 18:51:32 +0200928 return error(_(staged_changes_advice),
929 gpg_opt, gpg_opt);
Johannes Schindelinb5a67042016-10-21 14:25:04 +0200930 }
931
Johannes Schindelin07d968e2017-01-02 16:35:29 +0100932 argv_array_push(&cmd.args, "commit");
Neil Hormanb27cfb02012-04-20 10:36:15 -0400933
Johannes Schindelinb92ff6e2017-03-23 17:07:17 +0100934 if (!(flags & VERIFY_MSG))
935 argv_array_push(&cmd.args, "-n");
Johannes Schindelin789b3ef2017-03-23 17:07:11 +0100936 if ((flags & AMEND_MSG))
Johannes Schindelin07d968e2017-01-02 16:35:29 +0100937 argv_array_push(&cmd.args, "--amend");
Jeff King3bdd5522014-06-19 17:28:20 -0400938 if (opts->gpg_sign)
Johannes Schindelin07d968e2017-01-02 16:35:29 +0100939 argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
Đoàn Trần Công Danhcf0ad4d2020-04-03 17:28:03 +0700940 else
941 argv_array_push(&cmd.args, "--no-gpg-sign");
Johannes Schindelinb5a67042016-10-21 14:25:04 +0200942 if (defmsg)
Johannes Schindelin07d968e2017-01-02 16:35:29 +0100943 argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
Johannes Schindelindc4b5bc2018-04-27 22:48:28 +0200944 else if (!(flags & EDIT_MSG))
945 argv_array_pushl(&cmd.args, "-C", "HEAD", NULL);
Johannes Schindelin789b3ef2017-03-23 17:07:11 +0100946 if ((flags & CLEANUP_MSG))
Johannes Schindelin07d968e2017-01-02 16:35:29 +0100947 argv_array_push(&cmd.args, "--cleanup=strip");
Johannes Schindelin789b3ef2017-03-23 17:07:11 +0100948 if ((flags & EDIT_MSG))
Johannes Schindelin07d968e2017-01-02 16:35:29 +0100949 argv_array_push(&cmd.args, "-e");
Johannes Schindelin789b3ef2017-03-23 17:07:11 +0100950 else if (!(flags & CLEANUP_MSG) &&
Johannes Schindelin00094262016-10-21 14:25:28 +0200951 !opts->signoff && !opts->record_origin &&
Denton Liu1a2b9852019-04-17 11:23:30 +0100952 !opts->explicit_cleanup)
Johannes Schindelin07d968e2017-01-02 16:35:29 +0100953 argv_array_push(&cmd.args, "--cleanup=verbatim");
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530954
Johannes Schindelin789b3ef2017-03-23 17:07:11 +0100955 if ((flags & ALLOW_EMPTY))
Johannes Schindelin07d968e2017-01-02 16:35:29 +0100956 argv_array_push(&cmd.args, "--allow-empty");
Neil Hormandf478b72012-04-11 16:21:53 -0400957
Elijah Newrena3ec9ea2018-09-12 14:18:48 -0700958 if (!(flags & EDIT_MSG))
Johannes Schindelin07d968e2017-01-02 16:35:29 +0100959 argv_array_push(&cmd.args, "--allow-empty-message");
Chris Webb4bee9582012-08-02 11:38:51 +0100960
Alban Gruin34bec2c2018-08-10 18:51:32 +0200961 if (is_rebase_i(opts) && !(flags & EDIT_MSG))
962 return run_command_silent_on_success(&cmd);
963 else
964 return run_command(&cmd);
Neil Hormanb27cfb02012-04-20 10:36:15 -0400965}
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +0530966
Phillip Woodd0aaa462017-11-10 11:09:42 +0000967static int rest_is_empty(const struct strbuf *sb, int start)
968{
969 int i, eol;
970 const char *nl;
971
972 /* Check if the rest is just whitespace and Signed-off-by's. */
973 for (i = start; i < sb->len; i++) {
974 nl = memchr(sb->buf + i, '\n', sb->len - i);
975 if (nl)
976 eol = nl - sb->buf;
977 else
978 eol = sb->len;
979
980 if (strlen(sign_off_header) <= eol - i &&
981 starts_with(sb->buf + i, sign_off_header)) {
982 i = eol;
983 continue;
984 }
985 while (i < eol)
986 if (!isspace(sb->buf[i++]))
987 return 0;
988 }
989
990 return 1;
991}
992
Denton Liuf29cd862019-04-17 11:23:25 +0100993void cleanup_message(struct strbuf *msgbuf,
994 enum commit_msg_cleanup_mode cleanup_mode, int verbose)
995{
996 if (verbose || /* Truncate the message just before the diff, if any. */
997 cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS)
998 strbuf_setlen(msgbuf, wt_status_locate_end(msgbuf->buf, msgbuf->len));
999 if (cleanup_mode != COMMIT_MSG_CLEANUP_NONE)
1000 strbuf_stripspace(msgbuf, cleanup_mode == COMMIT_MSG_CLEANUP_ALL);
1001}
1002
Phillip Woodd0aaa462017-11-10 11:09:42 +00001003/*
1004 * Find out if the message in the strbuf contains only whitespace and
1005 * Signed-off-by lines.
1006 */
1007int message_is_empty(const struct strbuf *sb,
1008 enum commit_msg_cleanup_mode cleanup_mode)
1009{
1010 if (cleanup_mode == COMMIT_MSG_CLEANUP_NONE && sb->len)
1011 return 0;
1012 return rest_is_empty(sb, 0);
1013}
1014
1015/*
1016 * See if the user edited the message in the editor or left what
1017 * was in the template intact
1018 */
1019int template_untouched(const struct strbuf *sb, const char *template_file,
1020 enum commit_msg_cleanup_mode cleanup_mode)
1021{
1022 struct strbuf tmpl = STRBUF_INIT;
1023 const char *start;
1024
1025 if (cleanup_mode == COMMIT_MSG_CLEANUP_NONE && sb->len)
1026 return 0;
1027
1028 if (!template_file || strbuf_read_file(&tmpl, template_file, 0) <= 0)
1029 return 0;
1030
1031 strbuf_stripspace(&tmpl, cleanup_mode == COMMIT_MSG_CLEANUP_ALL);
1032 if (!skip_prefix(sb->buf, tmpl.buf, &start))
1033 start = sb->buf;
1034 strbuf_release(&tmpl);
1035 return rest_is_empty(sb, start - sb->buf);
1036}
1037
Phillip Wood0505d602017-11-17 11:34:47 +00001038int update_head_with_reflog(const struct commit *old_head,
1039 const struct object_id *new_head,
1040 const char *action, const struct strbuf *msg,
1041 struct strbuf *err)
1042{
1043 struct ref_transaction *transaction;
1044 struct strbuf sb = STRBUF_INIT;
1045 const char *nl;
1046 int ret = 0;
1047
1048 if (action) {
1049 strbuf_addstr(&sb, action);
1050 strbuf_addstr(&sb, ": ");
1051 }
1052
1053 nl = strchr(msg->buf, '\n');
1054 if (nl) {
1055 strbuf_add(&sb, msg->buf, nl + 1 - msg->buf);
1056 } else {
1057 strbuf_addbuf(&sb, msg);
1058 strbuf_addch(&sb, '\n');
1059 }
1060
1061 transaction = ref_transaction_begin(err);
1062 if (!transaction ||
1063 ref_transaction_update(transaction, "HEAD", new_head,
1064 old_head ? &old_head->object.oid : &null_oid,
1065 0, sb.buf, err) ||
1066 ref_transaction_commit(transaction, err)) {
1067 ret = -1;
1068 }
1069 ref_transaction_free(transaction);
1070 strbuf_release(&sb);
1071
1072 return ret;
1073}
1074
Phillip Wooda87a6f32017-11-17 11:34:48 +00001075static int run_rewrite_hook(const struct object_id *oldoid,
1076 const struct object_id *newoid)
1077{
1078 struct child_process proc = CHILD_PROCESS_INIT;
1079 const char *argv[3];
1080 int code;
1081 struct strbuf sb = STRBUF_INIT;
1082
1083 argv[0] = find_hook("post-rewrite");
1084 if (!argv[0])
1085 return 0;
1086
1087 argv[1] = "amend";
1088 argv[2] = NULL;
1089
1090 proc.argv = argv;
1091 proc.in = -1;
1092 proc.stdout_to_stderr = 1;
Jeff Hostetler62062862019-02-22 14:25:06 -08001093 proc.trace2_hook_name = "post-rewrite";
Phillip Wooda87a6f32017-11-17 11:34:48 +00001094
1095 code = start_command(&proc);
1096 if (code)
1097 return code;
1098 strbuf_addf(&sb, "%s %s\n", oid_to_hex(oldoid), oid_to_hex(newoid));
1099 sigchain_push(SIGPIPE, SIG_IGN);
1100 write_in_full(proc.in, sb.buf, sb.len);
1101 close(proc.in);
1102 strbuf_release(&sb);
1103 sigchain_pop(SIGPIPE);
1104 return finish_command(&proc);
1105}
1106
Nguyễn Thái Ngọc Duy1d18d752019-01-12 09:13:23 +07001107void commit_post_rewrite(struct repository *r,
1108 const struct commit *old_head,
Phillip Wooda87a6f32017-11-17 11:34:48 +00001109 const struct object_id *new_head)
1110{
1111 struct notes_rewrite_cfg *cfg;
1112
1113 cfg = init_copy_notes_for_rewrite("amend");
1114 if (cfg) {
1115 /* we are amending, so old_head is not NULL */
1116 copy_note_for_rewrite(cfg, &old_head->object.oid, new_head);
Nguyễn Thái Ngọc Duy1d18d752019-01-12 09:13:23 +07001117 finish_copy_notes_for_rewrite(r, cfg, "Notes added by 'git commit --amend'");
Phillip Wooda87a6f32017-11-17 11:34:48 +00001118 }
1119 run_rewrite_hook(&old_head->object.oid, new_head);
1120}
1121
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001122static int run_prepare_commit_msg_hook(struct repository *r,
1123 struct strbuf *msg,
1124 const char *commit)
Phillip Wood66618a52018-01-24 12:34:22 +00001125{
Phillip Wood49697cb2019-10-15 10:25:31 +00001126 int ret = 0;
1127 const char *name, *arg1 = NULL, *arg2 = NULL;
Phillip Wood66618a52018-01-24 12:34:22 +00001128
1129 name = git_path_commit_editmsg();
1130 if (write_message(msg->buf, msg->len, name, 0))
1131 return -1;
1132
Phillip Wood49697cb2019-10-15 10:25:31 +00001133 if (commit) {
1134 arg1 = "commit";
1135 arg2 = commit;
1136 } else {
1137 arg1 = "message";
1138 }
1139 if (run_commit_hook(0, r->index_file, "prepare-commit-msg", name,
1140 arg1, arg2, NULL))
Phillip Wood66618a52018-01-24 12:34:22 +00001141 ret = error(_("'prepare-commit-msg' hook failed"));
Phillip Wood66618a52018-01-24 12:34:22 +00001142
1143 return ret;
1144}
1145
Phillip Woode47c6ca2017-11-24 11:07:54 +00001146static const char implicit_ident_advice_noconfig[] =
1147N_("Your name and email address were configured automatically based\n"
1148"on your username and hostname. Please check that they are accurate.\n"
1149"You can suppress this message by setting them explicitly. Run the\n"
1150"following command and follow the instructions in your editor to edit\n"
1151"your configuration file:\n"
1152"\n"
1153" git config --global --edit\n"
1154"\n"
1155"After doing this, you may fix the identity used for this commit with:\n"
1156"\n"
1157" git commit --amend --reset-author\n");
1158
1159static const char implicit_ident_advice_config[] =
1160N_("Your name and email address were configured automatically based\n"
1161"on your username and hostname. Please check that they are accurate.\n"
1162"You can suppress this message by setting them explicitly:\n"
1163"\n"
1164" git config --global user.name \"Your Name\"\n"
1165" git config --global user.email you@example.com\n"
1166"\n"
1167"After doing this, you may fix the identity used for this commit with:\n"
1168"\n"
1169" git commit --amend --reset-author\n");
1170
1171static const char *implicit_ident_advice(void)
1172{
1173 char *user_config = expand_user_path("~/.gitconfig", 0);
1174 char *xdg_config = xdg_config_home("config");
1175 int config_exists = file_exists(user_config) || file_exists(xdg_config);
1176
1177 free(user_config);
1178 free(xdg_config);
1179
1180 if (config_exists)
1181 return _(implicit_ident_advice_config);
1182 else
1183 return _(implicit_ident_advice_noconfig);
1184
1185}
1186
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001187void print_commit_summary(struct repository *r,
1188 const char *prefix,
1189 const struct object_id *oid,
Phillip Woode47c6ca2017-11-24 11:07:54 +00001190 unsigned int flags)
1191{
1192 struct rev_info rev;
1193 struct commit *commit;
1194 struct strbuf format = STRBUF_INIT;
1195 const char *head;
1196 struct pretty_print_context pctx = {0};
1197 struct strbuf author_ident = STRBUF_INIT;
1198 struct strbuf committer_ident = STRBUF_INIT;
1199
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001200 commit = lookup_commit(r, oid);
Phillip Woode47c6ca2017-11-24 11:07:54 +00001201 if (!commit)
1202 die(_("couldn't look up newly created commit"));
1203 if (parse_commit(commit))
1204 die(_("could not parse newly created commit"));
1205
1206 strbuf_addstr(&format, "format:%h] %s");
1207
1208 format_commit_message(commit, "%an <%ae>", &author_ident, &pctx);
1209 format_commit_message(commit, "%cn <%ce>", &committer_ident, &pctx);
1210 if (strbuf_cmp(&author_ident, &committer_ident)) {
1211 strbuf_addstr(&format, "\n Author: ");
1212 strbuf_addbuf_percentquote(&format, &author_ident);
1213 }
1214 if (flags & SUMMARY_SHOW_AUTHOR_DATE) {
1215 struct strbuf date = STRBUF_INIT;
1216
1217 format_commit_message(commit, "%ad", &date, &pctx);
1218 strbuf_addstr(&format, "\n Date: ");
1219 strbuf_addbuf_percentquote(&format, &date);
1220 strbuf_release(&date);
1221 }
1222 if (!committer_ident_sufficiently_given()) {
1223 strbuf_addstr(&format, "\n Committer: ");
1224 strbuf_addbuf_percentquote(&format, &committer_ident);
1225 if (advice_implicit_identity) {
1226 strbuf_addch(&format, '\n');
1227 strbuf_addstr(&format, implicit_ident_advice());
1228 }
1229 }
1230 strbuf_release(&author_ident);
1231 strbuf_release(&committer_ident);
1232
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001233 repo_init_revisions(r, &rev, prefix);
Phillip Woode47c6ca2017-11-24 11:07:54 +00001234 setup_revisions(0, NULL, &rev, NULL);
1235
1236 rev.diff = 1;
1237 rev.diffopt.output_format =
1238 DIFF_FORMAT_SHORTSTAT | DIFF_FORMAT_SUMMARY;
1239
1240 rev.verbose_header = 1;
1241 rev.show_root_diff = 1;
1242 get_commit_format(format.buf, &rev);
1243 rev.always_show_header = 0;
Junio C Hamano0f57f732018-02-13 13:39:15 -08001244 rev.diffopt.detect_rename = DIFF_DETECT_RENAME;
Phillip Woode47c6ca2017-11-24 11:07:54 +00001245 rev.diffopt.break_opt = 0;
1246 diff_setup_done(&rev.diffopt);
1247
1248 head = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
1249 if (!head)
1250 die_errno(_("unable to resolve HEAD after creating commit"));
1251 if (!strcmp(head, "HEAD"))
1252 head = _("detached HEAD");
1253 else
1254 skip_prefix(head, "refs/heads/", &head);
1255 printf("[%s%s ", head, (flags & SUMMARY_INITIAL_COMMIT) ?
1256 _(" (root-commit)") : "");
1257
1258 if (!log_tree_commit(&rev, commit)) {
1259 rev.always_show_header = 1;
1260 rev.use_terminator = 1;
1261 log_tree_commit(&rev, commit);
1262 }
1263
1264 strbuf_release(&format);
1265}
1266
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01001267static int parse_head(struct repository *r, struct commit **head)
Phillip Wood356ee462017-11-24 11:07:57 +00001268{
1269 struct commit *current_head;
1270 struct object_id oid;
1271
1272 if (get_oid("HEAD", &oid)) {
1273 current_head = NULL;
1274 } else {
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01001275 current_head = lookup_commit_reference(r, &oid);
Phillip Wood356ee462017-11-24 11:07:57 +00001276 if (!current_head)
1277 return error(_("could not parse HEAD"));
Jeff King9001dc22018-08-28 17:22:48 -04001278 if (!oideq(&oid, &current_head->object.oid)) {
Phillip Wood356ee462017-11-24 11:07:57 +00001279 warning(_("HEAD %s is not a commit!"),
1280 oid_to_hex(&oid));
1281 }
1282 if (parse_commit(current_head))
1283 return error(_("could not parse HEAD commit"));
1284 }
1285 *head = current_head;
1286
1287 return 0;
1288}
1289
1290/*
1291 * Try to commit without forking 'git commit'. In some cases we need
1292 * to run 'git commit' to display an error message
1293 *
1294 * Returns:
1295 * -1 - error unable to commit
1296 * 0 - success
1297 * 1 - run 'git commit'
1298 */
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001299static int try_to_commit(struct repository *r,
1300 struct strbuf *msg, const char *author,
Phillip Wood356ee462017-11-24 11:07:57 +00001301 struct replay_opts *opts, unsigned int flags,
1302 struct object_id *oid)
1303{
1304 struct object_id tree;
Phillip Woodb0a31862019-08-19 02:18:23 -07001305 struct commit *current_head = NULL;
Phillip Wood356ee462017-11-24 11:07:57 +00001306 struct commit_list *parents = NULL;
1307 struct commit_extra_header *extra = NULL;
1308 struct strbuf err = STRBUF_INIT;
Phillip Wood66618a52018-01-24 12:34:22 +00001309 struct strbuf commit_msg = STRBUF_INIT;
Junio C Hamano4d924522020-01-12 12:27:41 -08001310 char *amend_author = NULL;
Phillip Wood66618a52018-01-24 12:34:22 +00001311 const char *hook_commit = NULL;
Phillip Wood356ee462017-11-24 11:07:57 +00001312 enum commit_msg_cleanup_mode cleanup;
1313 int res = 0;
1314
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01001315 if (parse_head(r, &current_head))
Phillip Wood356ee462017-11-24 11:07:57 +00001316 return -1;
Junio C Hamano4d924522020-01-12 12:27:41 -08001317
Phillip Wood356ee462017-11-24 11:07:57 +00001318 if (flags & AMEND_MSG) {
brian m. carlson42d4e1d2020-02-22 20:17:42 +00001319 const char *exclude_gpgsig[] = { "gpgsig", "gpgsig-sha256", NULL };
Phillip Wood356ee462017-11-24 11:07:57 +00001320 const char *out_enc = get_commit_output_encoding();
1321 const char *message = logmsg_reencode(current_head, NULL,
1322 out_enc);
1323
1324 if (!msg) {
1325 const char *orig_message = NULL;
1326
1327 find_commit_subject(message, &orig_message);
Phillip Wood66618a52018-01-24 12:34:22 +00001328 msg = &commit_msg;
Phillip Wood356ee462017-11-24 11:07:57 +00001329 strbuf_addstr(msg, orig_message);
Phillip Wood66618a52018-01-24 12:34:22 +00001330 hook_commit = "HEAD";
Phillip Wood356ee462017-11-24 11:07:57 +00001331 }
Junio C Hamano4d924522020-01-12 12:27:41 -08001332 author = amend_author = get_author(message);
Phillip Wood356ee462017-11-24 11:07:57 +00001333 unuse_commit_buffer(current_head, message);
1334 if (!author) {
1335 res = error(_("unable to parse commit author"));
1336 goto out;
1337 }
1338 parents = copy_commit_list(current_head->parents);
1339 extra = read_commit_extra_headers(current_head, exclude_gpgsig);
Phillip Woodb0a31862019-08-19 02:18:23 -07001340 } else if (current_head &&
1341 (!(flags & CREATE_ROOT_COMMIT) || (flags & AMEND_MSG))) {
Phillip Wood356ee462017-11-24 11:07:57 +00001342 commit_list_insert(current_head, &parents);
1343 }
1344
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001345 if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
Phillip Wood356ee462017-11-24 11:07:57 +00001346 res = error(_("git write-tree failed to write a tree"));
1347 goto out;
1348 }
1349
Phillip Wood2d05ef22019-11-22 19:43:03 +00001350 if (!(flags & ALLOW_EMPTY)) {
1351 struct commit *first_parent = current_head;
1352
1353 if (flags & AMEND_MSG) {
1354 if (current_head->parents) {
1355 first_parent = current_head->parents->item;
1356 if (repo_parse_commit(r, first_parent)) {
1357 res = error(_("could not parse HEAD commit"));
1358 goto out;
1359 }
1360 } else {
1361 first_parent = NULL;
1362 }
1363 }
1364 if (oideq(first_parent
1365 ? get_commit_tree_oid(first_parent)
1366 : the_hash_algo->empty_tree,
1367 &tree)) {
1368 res = 1; /* run 'git commit' to display error message */
1369 goto out;
1370 }
Phillip Wood356ee462017-11-24 11:07:57 +00001371 }
1372
Phillip Wood66618a52018-01-24 12:34:22 +00001373 if (find_hook("prepare-commit-msg")) {
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001374 res = run_prepare_commit_msg_hook(r, msg, hook_commit);
Phillip Wood66618a52018-01-24 12:34:22 +00001375 if (res)
1376 goto out;
1377 if (strbuf_read_file(&commit_msg, git_path_commit_editmsg(),
1378 2048) < 0) {
1379 res = error_errno(_("unable to read commit message "
1380 "from '%s'"),
1381 git_path_commit_editmsg());
1382 goto out;
1383 }
1384 msg = &commit_msg;
1385 }
1386
Phillip Woodd74f3e52019-03-29 11:08:42 +00001387 if (flags & CLEANUP_MSG)
1388 cleanup = COMMIT_MSG_CLEANUP_ALL;
1389 else if ((opts->signoff || opts->record_origin) &&
1390 !opts->explicit_cleanup)
1391 cleanup = COMMIT_MSG_CLEANUP_SPACE;
1392 else
1393 cleanup = opts->default_msg_cleanup;
Phillip Wood66618a52018-01-24 12:34:22 +00001394
1395 if (cleanup != COMMIT_MSG_CLEANUP_NONE)
1396 strbuf_stripspace(msg, cleanup == COMMIT_MSG_CLEANUP_ALL);
Elijah Newrena3ec9ea2018-09-12 14:18:48 -07001397 if ((flags & EDIT_MSG) && message_is_empty(msg, cleanup)) {
Phillip Wood66618a52018-01-24 12:34:22 +00001398 res = 1; /* run 'git commit' to display error message */
1399 goto out;
1400 }
1401
Johannes Sixt12f7bab2018-04-18 20:15:04 +02001402 reset_ident_date();
1403
Junio C Hamano8be83422018-02-15 14:55:43 -08001404 if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
1405 oid, author, opts->gpg_sign, extra)) {
Phillip Wood356ee462017-11-24 11:07:57 +00001406 res = error(_("failed to write commit object"));
1407 goto out;
1408 }
1409
1410 if (update_head_with_reflog(current_head, oid,
1411 getenv("GIT_REFLOG_ACTION"), msg, &err)) {
1412 res = error("%s", err.buf);
1413 goto out;
1414 }
1415
Phillip Wood4627bc72019-10-15 10:25:32 +00001416 run_commit_hook(0, r->index_file, "post-commit", NULL);
Phillip Wood356ee462017-11-24 11:07:57 +00001417 if (flags & AMEND_MSG)
Nguyễn Thái Ngọc Duy1d18d752019-01-12 09:13:23 +07001418 commit_post_rewrite(r, current_head, oid);
Phillip Wood356ee462017-11-24 11:07:57 +00001419
1420out:
1421 free_commit_extra_headers(extra);
1422 strbuf_release(&err);
Phillip Wood66618a52018-01-24 12:34:22 +00001423 strbuf_release(&commit_msg);
Junio C Hamano4d924522020-01-12 12:27:41 -08001424 free(amend_author);
Phillip Wood356ee462017-11-24 11:07:57 +00001425
1426 return res;
1427}
1428
Phillip Wood430b75f2019-12-06 16:06:12 +00001429static int write_rebase_head(struct object_id *oid)
1430{
1431 if (update_ref("rebase", "REBASE_HEAD", oid,
1432 NULL, REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR))
1433 return error(_("could not update %s"), "REBASE_HEAD");
1434
1435 return 0;
1436}
1437
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001438static int do_commit(struct repository *r,
1439 const char *msg_file, const char *author,
Phillip Wood430b75f2019-12-06 16:06:12 +00001440 struct replay_opts *opts, unsigned int flags,
1441 struct object_id *oid)
Phillip Wood356ee462017-11-24 11:07:57 +00001442{
1443 int res = 1;
1444
Phillip Woodb0a31862019-08-19 02:18:23 -07001445 if (!(flags & EDIT_MSG) && !(flags & VERIFY_MSG)) {
Phillip Wood356ee462017-11-24 11:07:57 +00001446 struct object_id oid;
1447 struct strbuf sb = STRBUF_INIT;
1448
1449 if (msg_file && strbuf_read_file(&sb, msg_file, 2048) < 0)
1450 return error_errno(_("unable to read commit message "
1451 "from '%s'"),
1452 msg_file);
1453
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001454 res = try_to_commit(r, msg_file ? &sb : NULL,
1455 author, opts, flags, &oid);
Phillip Wood356ee462017-11-24 11:07:57 +00001456 strbuf_release(&sb);
1457 if (!res) {
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001458 unlink(git_path_cherry_pick_head(r));
1459 unlink(git_path_merge_msg(r));
Phillip Wood356ee462017-11-24 11:07:57 +00001460 if (!is_rebase_i(opts))
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001461 print_commit_summary(r, NULL, &oid,
Phillip Wood356ee462017-11-24 11:07:57 +00001462 SUMMARY_SHOW_AUTHOR_DATE);
1463 return res;
1464 }
1465 }
Phillip Wood430b75f2019-12-06 16:06:12 +00001466 if (res == 1) {
1467 if (is_rebase_i(opts) && oid)
1468 if (write_rebase_head(oid))
1469 return -1;
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001470 return run_git_commit(r, msg_file, opts, flags);
Phillip Wood430b75f2019-12-06 16:06:12 +00001471 }
Phillip Wood356ee462017-11-24 11:07:57 +00001472
1473 return res;
1474}
1475
Neil Hormanb27cfb02012-04-20 10:36:15 -04001476static int is_original_commit_empty(struct commit *commit)
1477{
brian m. carlson092bbcd2017-07-13 23:49:22 +00001478 const struct object_id *ptree_oid;
Neil Hormanb27cfb02012-04-20 10:36:15 -04001479
1480 if (parse_commit(commit))
Johannes Schindelinaee42e12017-12-23 00:55:43 +01001481 return error(_("could not parse commit %s"),
brian m. carlsonf2fd0762015-11-10 02:22:28 +00001482 oid_to_hex(&commit->object.oid));
Neil Hormanb27cfb02012-04-20 10:36:15 -04001483 if (commit->parents) {
1484 struct commit *parent = commit->parents->item;
1485 if (parse_commit(parent))
Johannes Schindelinaee42e12017-12-23 00:55:43 +01001486 return error(_("could not parse parent commit %s"),
brian m. carlsonf2fd0762015-11-10 02:22:28 +00001487 oid_to_hex(&parent->object.oid));
Derrick Stolee2e27bd72018-04-06 19:09:38 +00001488 ptree_oid = get_commit_tree_oid(parent);
Neil Hormanb27cfb02012-04-20 10:36:15 -04001489 } else {
brian m. carlsoneb0ccfd2017-11-12 21:28:54 +00001490 ptree_oid = the_hash_algo->empty_tree; /* commit is root */
Neil Hormanb27cfb02012-04-20 10:36:15 -04001491 }
1492
Jeff King4a7e27e2018-08-28 17:22:40 -04001493 return oideq(ptree_oid, get_commit_tree_oid(commit));
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301494}
1495
Junio C Hamanoac2b0e82012-05-29 17:14:41 -07001496/*
Elijah Newrene98c4262020-02-15 21:36:25 +00001497 * Should empty commits be allowed? Return status:
1498 * <0: Error in is_index_unchanged(r) or is_original_commit_empty(commit)
1499 * 0: Halt on empty commit
1500 * 1: Allow empty commit
1501 * 2: Drop empty commit
Junio C Hamanoac2b0e82012-05-29 17:14:41 -07001502 */
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001503static int allow_empty(struct repository *r,
1504 struct replay_opts *opts,
1505 struct commit *commit)
Junio C Hamanoac2b0e82012-05-29 17:14:41 -07001506{
Elijah Newrend48e5e22020-02-15 21:36:24 +00001507 int index_unchanged, originally_empty;
Junio C Hamanoac2b0e82012-05-29 17:14:41 -07001508
1509 /*
Elijah Newrene98c4262020-02-15 21:36:25 +00001510 * Four cases:
Junio C Hamanoac2b0e82012-05-29 17:14:41 -07001511 *
1512 * (1) we do not allow empty at all and error out.
1513 *
Elijah Newrene98c4262020-02-15 21:36:25 +00001514 * (2) we allow ones that were initially empty, and
1515 * just drop the ones that become empty
Junio C Hamanoac2b0e82012-05-29 17:14:41 -07001516 *
Elijah Newrene98c4262020-02-15 21:36:25 +00001517 * (3) we allow ones that were initially empty, but
1518 * halt for the ones that become empty;
1519 *
1520 * (4) we allow both.
Junio C Hamanoac2b0e82012-05-29 17:14:41 -07001521 */
1522 if (!opts->allow_empty)
1523 return 0; /* let "git commit" barf as necessary */
1524
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01001525 index_unchanged = is_index_unchanged(r);
Junio C Hamanoac2b0e82012-05-29 17:14:41 -07001526 if (index_unchanged < 0)
1527 return index_unchanged;
1528 if (!index_unchanged)
1529 return 0; /* we do not have to say --allow-empty */
1530
1531 if (opts->keep_redundant_commits)
1532 return 1;
1533
Elijah Newrend48e5e22020-02-15 21:36:24 +00001534 originally_empty = is_original_commit_empty(commit);
1535 if (originally_empty < 0)
1536 return originally_empty;
Elijah Newrene98c4262020-02-15 21:36:25 +00001537 if (originally_empty)
Junio C Hamanoac2b0e82012-05-29 17:14:41 -07001538 return 1;
Elijah Newrene98c4262020-02-15 21:36:25 +00001539 else if (opts->drop_redundant_commits)
1540 return 2;
1541 else
1542 return 0;
Junio C Hamanoac2b0e82012-05-29 17:14:41 -07001543}
1544
Johannes Schindelin414697a2017-01-02 16:27:15 +01001545static struct {
1546 char c;
1547 const char *str;
1548} todo_command_info[] = {
1549 { 'p', "pick" },
1550 { 0, "revert" },
1551 { 'e', "edit" },
Johannes Schindelin04efc8b2017-01-02 16:28:00 +01001552 { 'r', "reword" },
Johannes Schindelin414697a2017-01-02 16:27:15 +01001553 { 'f', "fixup" },
1554 { 's', "squash" },
1555 { 'x', "exec" },
Johannes Schindelin71f82462018-10-12 06:14:26 -07001556 { 'b', "break" },
Johannes Schindelin9055e402018-04-25 14:28:47 +02001557 { 'l', "label" },
1558 { 't', "reset" },
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02001559 { 'm', "merge" },
Johannes Schindelinb3fdd582017-01-02 16:34:34 +01001560 { 0, "noop" },
Johannes Schindelinac191472017-01-02 16:34:39 +01001561 { 'd', "drop" },
1562 { 0, NULL }
Johannes Schindelin004fefa2016-10-21 14:24:41 +02001563};
1564
1565static const char *command_to_string(const enum todo_command command)
1566{
Johannes Schindelinac191472017-01-02 16:34:39 +01001567 if (command < TODO_COMMENT)
Johannes Schindelin414697a2017-01-02 16:27:15 +01001568 return todo_command_info[command].str;
Nguyễn Thái Ngọc Duy02127c62018-07-21 09:49:38 +02001569 die(_("unknown command: %d"), command);
Johannes Schindelin004fefa2016-10-21 14:24:41 +02001570}
1571
Junio C Hamanoee5462d2017-12-27 11:12:45 -08001572static char command_to_char(const enum todo_command command)
Liam Beguind8ae6c82017-12-05 12:52:34 -05001573{
Alban Gruin68e70902020-03-30 14:42:35 +02001574 if (command < TODO_COMMENT)
Liam Beguind8ae6c82017-12-05 12:52:34 -05001575 return todo_command_info[command].c;
1576 return comment_line_char;
1577}
1578
Johannes Schindelin25c43662017-01-02 16:26:38 +01001579static int is_noop(const enum todo_command command)
1580{
Johannes Schindelinb3fdd582017-01-02 16:34:34 +01001581 return TODO_NOOP <= command;
Johannes Schindelin25c43662017-01-02 16:26:38 +01001582}
Johannes Schindelin004fefa2016-10-21 14:24:41 +02001583
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001584static int is_fixup(enum todo_command command)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301585{
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001586 return command == TODO_FIXUP || command == TODO_SQUASH;
1587}
1588
Johannes Schindelind87d48b2018-05-04 01:01:17 +02001589/* Does this command create a (non-merge) commit? */
1590static int is_pick_or_similar(enum todo_command command)
1591{
1592 switch (command) {
1593 case TODO_PICK:
1594 case TODO_REVERT:
1595 case TODO_EDIT:
1596 case TODO_REWORD:
1597 case TODO_FIXUP:
1598 case TODO_SQUASH:
1599 return 1;
1600 default:
1601 return 0;
1602 }
1603}
1604
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01001605static int update_squash_messages(struct repository *r,
1606 enum todo_command command,
1607 struct commit *commit,
1608 struct replay_opts *opts)
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001609{
1610 struct strbuf buf = STRBUF_INIT;
Johannes Schindeline12a7ef2018-04-27 22:48:21 +02001611 int res;
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001612 const char *message, *body;
Doan Tran Cong Danhb3757442019-11-08 16:43:48 +07001613 const char *encoding = get_commit_output_encoding();
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001614
Johannes Schindeline12a7ef2018-04-27 22:48:21 +02001615 if (opts->current_fixup_count > 0) {
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001616 struct strbuf header = STRBUF_INIT;
Johannes Schindeline12a7ef2018-04-27 22:48:21 +02001617 char *eol;
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001618
Johannes Schindeline12a7ef2018-04-27 22:48:21 +02001619 if (strbuf_read_file(&buf, rebase_path_squash_msg(), 9) <= 0)
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001620 return error(_("could not read '%s'"),
1621 rebase_path_squash_msg());
1622
Johannes Schindeline12a7ef2018-04-27 22:48:21 +02001623 eol = buf.buf[0] != comment_line_char ?
1624 buf.buf : strchrnul(buf.buf, '\n');
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001625
1626 strbuf_addf(&header, "%c ", comment_line_char);
Johannes Schindeline12a7ef2018-04-27 22:48:21 +02001627 strbuf_addf(&header, _("This is a combination of %d commits."),
1628 opts->current_fixup_count + 2);
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001629 strbuf_splice(&buf, 0, eol - buf.buf, header.buf, header.len);
1630 strbuf_release(&header);
1631 } else {
brian m. carlson33d66df2017-05-06 22:10:07 +00001632 struct object_id head;
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001633 struct commit *head_commit;
1634 const char *head_message, *body;
1635
brian m. carlson33d66df2017-05-06 22:10:07 +00001636 if (get_oid("HEAD", &head))
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001637 return error(_("need a HEAD to fixup"));
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01001638 if (!(head_commit = lookup_commit_reference(r, &head)))
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001639 return error(_("could not read HEAD"));
Doan Tran Cong Danhb3757442019-11-08 16:43:48 +07001640 if (!(head_message = logmsg_reencode(head_commit, NULL, encoding)))
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001641 return error(_("could not read HEAD's commit message"));
1642
1643 find_commit_subject(head_message, &body);
1644 if (write_message(body, strlen(body),
1645 rebase_path_fixup_msg(), 0)) {
1646 unuse_commit_buffer(head_commit, head_message);
1647 return error(_("cannot write '%s'"),
1648 rebase_path_fixup_msg());
1649 }
1650
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001651 strbuf_addf(&buf, "%c ", comment_line_char);
Johannes Schindeline12a7ef2018-04-27 22:48:21 +02001652 strbuf_addf(&buf, _("This is a combination of %d commits."), 2);
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001653 strbuf_addf(&buf, "\n%c ", comment_line_char);
1654 strbuf_addstr(&buf, _("This is the 1st commit message:"));
1655 strbuf_addstr(&buf, "\n\n");
1656 strbuf_addstr(&buf, body);
1657
1658 unuse_commit_buffer(head_commit, head_message);
1659 }
1660
Doan Tran Cong Danhb3757442019-11-08 16:43:48 +07001661 if (!(message = logmsg_reencode(commit, NULL, encoding)))
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001662 return error(_("could not read commit message of %s"),
1663 oid_to_hex(&commit->object.oid));
1664 find_commit_subject(message, &body);
1665
1666 if (command == TODO_SQUASH) {
1667 unlink(rebase_path_fixup_msg());
1668 strbuf_addf(&buf, "\n%c ", comment_line_char);
Johannes Schindeline12a7ef2018-04-27 22:48:21 +02001669 strbuf_addf(&buf, _("This is the commit message #%d:"),
Phillip Wooddd2e36e2018-08-15 10:41:25 +01001670 ++opts->current_fixup_count + 1);
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001671 strbuf_addstr(&buf, "\n\n");
1672 strbuf_addstr(&buf, body);
1673 } else if (command == TODO_FIXUP) {
1674 strbuf_addf(&buf, "\n%c ", comment_line_char);
1675 strbuf_addf(&buf, _("The commit message #%d will be skipped:"),
Phillip Wooddd2e36e2018-08-15 10:41:25 +01001676 ++opts->current_fixup_count + 1);
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001677 strbuf_addstr(&buf, "\n\n");
1678 strbuf_add_commented_lines(&buf, body, strlen(body));
1679 } else
1680 return error(_("unknown command: %d"), command);
1681 unuse_commit_buffer(commit, message);
1682
1683 res = write_message(buf.buf, buf.len, rebase_path_squash_msg(), 0);
1684 strbuf_release(&buf);
Johannes Schindeline12a7ef2018-04-27 22:48:21 +02001685
1686 if (!res) {
1687 strbuf_addf(&opts->current_fixups, "%s%s %s",
1688 opts->current_fixups.len ? "\n" : "",
1689 command_to_string(command),
1690 oid_to_hex(&commit->object.oid));
1691 res = write_message(opts->current_fixups.buf,
1692 opts->current_fixups.len,
1693 rebase_path_current_fixups(), 0);
1694 }
1695
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001696 return res;
1697}
1698
Nguyễn Thái Ngọc Duy3b335762018-12-09 11:25:21 +01001699static void flush_rewritten_pending(void)
1700{
Johannes Schindelin25cb8df2017-01-02 16:28:16 +01001701 struct strbuf buf = STRBUF_INIT;
brian m. carlson092bbcd2017-07-13 23:49:22 +00001702 struct object_id newoid;
Johannes Schindelin25cb8df2017-01-02 16:28:16 +01001703 FILE *out;
1704
brian m. carlson092bbcd2017-07-13 23:49:22 +00001705 if (strbuf_read_file(&buf, rebase_path_rewritten_pending(), (GIT_MAX_HEXSZ + 1) * 2) > 0 &&
1706 !get_oid("HEAD", &newoid) &&
Nguyễn Thái Ngọc Duye9d983f2017-05-03 17:16:50 +07001707 (out = fopen_or_warn(rebase_path_rewritten_list(), "a"))) {
Johannes Schindelin25cb8df2017-01-02 16:28:16 +01001708 char *bol = buf.buf, *eol;
1709
1710 while (*bol) {
1711 eol = strchrnul(bol, '\n');
1712 fprintf(out, "%.*s %s\n", (int)(eol - bol),
brian m. carlson092bbcd2017-07-13 23:49:22 +00001713 bol, oid_to_hex(&newoid));
Johannes Schindelin25cb8df2017-01-02 16:28:16 +01001714 if (!*eol)
1715 break;
1716 bol = eol + 1;
1717 }
1718 fclose(out);
1719 unlink(rebase_path_rewritten_pending());
1720 }
1721 strbuf_release(&buf);
1722}
1723
1724static void record_in_rewritten(struct object_id *oid,
Nguyễn Thái Ngọc Duy3b335762018-12-09 11:25:21 +01001725 enum todo_command next_command)
1726{
Nguyễn Thái Ngọc Duye9d983f2017-05-03 17:16:50 +07001727 FILE *out = fopen_or_warn(rebase_path_rewritten_pending(), "a");
Johannes Schindelin25cb8df2017-01-02 16:28:16 +01001728
1729 if (!out)
1730 return;
1731
1732 fprintf(out, "%s\n", oid_to_hex(oid));
1733 fclose(out);
1734
1735 if (!is_fixup(next_command))
1736 flush_rewritten_pending();
1737}
1738
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001739static int do_pick_commit(struct repository *r,
1740 enum todo_command command,
1741 struct commit *commit,
1742 struct replay_opts *opts,
Phillip Wooda47ba3c2019-08-19 02:18:22 -07001743 int final_fixup, int *check_todo)
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001744{
Johannes Schindelin789b3ef2017-03-23 17:07:11 +01001745 unsigned int flags = opts->edit ? EDIT_MSG : 0;
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001746 const char *msg_file = opts->edit ? NULL : git_path_merge_msg(r);
brian m. carlsonace976b2017-05-06 22:10:32 +00001747 struct object_id head;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301748 struct commit *base, *next, *parent;
1749 const char *base_label, *next_label;
Phillip Wood356ee462017-11-24 11:07:57 +00001750 char *author = NULL;
Jeff Kingd74a4e52014-06-10 17:39:35 -04001751 struct commit_message msg = { NULL, NULL, NULL, NULL };
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301752 struct strbuf msgbuf = STRBUF_INIT;
Elijah Newrene98c4262020-02-15 21:36:25 +00001753 int res, unborn = 0, reword = 0, allow, drop_commit;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301754
1755 if (opts->no_commit) {
1756 /*
1757 * We do not intend to commit immediately. We just want to
1758 * merge the differences in, so let's compute the tree
1759 * that represents the "current" state for merge-recursive
1760 * to work on.
1761 */
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001762 if (write_index_as_tree(&head, r->index, r->index_file, 0, NULL))
Johannes Schindelin93b3df62016-10-21 14:26:25 +02001763 return error(_("your index file is unmerged."));
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301764 } else {
brian m. carlsonace976b2017-05-06 22:10:32 +00001765 unborn = get_oid("HEAD", &head);
Johannes Schindelind87d48b2018-05-04 01:01:17 +02001766 /* Do we want to generate a root commit? */
1767 if (is_pick_or_similar(command) && opts->have_squash_onto &&
Jeff King4a7e27e2018-08-28 17:22:40 -04001768 oideq(&head, &opts->squash_onto)) {
Johannes Schindelind87d48b2018-05-04 01:01:17 +02001769 if (is_fixup(command))
1770 return error(_("cannot fixup root commit"));
1771 flags |= CREATE_ROOT_COMMIT;
1772 unborn = 1;
1773 } else if (unborn)
brian m. carlsoneb0ccfd2017-11-12 21:28:54 +00001774 oidcpy(&head, the_hash_algo->empty_tree);
Nguyễn Thái Ngọc Duyffc00a42018-11-10 06:49:04 +01001775 if (index_differs_from(r, unborn ? empty_tree_oid_hex() : "HEAD",
Brandon Williams02f2f562017-10-31 11:19:05 -07001776 NULL, 0))
Nguyễn Thái Ngọc Duye1ff0a32019-01-12 09:13:26 +07001777 return error_dirty_index(r, opts);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301778 }
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001779 discard_index(r->index);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301780
Johannes Schindelin637666c2017-01-02 16:26:08 +01001781 if (!commit->parents)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301782 parent = NULL;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301783 else if (commit->parents->next) {
1784 /* Reverting or cherry-picking a merge commit */
1785 int cnt;
1786 struct commit_list *p;
1787
1788 if (!opts->mainline)
Johannes Schindelin93b3df62016-10-21 14:26:25 +02001789 return error(_("commit %s is a merge but no -m option was given."),
brian m. carlsonf2fd0762015-11-10 02:22:28 +00001790 oid_to_hex(&commit->object.oid));
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301791
1792 for (cnt = 1, p = commit->parents;
1793 cnt != opts->mainline && p;
1794 cnt++)
1795 p = p->next;
1796 if (cnt != opts->mainline || !p)
Johannes Schindelin93b3df62016-10-21 14:26:25 +02001797 return error(_("commit %s does not have parent %d"),
brian m. carlsonf2fd0762015-11-10 02:22:28 +00001798 oid_to_hex(&commit->object.oid), opts->mainline);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301799 parent = p->item;
Sergey Organov37897bf2018-12-14 07:53:51 +03001800 } else if (1 < opts->mainline)
1801 /*
1802 * Non-first parent explicitly specified as mainline for
1803 * non-merge commit
1804 */
1805 return error(_("commit %s does not have parent %d"),
1806 oid_to_hex(&commit->object.oid), opts->mainline);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301807 else
1808 parent = commit->parents->item;
1809
Johannes Schindelinbcbb68b2017-01-02 16:28:05 +01001810 if (get_message(commit, &msg) != 0)
1811 return error(_("cannot get commit message for %s"),
1812 oid_to_hex(&commit->object.oid));
1813
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001814 if (opts->allow_ff && !is_fixup(command) &&
Jeff King4a7e27e2018-08-28 17:22:40 -04001815 ((parent && oideq(&parent->object.oid, &head)) ||
Johannes Schindelinbcbb68b2017-01-02 16:28:05 +01001816 (!parent && unborn))) {
1817 if (is_rebase_i(opts))
1818 write_author_script(msg.message);
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001819 res = fast_forward_to(r, &commit->object.oid, &head, unborn,
Johannes Schindelinbcbb68b2017-01-02 16:28:05 +01001820 opts);
1821 if (res || command != TODO_REWORD)
1822 goto leave;
Phillip Wood450efe22019-08-19 02:18:21 -07001823 reword = 1;
Johannes Schindelinbcbb68b2017-01-02 16:28:05 +01001824 msg_file = NULL;
1825 goto fast_forward_edit;
1826 }
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301827 if (parent && parse_commit(parent) < 0)
Johannes Schindelin004fefa2016-10-21 14:24:41 +02001828 /* TRANSLATORS: The first %s will be a "todo" command like
1829 "revert" or "pick", the second %s a SHA1. */
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301830 return error(_("%s: cannot parse parent commit %s"),
Johannes Schindelin004fefa2016-10-21 14:24:41 +02001831 command_to_string(command),
1832 oid_to_hex(&parent->object.oid));
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301833
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301834 /*
1835 * "commit" is an existing commit. We would want to apply
1836 * the difference it introduces since its first parent "prev"
1837 * on top of the current HEAD if we are cherry-pick. Or the
1838 * reverse of it if we are revert.
1839 */
1840
Johannes Schindelin004fefa2016-10-21 14:24:41 +02001841 if (command == TODO_REVERT) {
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301842 base = commit;
1843 base_label = msg.label;
1844 next = parent;
1845 next_label = msg.parent_label;
1846 strbuf_addstr(&msgbuf, "Revert \"");
1847 strbuf_addstr(&msgbuf, msg.subject);
1848 strbuf_addstr(&msgbuf, "\"\n\nThis reverts commit ");
brian m. carlsonf2fd0762015-11-10 02:22:28 +00001849 strbuf_addstr(&msgbuf, oid_to_hex(&commit->object.oid));
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301850
1851 if (commit->parents && commit->parents->next) {
1852 strbuf_addstr(&msgbuf, ", reversing\nchanges made to ");
brian m. carlsonf2fd0762015-11-10 02:22:28 +00001853 strbuf_addstr(&msgbuf, oid_to_hex(&parent->object.oid));
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301854 }
1855 strbuf_addstr(&msgbuf, ".\n");
1856 } else {
1857 const char *p;
1858
1859 base = parent;
1860 base_label = msg.parent_label;
1861 next = commit;
1862 next_label = msg.label;
1863
Johannes Schindelin23aa5142017-01-02 16:26:20 +01001864 /* Append the commit log message to msgbuf. */
1865 if (find_commit_subject(msg.message, &p))
1866 strbuf_addstr(&msgbuf, p);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301867
1868 if (opts->record_origin) {
Jonathan Tan44dc7382017-04-26 13:50:03 -07001869 strbuf_complete_line(&msgbuf);
Brandon Caseybab4d102013-02-12 02:17:35 -08001870 if (!has_conforming_footer(&msgbuf, NULL, 0))
Brandon Caseyb971e042013-02-12 02:17:34 -08001871 strbuf_addch(&msgbuf, '\n');
Brandon Caseycd650a42013-02-12 02:17:32 -08001872 strbuf_addstr(&msgbuf, cherry_picked_prefix);
brian m. carlsonf2fd0762015-11-10 02:22:28 +00001873 strbuf_addstr(&msgbuf, oid_to_hex(&commit->object.oid));
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301874 strbuf_addstr(&msgbuf, ")\n");
1875 }
Phillip Wood356ee462017-11-24 11:07:57 +00001876 if (!is_fixup(command))
1877 author = get_author(msg.message);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301878 }
1879
Johannes Schindelin04efc8b2017-01-02 16:28:00 +01001880 if (command == TODO_REWORD)
Phillip Wood450efe22019-08-19 02:18:21 -07001881 reword = 1;
Johannes Schindelin04efc8b2017-01-02 16:28:00 +01001882 else if (is_fixup(command)) {
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01001883 if (update_squash_messages(r, command, commit, opts))
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001884 return -1;
Johannes Schindelin789b3ef2017-03-23 17:07:11 +01001885 flags |= AMEND_MSG;
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001886 if (!final_fixup)
1887 msg_file = rebase_path_squash_msg();
1888 else if (file_exists(rebase_path_fixup_msg())) {
Johannes Schindelin789b3ef2017-03-23 17:07:11 +01001889 flags |= CLEANUP_MSG;
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001890 msg_file = rebase_path_fixup_msg();
1891 } else {
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001892 const char *dest = git_path_squash_msg(r);
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001893 unlink(dest);
1894 if (copy_file(dest, rebase_path_squash_msg(), 0666))
1895 return error(_("could not rename '%s' to '%s'"),
1896 rebase_path_squash_msg(), dest);
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001897 unlink(git_path_merge_msg(r));
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001898 msg_file = dest;
Johannes Schindelin789b3ef2017-03-23 17:07:11 +01001899 flags |= EDIT_MSG;
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001900 }
1901 }
1902
Phillip Wooda852ec72018-03-20 11:10:55 +00001903 if (opts->signoff && !is_fixup(command))
Phillip Woodb34eeea2017-11-24 11:07:55 +00001904 append_signoff(&msgbuf, 0, 0);
1905
Johannes Schindelin0473f282017-01-02 16:27:18 +01001906 if (is_rebase_i(opts) && write_author_script(msg.message) < 0)
1907 res = -1;
1908 else if (!opts->strategy || !strcmp(opts->strategy, "recursive") || command == TODO_REVERT) {
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001909 res = do_recursive_merge(r, base, next, base_label, next_label,
brian m. carlson48be4c62017-05-06 22:10:36 +00001910 &head, &msgbuf, opts);
Johannes Schindelinf241ff02016-07-26 18:06:02 +02001911 if (res < 0)
Stefan Beller19517fb2018-06-01 13:01:45 -07001912 goto leave;
1913
Johannes Schindelin75871492016-10-21 14:26:05 +02001914 res |= write_message(msgbuf.buf, msgbuf.len,
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001915 git_path_merge_msg(r), 0);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301916 } else {
1917 struct commit_list *common = NULL;
1918 struct commit_list *remotes = NULL;
1919
Johannes Schindelin75871492016-10-21 14:26:05 +02001920 res = write_message(msgbuf.buf, msgbuf.len,
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001921 git_path_merge_msg(r), 0);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301922
1923 commit_list_insert(base, &common);
1924 commit_list_insert(next, &remotes);
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001925 res |= try_merge_command(r, opts->strategy,
Johannes Schindelin03a4e262016-10-21 14:24:13 +02001926 opts->xopts_nr, (const char **)opts->xopts,
brian m. carlsonace976b2017-05-06 22:10:32 +00001927 common, oid_to_hex(&head), remotes);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301928 free_commit_list(common);
1929 free_commit_list(remotes);
1930 }
Johannes Schindelin452202c2016-10-21 14:25:41 +02001931 strbuf_release(&msgbuf);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301932
1933 /*
1934 * If the merge was clean or if it failed due to conflict, we write
1935 * CHERRY_PICK_HEAD for the subsequent invocation of commit to use.
1936 * However, if the merge did not even start, then we don't want to
1937 * write it at all.
1938 */
Phillip Wood21b11c62019-12-06 16:06:09 +00001939 if ((command == TODO_PICK || command == TODO_REWORD ||
1940 command == TODO_EDIT) && !opts->no_commit &&
1941 (res == 0 || res == 1) &&
brian m. carlsonae077772017-10-15 22:06:51 +00001942 update_ref(NULL, "CHERRY_PICK_HEAD", &commit->object.oid, NULL,
Michael Haggerty91774af2017-11-05 09:42:06 +01001943 REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR))
Johannes Schindelindbfad032016-08-26 15:47:14 +02001944 res = -1;
Johannes Schindelin004fefa2016-10-21 14:24:41 +02001945 if (command == TODO_REVERT && ((opts->no_commit && res == 0) || res == 1) &&
brian m. carlsonae077772017-10-15 22:06:51 +00001946 update_ref(NULL, "REVERT_HEAD", &commit->object.oid, NULL,
Michael Haggerty91774af2017-11-05 09:42:06 +01001947 REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR))
Johannes Schindelindbfad032016-08-26 15:47:14 +02001948 res = -1;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301949
1950 if (res) {
Johannes Schindelin004fefa2016-10-21 14:24:41 +02001951 error(command == TODO_REVERT
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301952 ? _("could not revert %s... %s")
1953 : _("could not apply %s... %s"),
Johannes Schindelin39755962016-10-21 14:24:37 +02001954 short_commit_name(commit), msg.subject);
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01001955 print_advice(r, res == 1, opts);
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001956 repo_rerere(r, opts->allow_rerere_auto);
Felipe Contrerasc8d13512013-05-28 22:56:21 -05001957 goto leave;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05301958 }
1959
Elijah Newrene98c4262020-02-15 21:36:25 +00001960 drop_commit = 0;
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01001961 allow = allow_empty(r, opts, commit);
Felipe Contreras706728a2013-06-06 03:58:57 -05001962 if (allow < 0) {
1963 res = allow;
1964 goto leave;
Elijah Newrene98c4262020-02-15 21:36:25 +00001965 } else if (allow == 1) {
Johannes Schindelin789b3ef2017-03-23 17:07:11 +01001966 flags |= ALLOW_EMPTY;
Elijah Newrene98c4262020-02-15 21:36:25 +00001967 } else if (allow == 2) {
1968 drop_commit = 1;
Elijah Newren9a1b7472020-03-11 15:30:22 +00001969 unlink(git_path_cherry_pick_head(r));
1970 unlink(git_path_merge_msg(r));
Elijah Newrene98c4262020-02-15 21:36:25 +00001971 fprintf(stderr,
1972 _("dropping %s %s -- patch contents already upstream\n"),
1973 oid_to_hex(&commit->object.oid), msg.subject);
1974 } /* else allow == 0 and there's nothing special to do */
1975 if (!opts->no_commit && !drop_commit) {
Phillip Wood356ee462017-11-24 11:07:57 +00001976 if (author || command == TODO_REVERT || (flags & AMEND_MSG))
Phillip Wood430b75f2019-12-06 16:06:12 +00001977 res = do_commit(r, msg_file, author, opts, flags,
1978 commit? &commit->object.oid : NULL);
Phillip Wood356ee462017-11-24 11:07:57 +00001979 else
1980 res = error(_("unable to parse commit author"));
Phillip Wooda47ba3c2019-08-19 02:18:22 -07001981 *check_todo = !!(flags & EDIT_MSG);
1982 if (!res && reword) {
Phillip Wood450efe22019-08-19 02:18:21 -07001983fast_forward_edit:
1984 res = run_git_commit(r, NULL, opts, EDIT_MSG |
1985 VERIFY_MSG | AMEND_MSG |
1986 (flags & ALLOW_EMPTY));
Phillip Wooda47ba3c2019-08-19 02:18:22 -07001987 *check_todo = 1;
1988 }
Phillip Wood356ee462017-11-24 11:07:57 +00001989 }
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001990
Phillip Wood450efe22019-08-19 02:18:21 -07001991
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001992 if (!res && final_fixup) {
1993 unlink(rebase_path_fixup_msg());
1994 unlink(rebase_path_squash_msg());
Johannes Schindeline12a7ef2018-04-27 22:48:21 +02001995 unlink(rebase_path_current_fixups());
1996 strbuf_reset(&opts->current_fixups);
1997 opts->current_fixup_count = 0;
Johannes Schindelin6e98de72017-01-02 16:27:07 +01001998 }
Felipe Contrerasc8d13512013-05-28 22:56:21 -05001999
2000leave:
Jeff Kingd74a4e52014-06-10 17:39:35 -04002001 free_message(commit, &msg);
Phillip Wood356ee462017-11-24 11:07:57 +00002002 free(author);
Stephan Beyer1e412292016-12-07 22:51:32 +01002003 update_abort_safety_file();
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302004
2005 return res;
2006}
2007
Johannes Schindelinc3e86182016-09-09 16:37:18 +02002008static int prepare_revs(struct replay_opts *opts)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302009{
Martin von Zweigbergka73e22e2012-08-28 23:15:56 -07002010 /*
2011 * picking (but not reverting) ranges (but not individual revisions)
2012 * should be done in reverse
2013 */
2014 if (opts->action == REPLAY_PICK && !opts->revs->no_walk)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302015 opts->revs->reverse ^= 1;
2016
2017 if (prepare_revision_walk(opts->revs))
Johannes Schindelinc3e86182016-09-09 16:37:18 +02002018 return error(_("revision walk setup failed"));
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302019
Johannes Schindelinc3e86182016-09-09 16:37:18 +02002020 return 0;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302021}
2022
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01002023static int read_and_refresh_cache(struct repository *r,
2024 struct replay_opts *opts)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302025{
Martin Ågren14bca6c2018-02-27 22:30:09 +01002026 struct lock_file index_lock = LOCK_INIT;
Nguyễn Thái Ngọc Duy3a95f312019-01-12 09:13:24 +07002027 int index_fd = repo_hold_locked_index(r, &index_lock, 0);
2028 if (repo_read_index(r) < 0) {
Johannes Schindelin49fb9372016-09-09 16:38:20 +02002029 rollback_lock_file(&index_lock);
Johannes Schindelin0d9c6dc2016-09-09 16:37:21 +02002030 return error(_("git %s: failed to read the index"),
Johannes Schindelinc28cbc52016-10-21 14:26:17 +02002031 _(action_name(opts)));
Johannes Schindelin49fb9372016-09-09 16:38:20 +02002032 }
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01002033 refresh_index(r->index, REFRESH_QUIET|REFRESH_UNMERGED, NULL, NULL, NULL);
Martin Ågren61000812018-03-01 21:40:20 +01002034 if (index_fd >= 0) {
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01002035 if (write_locked_index(r->index, &index_lock,
Martin Ågren61000812018-03-01 21:40:20 +01002036 COMMIT_LOCK | SKIP_IF_UNCHANGED)) {
Johannes Schindelin0d9c6dc2016-09-09 16:37:21 +02002037 return error(_("git %s: failed to refresh the index"),
Johannes Schindelinc28cbc52016-10-21 14:26:17 +02002038 _(action_name(opts)));
Johannes Schindelin49fb9372016-09-09 16:38:20 +02002039 }
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302040 }
Johannes Schindelin0d9c6dc2016-09-09 16:37:21 +02002041 return 0;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302042}
2043
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02002044enum todo_item_flags {
2045 TODO_EDIT_MERGE_MSG = 1
2046};
2047
Alban Gruin5d94d542018-12-29 17:03:59 +01002048void todo_list_release(struct todo_list *todo_list)
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002049{
2050 strbuf_release(&todo_list->buf);
Ævar Arnfjörð Bjarmason6a83d902017-06-15 23:15:46 +00002051 FREE_AND_NULL(todo_list->items);
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002052 todo_list->nr = todo_list->alloc = 0;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302053}
2054
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002055static struct todo_item *append_new_todo(struct todo_list *todo_list)
2056{
2057 ALLOC_GROW(todo_list->items, todo_list->nr + 1, todo_list->alloc);
Alban Gruin86381142019-11-24 18:43:28 +01002058 todo_list->total_nr++;
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002059 return todo_list->items + todo_list->nr++;
2060}
2061
Alban Gruin6ad656d2019-01-29 16:01:46 +01002062const char *todo_item_get_arg(struct todo_list *todo_list,
2063 struct todo_item *item)
2064{
2065 return todo_list->buf.buf + item->arg_offset;
2066}
2067
Phillip Wood3e81bcc2019-06-27 07:12:45 -07002068static int is_command(enum todo_command command, const char **bol)
2069{
2070 const char *str = todo_command_info[command].str;
2071 const char nick = todo_command_info[command].c;
2072 const char *p = *bol + 1;
2073
2074 return skip_prefix(*bol, str, bol) ||
2075 ((nick && **bol == nick) &&
2076 (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || !*p) &&
2077 (*bol = p));
2078}
2079
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01002080static int parse_insn_line(struct repository *r, struct todo_item *item,
Alban Gruin6ad656d2019-01-29 16:01:46 +01002081 const char *buf, const char *bol, char *eol)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302082{
brian m. carlson1e43ed92017-05-06 22:10:09 +00002083 struct object_id commit_oid;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302084 char *end_of_object_name;
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002085 int i, saved, status, padding;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302086
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02002087 item->flags = 0;
2088
Johannes Schindelin8f8550b2016-10-21 14:25:36 +02002089 /* left-trim */
2090 bol += strspn(bol, " \t");
2091
Johannes Schindelin25c43662017-01-02 16:26:38 +01002092 if (bol == eol || *bol == '\r' || *bol == comment_line_char) {
Johannes Schindelinac191472017-01-02 16:34:39 +01002093 item->command = TODO_COMMENT;
Johannes Schindelin25c43662017-01-02 16:26:38 +01002094 item->commit = NULL;
Alban Gruin6ad656d2019-01-29 16:01:46 +01002095 item->arg_offset = bol - buf;
Johannes Schindelin25c43662017-01-02 16:26:38 +01002096 item->arg_len = eol - bol;
2097 return 0;
2098 }
2099
Johannes Schindelinac191472017-01-02 16:34:39 +01002100 for (i = 0; i < TODO_COMMENT; i++)
Phillip Wood3e81bcc2019-06-27 07:12:45 -07002101 if (is_command(i, &bol)) {
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002102 item->command = i;
2103 break;
2104 }
Johannes Schindelinac191472017-01-02 16:34:39 +01002105 if (i >= TODO_COMMENT)
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002106 return -1;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302107
Johannes Schindelin66afa242017-12-23 00:55:57 +01002108 /* Eat up extra spaces/ tabs before object name */
2109 padding = strspn(bol, " \t");
2110 bol += padding;
2111
Johannes Schindelin71f82462018-10-12 06:14:26 -07002112 if (item->command == TODO_NOOP || item->command == TODO_BREAK) {
Johannes Schindelin66afa242017-12-23 00:55:57 +01002113 if (bol != eol)
2114 return error(_("%s does not accept arguments: '%s'"),
2115 command_to_string(item->command), bol);
Johannes Schindelin25c43662017-01-02 16:26:38 +01002116 item->commit = NULL;
Alban Gruin6ad656d2019-01-29 16:01:46 +01002117 item->arg_offset = bol - buf;
Johannes Schindelin25c43662017-01-02 16:26:38 +01002118 item->arg_len = eol - bol;
2119 return 0;
2120 }
2121
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302122 if (!padding)
Johannes Schindelin66afa242017-12-23 00:55:57 +01002123 return error(_("missing arguments for %s"),
2124 command_to_string(item->command));
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302125
Johannes Schindelin9055e402018-04-25 14:28:47 +02002126 if (item->command == TODO_EXEC || item->command == TODO_LABEL ||
2127 item->command == TODO_RESET) {
Liam Beguin7dcbb3c2017-12-03 17:17:15 -05002128 item->commit = NULL;
Alban Gruin6ad656d2019-01-29 16:01:46 +01002129 item->arg_offset = bol - buf;
Johannes Schindelin311af522017-01-02 16:26:47 +01002130 item->arg_len = (int)(eol - bol);
2131 return 0;
2132 }
2133
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02002134 if (item->command == TODO_MERGE) {
2135 if (skip_prefix(bol, "-C", &bol))
2136 bol += strspn(bol, " \t");
2137 else if (skip_prefix(bol, "-c", &bol)) {
2138 bol += strspn(bol, " \t");
2139 item->flags |= TODO_EDIT_MERGE_MSG;
2140 } else {
2141 item->flags |= TODO_EDIT_MERGE_MSG;
2142 item->commit = NULL;
Alban Gruin6ad656d2019-01-29 16:01:46 +01002143 item->arg_offset = bol - buf;
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02002144 item->arg_len = (int)(eol - bol);
2145 return 0;
2146 }
2147 }
2148
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002149 end_of_object_name = (char *) bol + strcspn(bol, " \t\n");
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302150 saved = *end_of_object_name;
2151 *end_of_object_name = '\0';
brian m. carlson1e43ed92017-05-06 22:10:09 +00002152 status = get_oid(bol, &commit_oid);
Johannes Schindelind859dca2020-01-23 12:28:17 +00002153 if (status < 0)
2154 error(_("could not parse '%s'"), bol); /* return later */
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302155 *end_of_object_name = saved;
2156
Alban Gruin6ad656d2019-01-29 16:01:46 +01002157 bol = end_of_object_name + strspn(end_of_object_name, " \t");
2158 item->arg_offset = bol - buf;
2159 item->arg_len = (int)(eol - bol);
Johannes Schindelinc22f7df2016-10-21 14:25:00 +02002160
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302161 if (status < 0)
Johannes Schindelind859dca2020-01-23 12:28:17 +00002162 return status;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302163
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01002164 item->commit = lookup_commit_reference(r, &commit_oid);
Johannes Schindelind859dca2020-01-23 12:28:17 +00002165 return item->commit ? 0 : -1;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302166}
2167
Phillip Wood4a724862019-04-16 11:18:42 +01002168int sequencer_get_last_command(struct repository *r, enum replay_action *action)
2169{
Phillip Wooded5b1ca2019-06-27 07:12:46 -07002170 const char *todo_file, *bol;
Phillip Wood4a724862019-04-16 11:18:42 +01002171 struct strbuf buf = STRBUF_INIT;
Phillip Wooded5b1ca2019-06-27 07:12:46 -07002172 int ret = 0;
Phillip Wood4a724862019-04-16 11:18:42 +01002173
2174 todo_file = git_path_todo_file();
2175 if (strbuf_read_file(&buf, todo_file, 0) < 0) {
Phillip Wooded5b1ca2019-06-27 07:12:46 -07002176 if (errno == ENOENT || errno == ENOTDIR)
Phillip Wood4a724862019-04-16 11:18:42 +01002177 return -1;
2178 else
2179 return error_errno("unable to open '%s'", todo_file);
2180 }
Phillip Wooded5b1ca2019-06-27 07:12:46 -07002181 bol = buf.buf + strspn(buf.buf, " \t\r\n");
2182 if (is_command(TODO_PICK, &bol) && (*bol == ' ' || *bol == '\t'))
Phillip Wood4a724862019-04-16 11:18:42 +01002183 *action = REPLAY_PICK;
Phillip Wooded5b1ca2019-06-27 07:12:46 -07002184 else if (is_command(TODO_REVERT, &bol) &&
2185 (*bol == ' ' || *bol == '\t'))
Phillip Wood4a724862019-04-16 11:18:42 +01002186 *action = REPLAY_REVERT;
2187 else
Phillip Wooded5b1ca2019-06-27 07:12:46 -07002188 ret = -1;
Phillip Wood4a724862019-04-16 11:18:42 +01002189
Phillip Wood4a724862019-04-16 11:18:42 +01002190 strbuf_release(&buf);
2191
2192 return ret;
2193}
2194
Alban Gruin5d94d542018-12-29 17:03:59 +01002195int todo_list_parse_insn_buffer(struct repository *r, char *buf,
2196 struct todo_list *todo_list)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302197{
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002198 struct todo_item *item;
2199 char *p = buf, *next_p;
Johannes Schindelin6e98de72017-01-02 16:27:07 +01002200 int i, res = 0, fixup_okay = file_exists(rebase_path_done());
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302201
Alban Gruin2b715952018-12-29 17:03:58 +01002202 todo_list->current = todo_list->nr = 0;
2203
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002204 for (i = 1; *p; i++, p = next_p) {
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302205 char *eol = strchrnul(p, '\n');
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002206
2207 next_p = *eol ? eol + 1 /* skip LF */ : eol;
2208
Johannes Schindelin63070412016-10-21 14:24:46 +02002209 if (p != eol && eol[-1] == '\r')
2210 eol--; /* strip Carriage Return */
2211
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002212 item = append_new_todo(todo_list);
2213 item->offset_in_buf = p - todo_list->buf.buf;
Alban Gruin6ad656d2019-01-29 16:01:46 +01002214 if (parse_insn_line(r, item, buf, p, eol)) {
Johannes Schindelin93b3df62016-10-21 14:26:25 +02002215 res = error(_("invalid line %d: %.*s"),
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002216 i, (int)(eol - p), p);
Alban Gruin2b715952018-12-29 17:03:58 +01002217 item->command = TODO_COMMENT + 1;
Alban Gruin6ad656d2019-01-29 16:01:46 +01002218 item->arg_offset = p - buf;
Alban Gruin2b715952018-12-29 17:03:58 +01002219 item->arg_len = (int)(eol - p);
2220 item->commit = NULL;
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002221 }
Johannes Schindelin6e98de72017-01-02 16:27:07 +01002222
2223 if (fixup_okay)
2224 ; /* do nothing */
2225 else if (is_fixup(item->command))
2226 return error(_("cannot '%s' without a previous commit"),
2227 command_to_string(item->command));
2228 else if (!is_noop(item->command))
2229 fixup_okay = 1;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302230 }
Johannes Schindelin52865272017-01-02 16:27:34 +01002231
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002232 return res;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302233}
2234
Johannes Schindelin968492e2017-01-02 16:35:46 +01002235static int count_commands(struct todo_list *todo_list)
2236{
2237 int count = 0, i;
2238
2239 for (i = 0; i < todo_list->nr; i++)
2240 if (todo_list->items[i].command != TODO_COMMENT)
2241 count++;
2242
2243 return count;
2244}
2245
Johannes Schindelina01c2a52018-04-25 14:28:29 +02002246static int get_item_line_offset(struct todo_list *todo_list, int index)
2247{
2248 return index < todo_list->nr ?
2249 todo_list->items[index].offset_in_buf : todo_list->buf.len;
2250}
2251
2252static const char *get_item_line(struct todo_list *todo_list, int index)
2253{
2254 return todo_list->buf.buf + get_item_line_offset(todo_list, index);
2255}
2256
2257static int get_item_line_length(struct todo_list *todo_list, int index)
2258{
2259 return get_item_line_offset(todo_list, index + 1)
2260 - get_item_line_offset(todo_list, index);
2261}
2262
René Scharfe87805602018-02-22 20:29:25 +01002263static ssize_t strbuf_read_file_or_whine(struct strbuf *sb, const char *path)
2264{
2265 int fd;
2266 ssize_t len;
2267
2268 fd = open(path, O_RDONLY);
2269 if (fd < 0)
2270 return error_errno(_("could not open '%s'"), path);
2271 len = strbuf_read(sb, fd, 0);
2272 close(fd);
2273 if (len < 0)
2274 return error(_("could not read '%s'."), path);
2275 return len;
2276}
2277
Phillip Woodb07d9bf2019-04-16 11:18:41 +01002278static int have_finished_the_last_pick(void)
2279{
2280 struct strbuf buf = STRBUF_INIT;
2281 const char *eol;
2282 const char *todo_path = git_path_todo_file();
2283 int ret = 0;
2284
2285 if (strbuf_read_file(&buf, todo_path, 0) < 0) {
2286 if (errno == ENOENT) {
2287 return 0;
2288 } else {
2289 error_errno("unable to open '%s'", todo_path);
2290 return 0;
2291 }
2292 }
2293 /* If there is only one line then we are done */
2294 eol = strchr(buf.buf, '\n');
2295 if (!eol || !eol[1])
2296 ret = 1;
2297
2298 strbuf_release(&buf);
2299
2300 return ret;
2301}
2302
Junio C Hamanof496b062019-07-09 15:25:44 -07002303void sequencer_post_commit_cleanup(struct repository *r, int verbose)
Phillip Woodb07d9bf2019-04-16 11:18:41 +01002304{
2305 struct replay_opts opts = REPLAY_OPTS_INIT;
2306 int need_cleanup = 0;
2307
2308 if (file_exists(git_path_cherry_pick_head(r))) {
Junio C Hamanof496b062019-07-09 15:25:44 -07002309 if (!unlink(git_path_cherry_pick_head(r)) && verbose)
2310 warning(_("cancelling a cherry picking in progress"));
Phillip Woodb07d9bf2019-04-16 11:18:41 +01002311 opts.action = REPLAY_PICK;
2312 need_cleanup = 1;
2313 }
2314
2315 if (file_exists(git_path_revert_head(r))) {
Junio C Hamanof496b062019-07-09 15:25:44 -07002316 if (!unlink(git_path_revert_head(r)) && verbose)
2317 warning(_("cancelling a revert in progress"));
Phillip Woodb07d9bf2019-04-16 11:18:41 +01002318 opts.action = REPLAY_REVERT;
2319 need_cleanup = 1;
2320 }
2321
2322 if (!need_cleanup)
2323 return;
2324
2325 if (!have_finished_the_last_pick())
2326 return;
2327
2328 sequencer_remove_state(&opts);
2329}
2330
Alban Gruin3f34f2d2019-11-24 18:43:30 +01002331static void todo_list_write_total_nr(struct todo_list *todo_list)
2332{
2333 FILE *f = fopen_or_warn(rebase_path_msgtotal(), "w");
2334
2335 if (f) {
2336 fprintf(f, "%d\n", todo_list->total_nr);
2337 fclose(f);
2338 }
2339}
2340
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01002341static int read_populate_todo(struct repository *r,
2342 struct todo_list *todo_list,
2343 struct replay_opts *opts)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302344{
Stephen Hicks54fd3242017-04-26 21:17:40 +02002345 struct stat st;
Johannes Schindelinc0246502016-10-21 14:24:32 +02002346 const char *todo_file = get_todo_path(opts);
René Scharfe87805602018-02-22 20:29:25 +01002347 int res;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302348
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002349 strbuf_reset(&todo_list->buf);
René Scharfe87805602018-02-22 20:29:25 +01002350 if (strbuf_read_file_or_whine(&todo_list->buf, todo_file) < 0)
2351 return -1;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302352
Stephen Hicks54fd3242017-04-26 21:17:40 +02002353 res = stat(todo_file, &st);
2354 if (res)
2355 return error(_("could not stat '%s'"), todo_file);
2356 fill_stat_data(&todo_list->stat, &st);
2357
Alban Gruin5d94d542018-12-29 17:03:59 +01002358 res = todo_list_parse_insn_buffer(r, todo_list->buf.buf, todo_list);
Johannes Schindelin27fdbb92017-01-02 16:35:42 +01002359 if (res) {
2360 if (is_rebase_i(opts))
2361 return error(_("please fix this using "
2362 "'git rebase --edit-todo'."));
Johannes Schindelin93b3df62016-10-21 14:26:25 +02002363 return error(_("unusable instruction sheet: '%s'"), todo_file);
Johannes Schindelin27fdbb92017-01-02 16:35:42 +01002364 }
Johannes Schindelin2eeaf1b2016-10-21 14:26:13 +02002365
Johannes Schindelin52865272017-01-02 16:27:34 +01002366 if (!todo_list->nr &&
2367 (!is_rebase_i(opts) || !file_exists(rebase_path_done())))
2368 return error(_("no commits parsed."));
2369
Johannes Schindelin2eeaf1b2016-10-21 14:26:13 +02002370 if (!is_rebase_i(opts)) {
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002371 enum todo_command valid =
2372 opts->action == REPLAY_PICK ? TODO_PICK : TODO_REVERT;
2373 int i;
2374
2375 for (i = 0; i < todo_list->nr; i++)
2376 if (valid == todo_list->items[i].command)
2377 continue;
2378 else if (valid == TODO_PICK)
Johannes Schindelin93b3df62016-10-21 14:26:25 +02002379 return error(_("cannot cherry-pick during a revert."));
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002380 else
Johannes Schindelin93b3df62016-10-21 14:26:25 +02002381 return error(_("cannot revert during a cherry-pick."));
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002382 }
2383
Johannes Schindelin968492e2017-01-02 16:35:46 +01002384 if (is_rebase_i(opts)) {
2385 struct todo_list done = TODO_LIST_INIT;
2386
2387 if (strbuf_read_file(&done.buf, rebase_path_done(), 0) > 0 &&
Alban Gruin5d94d542018-12-29 17:03:59 +01002388 !todo_list_parse_insn_buffer(r, done.buf.buf, &done))
Johannes Schindelin968492e2017-01-02 16:35:46 +01002389 todo_list->done_nr = count_commands(&done);
2390 else
2391 todo_list->done_nr = 0;
2392
2393 todo_list->total_nr = todo_list->done_nr
2394 + count_commands(todo_list);
Johannes Schindelin968492e2017-01-02 16:35:46 +01002395 todo_list_release(&done);
Johannes Schindelinef800692017-01-02 16:36:20 +01002396
Alban Gruin3f34f2d2019-11-24 18:43:30 +01002397 todo_list_write_total_nr(todo_list);
Johannes Schindelin968492e2017-01-02 16:35:46 +01002398 }
2399
Johannes Schindelin0ae42a02016-09-09 16:37:24 +02002400 return 0;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302401}
2402
Johannes Schindelin03a4e262016-10-21 14:24:13 +02002403static int git_config_string_dup(char **dest,
2404 const char *var, const char *value)
2405{
2406 if (!value)
2407 return config_error_nonbool(var);
2408 free(*dest);
2409 *dest = xstrdup(value);
2410 return 0;
2411}
2412
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302413static int populate_opts_cb(const char *key, const char *value, void *data)
2414{
2415 struct replay_opts *opts = data;
2416 int error_flag = 1;
2417
2418 if (!value)
2419 error_flag = 0;
2420 else if (!strcmp(key, "options.no-commit"))
2421 opts->no_commit = git_config_bool_or_int(key, value, &error_flag);
2422 else if (!strcmp(key, "options.edit"))
2423 opts->edit = git_config_bool_or_int(key, value, &error_flag);
Phillip Wood6860ce52019-03-13 18:26:15 +00002424 else if (!strcmp(key, "options.allow-empty"))
2425 opts->allow_empty =
2426 git_config_bool_or_int(key, value, &error_flag);
2427 else if (!strcmp(key, "options.allow-empty-message"))
2428 opts->allow_empty_message =
2429 git_config_bool_or_int(key, value, &error_flag);
2430 else if (!strcmp(key, "options.keep-redundant-commits"))
2431 opts->keep_redundant_commits =
2432 git_config_bool_or_int(key, value, &error_flag);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302433 else if (!strcmp(key, "options.signoff"))
2434 opts->signoff = git_config_bool_or_int(key, value, &error_flag);
2435 else if (!strcmp(key, "options.record-origin"))
2436 opts->record_origin = git_config_bool_or_int(key, value, &error_flag);
2437 else if (!strcmp(key, "options.allow-ff"))
2438 opts->allow_ff = git_config_bool_or_int(key, value, &error_flag);
2439 else if (!strcmp(key, "options.mainline"))
2440 opts->mainline = git_config_int(key, value);
2441 else if (!strcmp(key, "options.strategy"))
Johannes Schindelin03a4e262016-10-21 14:24:13 +02002442 git_config_string_dup(&opts->strategy, key, value);
Nicolas Vigier32535532014-01-24 00:50:58 +00002443 else if (!strcmp(key, "options.gpg-sign"))
Johannes Schindelin03a4e262016-10-21 14:24:13 +02002444 git_config_string_dup(&opts->gpg_sign, key, value);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302445 else if (!strcmp(key, "options.strategy-option")) {
2446 ALLOC_GROW(opts->xopts, opts->xopts_nr + 1, opts->xopts_alloc);
2447 opts->xopts[opts->xopts_nr++] = xstrdup(value);
Phillip Wood8d8cb4b2017-08-02 11:44:19 +01002448 } else if (!strcmp(key, "options.allow-rerere-auto"))
2449 opts->allow_rerere_auto =
2450 git_config_bool_or_int(key, value, &error_flag) ?
2451 RERERE_AUTOUPDATE : RERERE_NOAUTOUPDATE;
Phillip Wooddc42e9a2019-04-17 11:23:29 +01002452 else if (!strcmp(key, "options.default-msg-cleanup")) {
2453 opts->explicit_cleanup = 1;
2454 opts->default_msg_cleanup = get_cleanup_mode(value, 1);
2455 } else
Johannes Schindelin93b3df62016-10-21 14:26:25 +02002456 return error(_("invalid key: %s"), key);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302457
2458 if (!error_flag)
Johannes Schindelin93b3df62016-10-21 14:26:25 +02002459 return error(_("invalid value for %s: %s"), key, value);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302460
2461 return 0;
2462}
2463
Alban Gruin65850682018-08-28 14:10:40 +02002464void parse_strategy_opts(struct replay_opts *opts, char *raw_opts)
Johannes Schindelinca6c6b42017-01-02 16:28:30 +01002465{
2466 int i;
Alban Gruin65850682018-08-28 14:10:40 +02002467 char *strategy_opts_string = raw_opts;
Johannes Schindelinca6c6b42017-01-02 16:28:30 +01002468
Elijah Newren00600412018-06-27 08:48:04 -07002469 if (*strategy_opts_string == ' ')
2470 strategy_opts_string++;
Alban Gruin65850682018-08-28 14:10:40 +02002471
Elijah Newren00600412018-06-27 08:48:04 -07002472 opts->xopts_nr = split_cmdline(strategy_opts_string,
2473 (const char ***)&opts->xopts);
Johannes Schindelinca6c6b42017-01-02 16:28:30 +01002474 for (i = 0; i < opts->xopts_nr; i++) {
2475 const char *arg = opts->xopts[i];
2476
2477 skip_prefix(arg, "--", &arg);
2478 opts->xopts[i] = xstrdup(arg);
2479 }
2480}
2481
Alban Gruin65850682018-08-28 14:10:40 +02002482static void read_strategy_opts(struct replay_opts *opts, struct strbuf *buf)
2483{
2484 strbuf_reset(buf);
2485 if (!read_oneliner(buf, rebase_path_strategy(), 0))
2486 return;
2487 opts->strategy = strbuf_detach(buf, NULL);
2488 if (!read_oneliner(buf, rebase_path_strategy_opts(), 0))
2489 return;
2490
2491 parse_strategy_opts(opts, buf->buf);
2492}
2493
Johannes Schindelin5adf9bd2016-10-14 15:17:16 +02002494static int read_populate_opts(struct replay_opts *opts)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302495{
Johannes Schindelina1c75762016-10-21 14:25:12 +02002496 if (is_rebase_i(opts)) {
2497 struct strbuf buf = STRBUF_INIT;
Denton Liu65c425a2020-04-03 21:11:16 -04002498 int ret = 0;
Johannes Schindelina1c75762016-10-21 14:25:12 +02002499
Denton Liu3442c3d2020-04-07 10:27:52 -04002500 if (read_oneliner(&buf, rebase_path_gpg_sign_opt(),
2501 READ_ONELINER_SKIP_IF_EMPTY)) {
Johannes Schindelina1c75762016-10-21 14:25:12 +02002502 if (!starts_with(buf.buf, "-S"))
2503 strbuf_reset(&buf);
2504 else {
2505 free(opts->gpg_sign);
2506 opts->gpg_sign = xstrdup(buf.buf + 2);
2507 }
Phillip Wood9b6d7a62017-08-02 11:44:17 +01002508 strbuf_reset(&buf);
2509 }
2510
Denton Liu3442c3d2020-04-07 10:27:52 -04002511 if (read_oneliner(&buf, rebase_path_allow_rerere_autoupdate(),
2512 READ_ONELINER_SKIP_IF_EMPTY)) {
Phillip Wood9b6d7a62017-08-02 11:44:17 +01002513 if (!strcmp(buf.buf, "--rerere-autoupdate"))
2514 opts->allow_rerere_auto = RERERE_AUTOUPDATE;
2515 else if (!strcmp(buf.buf, "--no-rerere-autoupdate"))
2516 opts->allow_rerere_auto = RERERE_NOAUTOUPDATE;
2517 strbuf_reset(&buf);
Johannes Schindelina1c75762016-10-21 14:25:12 +02002518 }
Johannes Schindelina1c75762016-10-21 14:25:12 +02002519
Johannes Schindelin556907f2017-01-02 16:26:53 +01002520 if (file_exists(rebase_path_verbose()))
2521 opts->verbose = 1;
2522
Elijah Newren899b49c2018-12-11 08:11:36 -08002523 if (file_exists(rebase_path_quiet()))
2524 opts->quiet = 1;
2525
Phillip Wooda852ec72018-03-20 11:10:55 +00002526 if (file_exists(rebase_path_signoff())) {
2527 opts->allow_ff = 0;
2528 opts->signoff = 1;
2529 }
2530
Johannes Schindelind421afa2018-12-10 11:04:58 -08002531 if (file_exists(rebase_path_reschedule_failed_exec()))
2532 opts->reschedule_failed_exec = 1;
2533
Elijah Newrene98c4262020-02-15 21:36:25 +00002534 if (file_exists(rebase_path_drop_redundant_commits()))
2535 opts->drop_redundant_commits = 1;
2536
2537 if (file_exists(rebase_path_keep_redundant_commits()))
2538 opts->keep_redundant_commits = 1;
2539
Johannes Schindelinca6c6b42017-01-02 16:28:30 +01002540 read_strategy_opts(opts, &buf);
Denton Liu65c425a2020-04-03 21:11:16 -04002541 strbuf_reset(&buf);
Johannes Schindelinca6c6b42017-01-02 16:28:30 +01002542
Johannes Schindeline12a7ef2018-04-27 22:48:21 +02002543 if (read_oneliner(&opts->current_fixups,
Denton Liu3442c3d2020-04-07 10:27:52 -04002544 rebase_path_current_fixups(),
2545 READ_ONELINER_SKIP_IF_EMPTY)) {
Johannes Schindeline12a7ef2018-04-27 22:48:21 +02002546 const char *p = opts->current_fixups.buf;
2547 opts->current_fixup_count = 1;
2548 while ((p = strchr(p, '\n'))) {
2549 opts->current_fixup_count++;
2550 p++;
2551 }
2552 }
2553
Johannes Schindelind87d48b2018-05-04 01:01:17 +02002554 if (read_oneliner(&buf, rebase_path_squash_onto(), 0)) {
Denton Liu65c425a2020-04-03 21:11:16 -04002555 if (get_oid_hex(buf.buf, &opts->squash_onto) < 0) {
2556 ret = error(_("unusable squash-onto"));
2557 goto done_rebase_i;
2558 }
Johannes Schindelind87d48b2018-05-04 01:01:17 +02002559 opts->have_squash_onto = 1;
2560 }
2561
Denton Liu65c425a2020-04-03 21:11:16 -04002562done_rebase_i:
2563 strbuf_release(&buf);
2564 return ret;
Johannes Schindelina1c75762016-10-21 14:25:12 +02002565 }
Johannes Schindelinb5a67042016-10-21 14:25:04 +02002566
Jeff Kingf9327292015-08-10 05:38:57 -04002567 if (!file_exists(git_path_opts_file()))
Johannes Schindelin0d00da72016-09-09 16:37:27 +02002568 return 0;
2569 /*
2570 * The function git_parse_source(), called from git_config_from_file(),
2571 * may die() in case of a syntactically incorrect file. We do not care
2572 * about this case, though, because we wrote that file ourselves, so we
2573 * are pretty certain that it is syntactically correct.
2574 */
Johannes Schindelin5adf9bd2016-10-14 15:17:16 +02002575 if (git_config_from_file(populate_opts_cb, git_path_opts_file(), opts) < 0)
Johannes Schindelin93b3df62016-10-21 14:26:25 +02002576 return error(_("malformed options sheet: '%s'"),
Johannes Schindelin0d00da72016-09-09 16:37:27 +02002577 git_path_opts_file());
2578 return 0;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302579}
2580
Alban Gruin65850682018-08-28 14:10:40 +02002581static void write_strategy_opts(struct replay_opts *opts)
2582{
2583 int i;
2584 struct strbuf buf = STRBUF_INIT;
2585
2586 for (i = 0; i < opts->xopts_nr; ++i)
2587 strbuf_addf(&buf, " --%s", opts->xopts[i]);
2588
2589 write_file(rebase_path_strategy_opts(), "%s\n", buf.buf);
2590 strbuf_release(&buf);
2591}
2592
2593int write_basic_state(struct replay_opts *opts, const char *head_name,
Phillip Wood7d3488e2019-04-17 15:30:39 +01002594 struct commit *onto, const char *orig_head)
Alban Gruin65850682018-08-28 14:10:40 +02002595{
Alban Gruin65850682018-08-28 14:10:40 +02002596 if (head_name)
2597 write_file(rebase_path_head_name(), "%s\n", head_name);
2598 if (onto)
Phillip Wood7d3488e2019-04-17 15:30:39 +01002599 write_file(rebase_path_onto(), "%s\n",
2600 oid_to_hex(&onto->object.oid));
Alban Gruin65850682018-08-28 14:10:40 +02002601 if (orig_head)
2602 write_file(rebase_path_orig_head(), "%s\n", orig_head);
2603
Elijah Newren8a997ed2020-02-15 21:36:27 +00002604 if (opts->quiet)
2605 write_file(rebase_path_quiet(), "%s", "");
Alban Gruin65850682018-08-28 14:10:40 +02002606 if (opts->verbose)
Carlo Marcelo Arenas Belón4af51742018-10-25 02:38:54 -07002607 write_file(rebase_path_verbose(), "%s", "");
Alban Gruin65850682018-08-28 14:10:40 +02002608 if (opts->strategy)
2609 write_file(rebase_path_strategy(), "%s\n", opts->strategy);
2610 if (opts->xopts_nr > 0)
2611 write_strategy_opts(opts);
2612
2613 if (opts->allow_rerere_auto == RERERE_AUTOUPDATE)
2614 write_file(rebase_path_allow_rerere_autoupdate(), "--rerere-autoupdate\n");
2615 else if (opts->allow_rerere_auto == RERERE_NOAUTOUPDATE)
2616 write_file(rebase_path_allow_rerere_autoupdate(), "--no-rerere-autoupdate\n");
2617
2618 if (opts->gpg_sign)
2619 write_file(rebase_path_gpg_sign_opt(), "-S%s\n", opts->gpg_sign);
2620 if (opts->signoff)
2621 write_file(rebase_path_signoff(), "--signoff\n");
Elijah Newrene98c4262020-02-15 21:36:25 +00002622 if (opts->drop_redundant_commits)
2623 write_file(rebase_path_drop_redundant_commits(), "%s", "");
2624 if (opts->keep_redundant_commits)
2625 write_file(rebase_path_keep_redundant_commits(), "%s", "");
Johannes Schindelind421afa2018-12-10 11:04:58 -08002626 if (opts->reschedule_failed_exec)
2627 write_file(rebase_path_reschedule_failed_exec(), "%s", "");
Alban Gruin65850682018-08-28 14:10:40 +02002628
2629 return 0;
2630}
2631
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002632static int walk_revs_populate_todo(struct todo_list *todo_list,
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302633 struct replay_opts *opts)
2634{
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002635 enum todo_command command = opts->action == REPLAY_PICK ?
2636 TODO_PICK : TODO_REVERT;
Johannes Schindelin414697a2017-01-02 16:27:15 +01002637 const char *command_string = todo_command_info[command].str;
Doan Tran Cong Danh019a9d82019-11-08 16:43:47 +07002638 const char *encoding;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302639 struct commit *commit;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302640
Johannes Schindelin34b05282016-09-09 16:37:15 +02002641 if (prepare_revs(opts))
2642 return -1;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302643
Doan Tran Cong Danh019a9d82019-11-08 16:43:47 +07002644 encoding = get_log_output_encoding();
2645
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002646 while ((commit = get_revision(opts->revs))) {
2647 struct todo_item *item = append_new_todo(todo_list);
Doan Tran Cong Danh019a9d82019-11-08 16:43:47 +07002648 const char *commit_buffer = logmsg_reencode(commit, NULL, encoding);
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002649 const char *subject;
2650 int subject_len;
2651
2652 item->command = command;
2653 item->commit = commit;
Alban Gruin6ad656d2019-01-29 16:01:46 +01002654 item->arg_offset = 0;
Johannes Schindelinc22f7df2016-10-21 14:25:00 +02002655 item->arg_len = 0;
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002656 item->offset_in_buf = todo_list->buf.len;
2657 subject_len = find_commit_subject(commit_buffer, &subject);
2658 strbuf_addf(&todo_list->buf, "%s %s %.*s\n", command_string,
2659 short_commit_name(commit), subject_len, subject);
2660 unuse_commit_buffer(commit, commit_buffer);
2661 }
Jeff King8530c732018-07-09 15:48:19 -04002662
2663 if (!todo_list->nr)
2664 return error(_("empty commit set passed"));
2665
Johannes Schindelin34b05282016-09-09 16:37:15 +02002666 return 0;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302667}
2668
Rohit Ashiwal6a1f9042019-07-02 14:41:25 +05302669static int create_seq_dir(struct repository *r)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302670{
Rohit Ashiwal6a1f9042019-07-02 14:41:25 +05302671 enum replay_action action;
2672 const char *in_progress_error = NULL;
2673 const char *in_progress_advice = NULL;
Rohit Ashiwaldcb500d2019-07-02 14:41:29 +05302674 unsigned int advise_skip = file_exists(git_path_revert_head(r)) ||
2675 file_exists(git_path_cherry_pick_head(r));
Rohit Ashiwal6a1f9042019-07-02 14:41:25 +05302676
2677 if (!sequencer_get_last_command(r, &action)) {
2678 switch (action) {
2679 case REPLAY_REVERT:
2680 in_progress_error = _("revert is already in progress");
2681 in_progress_advice =
Rohit Ashiwaldcb500d2019-07-02 14:41:29 +05302682 _("try \"git revert (--continue | %s--abort | --quit)\"");
Rohit Ashiwal6a1f9042019-07-02 14:41:25 +05302683 break;
2684 case REPLAY_PICK:
2685 in_progress_error = _("cherry-pick is already in progress");
2686 in_progress_advice =
Rohit Ashiwaldcb500d2019-07-02 14:41:29 +05302687 _("try \"git cherry-pick (--continue | %s--abort | --quit)\"");
Rohit Ashiwal6a1f9042019-07-02 14:41:25 +05302688 break;
2689 default:
2690 BUG("unexpected action in create_seq_dir");
2691 }
2692 }
2693 if (in_progress_error) {
2694 error("%s", in_progress_error);
2695 if (advice_sequencer_in_use)
Rohit Ashiwaldcb500d2019-07-02 14:41:29 +05302696 advise(in_progress_advice,
2697 advise_skip ? "--skip | " : "");
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302698 return -1;
Rohit Ashiwal6a1f9042019-07-02 14:41:25 +05302699 }
2700 if (mkdir(git_path_seq_dir(), 0777) < 0)
Johannes Schindelin93b3df62016-10-21 14:26:25 +02002701 return error_errno(_("could not create sequencer directory '%s'"),
Johannes Schindelinf6e82b02016-09-09 16:37:44 +02002702 git_path_seq_dir());
Rohit Ashiwal6a1f9042019-07-02 14:41:25 +05302703
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302704 return 0;
2705}
2706
Johannes Schindelin311fd392016-09-09 16:37:47 +02002707static int save_head(const char *head)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302708{
Martin Ågren14bca6c2018-02-27 22:30:09 +01002709 struct lock_file head_lock = LOCK_INIT;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302710 struct strbuf buf = STRBUF_INIT;
2711 int fd;
Rene Scharfeed3f9a12017-08-30 20:20:14 +02002712 ssize_t written;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302713
Johannes Schindelin311fd392016-09-09 16:37:47 +02002714 fd = hold_lock_file_for_update(&head_lock, git_path_head_file(), 0);
Martin Ågren350292a2018-02-28 20:07:58 +01002715 if (fd < 0)
Johannes Schindelin93b3df62016-10-21 14:26:25 +02002716 return error_errno(_("could not lock HEAD"));
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302717 strbuf_addf(&buf, "%s\n", head);
Rene Scharfeed3f9a12017-08-30 20:20:14 +02002718 written = write_in_full(fd, buf.buf, buf.len);
2719 strbuf_release(&buf);
2720 if (written < 0) {
Johannes Schindelinbf5c0572018-04-25 14:28:17 +02002721 error_errno(_("could not write to '%s'"), git_path_head_file());
Johannes Schindelin311fd392016-09-09 16:37:47 +02002722 rollback_lock_file(&head_lock);
Johannes Schindelinbf5c0572018-04-25 14:28:17 +02002723 return -1;
Johannes Schindelin311fd392016-09-09 16:37:47 +02002724 }
Martin Ågren350292a2018-02-28 20:07:58 +01002725 if (commit_lock_file(&head_lock) < 0)
2726 return error(_("failed to finalize '%s'"), git_path_head_file());
Johannes Schindelin311fd392016-09-09 16:37:47 +02002727 return 0;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302728}
2729
Stephan Beyer1e412292016-12-07 22:51:32 +01002730static int rollback_is_safe(void)
2731{
2732 struct strbuf sb = STRBUF_INIT;
2733 struct object_id expected_head, actual_head;
2734
2735 if (strbuf_read_file(&sb, git_path_abort_safety_file(), 0) >= 0) {
2736 strbuf_trim(&sb);
2737 if (get_oid_hex(sb.buf, &expected_head)) {
2738 strbuf_release(&sb);
2739 die(_("could not parse %s"), git_path_abort_safety_file());
2740 }
2741 strbuf_release(&sb);
2742 }
2743 else if (errno == ENOENT)
2744 oidclr(&expected_head);
2745 else
2746 die_errno(_("could not read '%s'"), git_path_abort_safety_file());
2747
2748 if (get_oid("HEAD", &actual_head))
2749 oidclr(&actual_head);
2750
Jeff King4a7e27e2018-08-28 17:22:40 -04002751 return oideq(&actual_head, &expected_head);
Stephan Beyer1e412292016-12-07 22:51:32 +01002752}
2753
Rohit Ashiwal918d1e62019-07-02 14:41:26 +05302754static int reset_merge(const struct object_id *oid)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302755{
Rohit Ashiwal265ab482019-07-02 14:41:27 +05302756 int ret;
2757 struct argv_array argv = ARGV_ARRAY_INIT;
Stephan Beyer1e412292016-12-07 22:51:32 +01002758
Rohit Ashiwal265ab482019-07-02 14:41:27 +05302759 argv_array_pushl(&argv, "reset", "--merge", NULL);
2760
2761 if (!is_null_oid(oid))
2762 argv_array_push(&argv, oid_to_hex(oid));
2763
2764 ret = run_command_v_opt(argv.argv, RUN_GIT_CMD);
2765 argv_array_clear(&argv);
2766
2767 return ret;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302768}
2769
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01002770static int rollback_single_pick(struct repository *r)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302771{
brian m. carlson092bbcd2017-07-13 23:49:22 +00002772 struct object_id head_oid;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302773
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01002774 if (!file_exists(git_path_cherry_pick_head(r)) &&
2775 !file_exists(git_path_revert_head(r)))
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302776 return error(_("no cherry-pick or revert in progress"));
brian m. carlson34c290a2017-10-15 22:06:56 +00002777 if (read_ref_full("HEAD", 0, &head_oid, NULL))
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302778 return error(_("cannot resolve HEAD"));
brian m. carlson092bbcd2017-07-13 23:49:22 +00002779 if (is_null_oid(&head_oid))
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302780 return error(_("cannot abort from a branch yet to be born"));
Rohit Ashiwal918d1e62019-07-02 14:41:26 +05302781 return reset_merge(&head_oid);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302782}
2783
Rohit Ashiwalde81ca32019-07-02 14:41:28 +05302784static int skip_single_pick(void)
2785{
2786 struct object_id head;
2787
2788 if (read_ref_full("HEAD", 0, &head, NULL))
2789 return error(_("cannot resolve HEAD"));
2790 return reset_merge(&head);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302791}
2792
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01002793int sequencer_rollback(struct repository *r, struct replay_opts *opts)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302794{
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302795 FILE *f;
brian m. carlson092bbcd2017-07-13 23:49:22 +00002796 struct object_id oid;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302797 struct strbuf buf = STRBUF_INIT;
brian m. carlson092bbcd2017-07-13 23:49:22 +00002798 const char *p;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302799
Jeff Kingf9327292015-08-10 05:38:57 -04002800 f = fopen(git_path_head_file(), "r");
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302801 if (!f && errno == ENOENT) {
2802 /*
2803 * There is no multiple-cherry-pick in progress.
2804 * If CHERRY_PICK_HEAD or REVERT_HEAD indicates
2805 * a single-cherry-pick in progress, abort that.
2806 */
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01002807 return rollback_single_pick(r);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302808 }
2809 if (!f)
Johannes Schindelinf7ed1952016-10-21 14:26:21 +02002810 return error_errno(_("cannot open '%s'"), git_path_head_file());
Junio C Hamano8f309ae2016-01-13 15:31:17 -08002811 if (strbuf_getline_lf(&buf, f)) {
Johannes Schindelinf7ed1952016-10-21 14:26:21 +02002812 error(_("cannot read '%s': %s"), git_path_head_file(),
Jeff Kingf9327292015-08-10 05:38:57 -04002813 ferror(f) ? strerror(errno) : _("unexpected end of file"));
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302814 fclose(f);
2815 goto fail;
2816 }
2817 fclose(f);
brian m. carlson092bbcd2017-07-13 23:49:22 +00002818 if (parse_oid_hex(buf.buf, &oid, &p) || *p != '\0') {
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302819 error(_("stored pre-cherry-pick HEAD file '%s' is corrupt"),
Jeff Kingf9327292015-08-10 05:38:57 -04002820 git_path_head_file());
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302821 goto fail;
2822 }
brian m. carlson092bbcd2017-07-13 23:49:22 +00002823 if (is_null_oid(&oid)) {
Michael J Gruber0f974e22016-06-06 15:23:54 +02002824 error(_("cannot abort from a branch yet to be born"));
2825 goto fail;
2826 }
Stephan Beyer1e412292016-12-07 22:51:32 +01002827
2828 if (!rollback_is_safe()) {
2829 /* Do not error, just do not rollback */
2830 warning(_("You seem to have moved HEAD. "
2831 "Not rewinding, check your HEAD!"));
2832 } else
Rohit Ashiwal918d1e62019-07-02 14:41:26 +05302833 if (reset_merge(&oid))
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302834 goto fail;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302835 strbuf_release(&buf);
Johannes Schindelin28635842016-10-21 14:24:55 +02002836 return sequencer_remove_state(opts);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302837fail:
2838 strbuf_release(&buf);
2839 return -1;
2840}
2841
Rohit Ashiwalde81ca32019-07-02 14:41:28 +05302842int sequencer_skip(struct repository *r, struct replay_opts *opts)
2843{
2844 enum replay_action action = -1;
2845 sequencer_get_last_command(r, &action);
2846
2847 /*
2848 * Check whether the subcommand requested to skip the commit is actually
2849 * in progress and that it's safe to skip the commit.
2850 *
2851 * opts->action tells us which subcommand requested to skip the commit.
2852 * If the corresponding .git/<ACTION>_HEAD exists, we know that the
2853 * action is in progress and we can skip the commit.
2854 *
2855 * Otherwise we check that the last instruction was related to the
2856 * particular subcommand we're trying to execute and barf if that's not
2857 * the case.
2858 *
2859 * Finally we check that the rollback is "safe", i.e., has the HEAD
2860 * moved? In this case, it doesn't make sense to "reset the merge" and
2861 * "skip the commit" as the user already handled this by committing. But
2862 * we'd not want to barf here, instead give advice on how to proceed. We
2863 * only need to check that when .git/<ACTION>_HEAD doesn't exist because
2864 * it gets removed when the user commits, so if it still exists we're
2865 * sure the user can't have committed before.
2866 */
2867 switch (opts->action) {
2868 case REPLAY_REVERT:
2869 if (!file_exists(git_path_revert_head(r))) {
2870 if (action != REPLAY_REVERT)
2871 return error(_("no revert in progress"));
2872 if (!rollback_is_safe())
2873 goto give_advice;
2874 }
2875 break;
2876 case REPLAY_PICK:
2877 if (!file_exists(git_path_cherry_pick_head(r))) {
2878 if (action != REPLAY_PICK)
2879 return error(_("no cherry-pick in progress"));
2880 if (!rollback_is_safe())
2881 goto give_advice;
2882 }
2883 break;
2884 default:
2885 BUG("unexpected action in sequencer_skip");
2886 }
2887
2888 if (skip_single_pick())
2889 return error(_("failed to skip the commit"));
2890 if (!is_directory(git_path_seq_dir()))
2891 return 0;
2892
2893 return sequencer_continue(r, opts);
2894
2895give_advice:
2896 error(_("there is nothing to skip"));
2897
2898 if (advice_resolve_conflict) {
2899 advise(_("have you committed already?\n"
2900 "try \"git %s --continue\""),
2901 action == REPLAY_REVERT ? "revert" : "cherry-pick");
2902 }
2903 return -1;
2904}
2905
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002906static int save_todo(struct todo_list *todo_list, struct replay_opts *opts)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302907{
Martin Ågren14bca6c2018-02-27 22:30:09 +01002908 struct lock_file todo_lock = LOCK_INIT;
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002909 const char *todo_path = get_todo_path(opts);
2910 int next = todo_list->current, offset, fd;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302911
Johannes Schindelin84583952017-01-02 16:26:28 +01002912 /*
2913 * rebase -i writes "git-rebase-todo" without the currently executing
2914 * command, appending it to "done" instead.
2915 */
2916 if (is_rebase_i(opts))
2917 next++;
2918
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002919 fd = hold_lock_file_for_update(&todo_lock, todo_path, 0);
Johannes Schindelin221675d2016-09-09 16:37:50 +02002920 if (fd < 0)
Johannes Schindelin93b3df62016-10-21 14:26:25 +02002921 return error_errno(_("could not lock '%s'"), todo_path);
Johannes Schindelina01c2a52018-04-25 14:28:29 +02002922 offset = get_item_line_offset(todo_list, next);
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002923 if (write_in_full(fd, todo_list->buf.buf + offset,
2924 todo_list->buf.len - offset) < 0)
Johannes Schindelin93b3df62016-10-21 14:26:25 +02002925 return error_errno(_("could not write to '%s'"), todo_path);
Johannes Schindelin004fefa2016-10-21 14:24:41 +02002926 if (commit_lock_file(&todo_lock) < 0)
Martin Ågren350292a2018-02-28 20:07:58 +01002927 return error(_("failed to finalize '%s'"), todo_path);
Johannes Schindelin1df6df02017-01-02 16:27:00 +01002928
Johannes Schindelina01c2a52018-04-25 14:28:29 +02002929 if (is_rebase_i(opts) && next > 0) {
2930 const char *done = rebase_path_done();
2931 int fd = open(done, O_CREAT | O_WRONLY | O_APPEND, 0666);
2932 int ret = 0;
Johannes Schindelin1df6df02017-01-02 16:27:00 +01002933
Johannes Schindelina01c2a52018-04-25 14:28:29 +02002934 if (fd < 0)
2935 return 0;
2936 if (write_in_full(fd, get_item_line(todo_list, next - 1),
2937 get_item_line_length(todo_list, next - 1))
2938 < 0)
2939 ret = error_errno(_("could not write to '%s'"), done);
2940 if (close(fd) < 0)
2941 ret = error_errno(_("failed to finalize '%s'"), done);
2942 return ret;
Johannes Schindelin1df6df02017-01-02 16:27:00 +01002943 }
Johannes Schindelin221675d2016-09-09 16:37:50 +02002944 return 0;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302945}
2946
Johannes Schindelin88d5a272016-09-09 16:37:53 +02002947static int save_opts(struct replay_opts *opts)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302948{
Jeff Kingf9327292015-08-10 05:38:57 -04002949 const char *opts_file = git_path_opts_file();
Johannes Schindelin88d5a272016-09-09 16:37:53 +02002950 int res = 0;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302951
2952 if (opts->no_commit)
Phillip Woodf59199d2019-03-13 18:26:13 +00002953 res |= git_config_set_in_file_gently(opts_file,
2954 "options.no-commit", "true");
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302955 if (opts->edit)
Phillip Woodf59199d2019-03-13 18:26:13 +00002956 res |= git_config_set_in_file_gently(opts_file,
2957 "options.edit", "true");
Phillip Wood6860ce52019-03-13 18:26:15 +00002958 if (opts->allow_empty)
2959 res |= git_config_set_in_file_gently(opts_file,
2960 "options.allow-empty", "true");
2961 if (opts->allow_empty_message)
2962 res |= git_config_set_in_file_gently(opts_file,
2963 "options.allow-empty-message", "true");
2964 if (opts->keep_redundant_commits)
2965 res |= git_config_set_in_file_gently(opts_file,
2966 "options.keep-redundant-commits", "true");
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302967 if (opts->signoff)
Phillip Woodf59199d2019-03-13 18:26:13 +00002968 res |= git_config_set_in_file_gently(opts_file,
2969 "options.signoff", "true");
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302970 if (opts->record_origin)
Phillip Woodf59199d2019-03-13 18:26:13 +00002971 res |= git_config_set_in_file_gently(opts_file,
2972 "options.record-origin", "true");
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302973 if (opts->allow_ff)
Phillip Woodf59199d2019-03-13 18:26:13 +00002974 res |= git_config_set_in_file_gently(opts_file,
2975 "options.allow-ff", "true");
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302976 if (opts->mainline) {
2977 struct strbuf buf = STRBUF_INIT;
2978 strbuf_addf(&buf, "%d", opts->mainline);
Phillip Woodf59199d2019-03-13 18:26:13 +00002979 res |= git_config_set_in_file_gently(opts_file,
2980 "options.mainline", buf.buf);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302981 strbuf_release(&buf);
2982 }
2983 if (opts->strategy)
Phillip Woodf59199d2019-03-13 18:26:13 +00002984 res |= git_config_set_in_file_gently(opts_file,
2985 "options.strategy", opts->strategy);
Nicolas Vigier32535532014-01-24 00:50:58 +00002986 if (opts->gpg_sign)
Phillip Woodf59199d2019-03-13 18:26:13 +00002987 res |= git_config_set_in_file_gently(opts_file,
2988 "options.gpg-sign", opts->gpg_sign);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302989 if (opts->xopts) {
2990 int i;
2991 for (i = 0; i < opts->xopts_nr; i++)
Johannes Schindelin88d5a272016-09-09 16:37:53 +02002992 res |= git_config_set_multivar_in_file_gently(opts_file,
Phillip Woodf59199d2019-03-13 18:26:13 +00002993 "options.strategy-option",
2994 opts->xopts[i], "^$", 0);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05302995 }
Phillip Wood8d8cb4b2017-08-02 11:44:19 +01002996 if (opts->allow_rerere_auto)
Phillip Woodf59199d2019-03-13 18:26:13 +00002997 res |= git_config_set_in_file_gently(opts_file,
2998 "options.allow-rerere-auto",
2999 opts->allow_rerere_auto == RERERE_AUTOUPDATE ?
3000 "true" : "false");
Phillip Wooddc42e9a2019-04-17 11:23:29 +01003001
3002 if (opts->explicit_cleanup)
3003 res |= git_config_set_in_file_gently(opts_file,
3004 "options.default-msg-cleanup",
3005 describe_cleanup_mode(opts->default_msg_cleanup));
Johannes Schindelin88d5a272016-09-09 16:37:53 +02003006 return res;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05303007}
3008
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003009static int make_patch(struct repository *r,
3010 struct commit *commit,
3011 struct replay_opts *opts)
Johannes Schindelin56dc3ab2017-01-02 16:26:43 +01003012{
3013 struct strbuf buf = STRBUF_INIT;
3014 struct rev_info log_tree_opt;
3015 const char *subject, *p;
3016 int res = 0;
3017
3018 p = short_commit_name(commit);
3019 if (write_message(p, strlen(p), rebase_path_stopped_sha(), 1) < 0)
3020 return -1;
Phillip Wood430b75f2019-12-06 16:06:12 +00003021 res |= write_rebase_head(&commit->object.oid);
Johannes Schindelin56dc3ab2017-01-02 16:26:43 +01003022
3023 strbuf_addf(&buf, "%s/patch", get_dir(opts));
3024 memset(&log_tree_opt, 0, sizeof(log_tree_opt));
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003025 repo_init_revisions(r, &log_tree_opt, NULL);
Johannes Schindelin56dc3ab2017-01-02 16:26:43 +01003026 log_tree_opt.abbrev = 0;
3027 log_tree_opt.diff = 1;
3028 log_tree_opt.diffopt.output_format = DIFF_FORMAT_PATCH;
3029 log_tree_opt.disable_stdin = 1;
3030 log_tree_opt.no_commit_id = 1;
3031 log_tree_opt.diffopt.file = fopen(buf.buf, "w");
3032 log_tree_opt.diffopt.use_color = GIT_COLOR_NEVER;
3033 if (!log_tree_opt.diffopt.file)
3034 res |= error_errno(_("could not open '%s'"), buf.buf);
3035 else {
3036 res |= log_tree_commit(&log_tree_opt, commit);
3037 fclose(log_tree_opt.diffopt.file);
3038 }
3039 strbuf_reset(&buf);
3040
3041 strbuf_addf(&buf, "%s/message", get_dir(opts));
3042 if (!file_exists(buf.buf)) {
Doan Tran Cong Danh52f52e52019-11-11 13:03:41 +07003043 const char *encoding = get_commit_output_encoding();
3044 const char *commit_buffer = logmsg_reencode(commit, NULL, encoding);
Johannes Schindelin56dc3ab2017-01-02 16:26:43 +01003045 find_commit_subject(commit_buffer, &subject);
3046 res |= write_message(subject, strlen(subject), buf.buf, 1);
3047 unuse_commit_buffer(commit, commit_buffer);
3048 }
3049 strbuf_release(&buf);
3050
3051 return res;
3052}
3053
3054static int intend_to_amend(void)
3055{
brian m. carlson092bbcd2017-07-13 23:49:22 +00003056 struct object_id head;
Johannes Schindelin56dc3ab2017-01-02 16:26:43 +01003057 char *p;
3058
brian m. carlson092bbcd2017-07-13 23:49:22 +00003059 if (get_oid("HEAD", &head))
Johannes Schindelin56dc3ab2017-01-02 16:26:43 +01003060 return error(_("cannot read HEAD"));
3061
brian m. carlson092bbcd2017-07-13 23:49:22 +00003062 p = oid_to_hex(&head);
Johannes Schindelin56dc3ab2017-01-02 16:26:43 +01003063 return write_message(p, strlen(p), rebase_path_amend(), 1);
3064}
3065
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003066static int error_with_patch(struct repository *r,
3067 struct commit *commit,
3068 const char *subject, int subject_len,
3069 struct replay_opts *opts,
3070 int exit_code, int to_amend)
Johannes Schindelin56dc3ab2017-01-02 16:26:43 +01003071{
Phillip Woodbc9238b2018-08-15 10:39:35 +01003072 if (commit) {
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003073 if (make_patch(r, commit, opts))
Phillip Woodbc9238b2018-08-15 10:39:35 +01003074 return -1;
Junio C Hamano5a5c5e92018-08-20 12:41:33 -07003075 } else if (copy_file(rebase_path_message(),
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003076 git_path_merge_msg(r), 0666))
Phillip Woodbc9238b2018-08-15 10:39:35 +01003077 return error(_("unable to copy '%s' to '%s'"),
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003078 git_path_merge_msg(r), rebase_path_message());
Johannes Schindelin56dc3ab2017-01-02 16:26:43 +01003079
3080 if (to_amend) {
3081 if (intend_to_amend())
3082 return -1;
3083
Nguyễn Thái Ngọc Duy02127c62018-07-21 09:49:38 +02003084 fprintf(stderr,
3085 _("You can amend the commit now, with\n"
3086 "\n"
3087 " git commit --amend %s\n"
3088 "\n"
3089 "Once you are satisfied with your changes, run\n"
3090 "\n"
3091 " git rebase --continue\n"),
3092 gpg_sign_opt_quoted(opts));
Phillip Woodbc9238b2018-08-15 10:39:35 +01003093 } else if (exit_code) {
3094 if (commit)
Junio C Hamano5a5c5e92018-08-20 12:41:33 -07003095 fprintf_ln(stderr, _("Could not apply %s... %.*s"),
3096 short_commit_name(commit), subject_len, subject);
Phillip Woodbc9238b2018-08-15 10:39:35 +01003097 else
3098 /*
3099 * We don't have the hash of the parent so
3100 * just print the line from the todo file.
3101 */
Junio C Hamano5a5c5e92018-08-20 12:41:33 -07003102 fprintf_ln(stderr, _("Could not merge %.*s"),
3103 subject_len, subject);
Phillip Woodbc9238b2018-08-15 10:39:35 +01003104 }
Johannes Schindelin56dc3ab2017-01-02 16:26:43 +01003105
3106 return exit_code;
3107}
3108
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003109static int error_failed_squash(struct repository *r,
3110 struct commit *commit,
3111 struct replay_opts *opts,
3112 int subject_len,
3113 const char *subject)
Johannes Schindelin6e98de72017-01-02 16:27:07 +01003114{
Johannes Schindeline12a7ef2018-04-27 22:48:21 +02003115 if (copy_file(rebase_path_message(), rebase_path_squash_msg(), 0666))
3116 return error(_("could not copy '%s' to '%s'"),
Johannes Schindelin6e98de72017-01-02 16:27:07 +01003117 rebase_path_squash_msg(), rebase_path_message());
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003118 unlink(git_path_merge_msg(r));
3119 if (copy_file(git_path_merge_msg(r), rebase_path_message(), 0666))
Johannes Schindelin6e98de72017-01-02 16:27:07 +01003120 return error(_("could not copy '%s' to '%s'"),
Stefan Beller102de882018-05-17 15:51:51 -07003121 rebase_path_message(),
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003122 git_path_merge_msg(r));
3123 return error_with_patch(r, commit, subject, subject_len, opts, 1, 0);
Johannes Schindelin6e98de72017-01-02 16:27:07 +01003124}
3125
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003126static int do_exec(struct repository *r, const char *command_line)
Johannes Schindelin311af522017-01-02 16:26:47 +01003127{
Jacob Keller09d7b6c2017-10-31 16:07:33 -07003128 struct argv_array child_env = ARGV_ARRAY_INIT;
Johannes Schindelin311af522017-01-02 16:26:47 +01003129 const char *child_argv[] = { NULL, NULL };
3130 int dirty, status;
3131
Alban Gruin4d55d632020-03-28 14:05:15 +01003132 fprintf(stderr, _("Executing: %s\n"), command_line);
Johannes Schindelin311af522017-01-02 16:26:47 +01003133 child_argv[0] = command_line;
Jacob Keller09d7b6c2017-10-31 16:07:33 -07003134 argv_array_pushf(&child_env, "GIT_DIR=%s", absolute_path(get_git_dir()));
brian m. carlsonab5e67d2018-07-14 18:38:59 +00003135 argv_array_pushf(&child_env, "GIT_WORK_TREE=%s",
3136 absolute_path(get_git_work_tree()));
Jacob Keller09d7b6c2017-10-31 16:07:33 -07003137 status = run_command_v_opt_cd_env(child_argv, RUN_USING_SHELL, NULL,
3138 child_env.argv);
Johannes Schindelin311af522017-01-02 16:26:47 +01003139
3140 /* force re-reading of the cache */
Nguyễn Thái Ngọc Duye1ff0a32019-01-12 09:13:26 +07003141 if (discard_index(r->index) < 0 || repo_read_index(r) < 0)
Johannes Schindelin311af522017-01-02 16:26:47 +01003142 return error(_("could not read index"));
3143
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003144 dirty = require_clean_work_tree(r, "rebase", NULL, 1, 1);
Johannes Schindelin311af522017-01-02 16:26:47 +01003145
3146 if (status) {
3147 warning(_("execution failed: %s\n%s"
3148 "You can fix the problem, and then run\n"
3149 "\n"
3150 " git rebase --continue\n"
3151 "\n"),
3152 command_line,
3153 dirty ? N_("and made changes to the index and/or the "
3154 "working tree\n") : "");
3155 if (status == 127)
3156 /* command not found */
3157 status = 1;
3158 } else if (dirty) {
3159 warning(_("execution succeeded: %s\nbut "
3160 "left changes to the index and/or the working tree\n"
3161 "Commit or stash your changes, and then run\n"
3162 "\n"
3163 " git rebase --continue\n"
3164 "\n"), command_line);
3165 status = 1;
3166 }
3167
Jacob Keller09d7b6c2017-10-31 16:07:33 -07003168 argv_array_clear(&child_env);
3169
Johannes Schindelin311af522017-01-02 16:26:47 +01003170 return status;
3171}
3172
Johannes Schindelin9055e402018-04-25 14:28:47 +02003173static int safe_append(const char *filename, const char *fmt, ...)
3174{
3175 va_list ap;
3176 struct lock_file lock = LOCK_INIT;
3177 int fd = hold_lock_file_for_update(&lock, filename,
3178 LOCK_REPORT_ON_ERROR);
3179 struct strbuf buf = STRBUF_INIT;
3180
3181 if (fd < 0)
3182 return -1;
3183
3184 if (strbuf_read_file(&buf, filename, 0) < 0 && errno != ENOENT) {
3185 error_errno(_("could not read '%s'"), filename);
3186 rollback_lock_file(&lock);
3187 return -1;
3188 }
3189 strbuf_complete(&buf, '\n');
3190 va_start(ap, fmt);
3191 strbuf_vaddf(&buf, fmt, ap);
3192 va_end(ap);
3193
3194 if (write_in_full(fd, buf.buf, buf.len) < 0) {
3195 error_errno(_("could not write to '%s'"), filename);
3196 strbuf_release(&buf);
3197 rollback_lock_file(&lock);
3198 return -1;
3199 }
3200 if (commit_lock_file(&lock) < 0) {
3201 strbuf_release(&buf);
3202 rollback_lock_file(&lock);
3203 return error(_("failed to finalize '%s'"), filename);
3204 }
3205
3206 strbuf_release(&buf);
3207 return 0;
3208}
3209
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003210static int do_label(struct repository *r, const char *name, int len)
Johannes Schindelin9055e402018-04-25 14:28:47 +02003211{
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003212 struct ref_store *refs = get_main_ref_store(r);
Johannes Schindelin9055e402018-04-25 14:28:47 +02003213 struct ref_transaction *transaction;
3214 struct strbuf ref_name = STRBUF_INIT, err = STRBUF_INIT;
3215 struct strbuf msg = STRBUF_INIT;
3216 int ret = 0;
3217 struct object_id head_oid;
3218
3219 if (len == 1 && *name == '#')
Nguyễn Thái Ngọc Duy02127c62018-07-21 09:49:38 +02003220 return error(_("illegal label name: '%.*s'"), len, name);
Johannes Schindelin9055e402018-04-25 14:28:47 +02003221
3222 strbuf_addf(&ref_name, "refs/rewritten/%.*s", len, name);
Elijah Newrenc2417d32020-02-15 21:36:36 +00003223 strbuf_addf(&msg, "rebase (label) '%.*s'", len, name);
Johannes Schindelin9055e402018-04-25 14:28:47 +02003224
3225 transaction = ref_store_transaction_begin(refs, &err);
3226 if (!transaction) {
3227 error("%s", err.buf);
3228 ret = -1;
3229 } else if (get_oid("HEAD", &head_oid)) {
3230 error(_("could not read HEAD"));
3231 ret = -1;
3232 } else if (ref_transaction_update(transaction, ref_name.buf, &head_oid,
3233 NULL, 0, msg.buf, &err) < 0 ||
3234 ref_transaction_commit(transaction, &err)) {
3235 error("%s", err.buf);
3236 ret = -1;
3237 }
3238 ref_transaction_free(transaction);
3239 strbuf_release(&err);
3240 strbuf_release(&msg);
3241
3242 if (!ret)
3243 ret = safe_append(rebase_path_refs_to_delete(),
3244 "%s\n", ref_name.buf);
3245 strbuf_release(&ref_name);
3246
3247 return ret;
3248}
3249
3250static const char *reflog_message(struct replay_opts *opts,
3251 const char *sub_action, const char *fmt, ...);
3252
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003253static int do_reset(struct repository *r,
3254 const char *name, int len,
3255 struct replay_opts *opts)
Johannes Schindelin9055e402018-04-25 14:28:47 +02003256{
3257 struct strbuf ref_name = STRBUF_INIT;
3258 struct object_id oid;
3259 struct lock_file lock = LOCK_INIT;
3260 struct tree_desc desc;
3261 struct tree *tree;
3262 struct unpack_trees_options unpack_tree_opts;
Martin Ågren71571cd2018-10-30 09:09:37 +01003263 int ret = 0;
Johannes Schindelin9055e402018-04-25 14:28:47 +02003264
Nguyễn Thái Ngọc Duy3a95f312019-01-12 09:13:24 +07003265 if (repo_hold_locked_index(r, &lock, LOCK_REPORT_ON_ERROR) < 0)
Johannes Schindelin9055e402018-04-25 14:28:47 +02003266 return -1;
3267
Johannes Schindelinebddf392018-05-04 01:01:23 +02003268 if (len == 10 && !strncmp("[new root]", name, len)) {
3269 if (!opts->have_squash_onto) {
3270 const char *hex;
3271 if (commit_tree("", 0, the_hash_algo->empty_tree,
3272 NULL, &opts->squash_onto,
3273 NULL, NULL))
3274 return error(_("writing fake root commit"));
3275 opts->have_squash_onto = 1;
3276 hex = oid_to_hex(&opts->squash_onto);
3277 if (write_message(hex, strlen(hex),
3278 rebase_path_squash_onto(), 0))
3279 return error(_("writing squash-onto"));
3280 }
3281 oidcpy(&oid, &opts->squash_onto);
3282 } else {
Martin Ågren71571cd2018-10-30 09:09:37 +01003283 int i;
3284
Johannes Schindelinebddf392018-05-04 01:01:23 +02003285 /* Determine the length of the label */
3286 for (i = 0; i < len; i++)
3287 if (isspace(name[i]))
Martin Ågren71571cd2018-10-30 09:09:37 +01003288 break;
3289 len = i;
Johannes Schindelin9055e402018-04-25 14:28:47 +02003290
Johannes Schindelinebddf392018-05-04 01:01:23 +02003291 strbuf_addf(&ref_name, "refs/rewritten/%.*s", len, name);
3292 if (get_oid(ref_name.buf, &oid) &&
3293 get_oid(ref_name.buf + strlen("refs/rewritten/"), &oid)) {
3294 error(_("could not read '%s'"), ref_name.buf);
3295 rollback_lock_file(&lock);
3296 strbuf_release(&ref_name);
3297 return -1;
3298 }
Johannes Schindelin9055e402018-04-25 14:28:47 +02003299 }
3300
3301 memset(&unpack_tree_opts, 0, sizeof(unpack_tree_opts));
3302 setup_unpack_trees_porcelain(&unpack_tree_opts, "reset");
3303 unpack_tree_opts.head_idx = 1;
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003304 unpack_tree_opts.src_index = r->index;
3305 unpack_tree_opts.dst_index = r->index;
Johannes Schindelin9055e402018-04-25 14:28:47 +02003306 unpack_tree_opts.fn = oneway_merge;
3307 unpack_tree_opts.merge = 1;
3308 unpack_tree_opts.update = 1;
brian m. carlson3f267852020-03-16 18:05:06 +00003309 init_checkout_metadata(&unpack_tree_opts.meta, name, &oid, NULL);
Johannes Schindelin9055e402018-04-25 14:28:47 +02003310
Nguyễn Thái Ngọc Duye1ff0a32019-01-12 09:13:26 +07003311 if (repo_read_index_unmerged(r)) {
Johannes Schindelin9055e402018-04-25 14:28:47 +02003312 rollback_lock_file(&lock);
3313 strbuf_release(&ref_name);
3314 return error_resolve_conflict(_(action_name(opts)));
3315 }
3316
Nguyễn Thái Ngọc Duy5e575802019-06-27 16:28:48 +07003317 if (!fill_tree_descriptor(r, &desc, &oid)) {
Johannes Schindelin9055e402018-04-25 14:28:47 +02003318 error(_("failed to find tree of %s"), oid_to_hex(&oid));
3319 rollback_lock_file(&lock);
3320 free((void *)desc.buffer);
3321 strbuf_release(&ref_name);
3322 return -1;
3323 }
3324
3325 if (unpack_trees(1, &desc, &unpack_tree_opts)) {
3326 rollback_lock_file(&lock);
3327 free((void *)desc.buffer);
3328 strbuf_release(&ref_name);
3329 return -1;
3330 }
3331
3332 tree = parse_tree_indirect(&oid);
Nguyễn Thái Ngọc Duyc207e9e2018-11-10 06:49:02 +01003333 prime_cache_tree(r, r->index, tree);
Johannes Schindelin9055e402018-04-25 14:28:47 +02003334
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003335 if (write_locked_index(r->index, &lock, COMMIT_LOCK) < 0)
Johannes Schindelin9055e402018-04-25 14:28:47 +02003336 ret = error(_("could not write index"));
3337 free((void *)desc.buffer);
3338
3339 if (!ret)
3340 ret = update_ref(reflog_message(opts, "reset", "'%.*s'",
3341 len, name), "HEAD", &oid,
3342 NULL, 0, UPDATE_REFS_MSG_ON_ERR);
3343
3344 strbuf_release(&ref_name);
3345 return ret;
3346}
3347
Johannes Schindelin2b6ad0f2017-12-21 15:52:45 +01003348static struct commit *lookup_label(const char *label, int len,
3349 struct strbuf *buf)
3350{
3351 struct commit *commit;
3352
3353 strbuf_reset(buf);
3354 strbuf_addf(buf, "refs/rewritten/%.*s", len, label);
3355 commit = lookup_commit_reference_by_name(buf->buf);
3356 if (!commit) {
3357 /* fall back to non-rewritten ref or commit */
3358 strbuf_splice(buf, 0, strlen("refs/rewritten/"), "", 0);
3359 commit = lookup_commit_reference_by_name(buf->buf);
3360 }
3361
3362 if (!commit)
3363 error(_("could not resolve '%s'"), buf->buf);
3364
3365 return commit;
3366}
3367
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003368static int do_merge(struct repository *r,
3369 struct commit *commit,
3370 const char *arg, int arg_len,
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02003371 int flags, struct replay_opts *opts)
3372{
3373 int run_commit_flags = (flags & TODO_EDIT_MERGE_MSG) ?
3374 EDIT_MSG | VERIFY_MSG : 0;
3375 struct strbuf ref_name = STRBUF_INIT;
3376 struct commit *head_commit, *merge_commit, *i;
3377 struct commit_list *bases, *j, *reversed = NULL;
Johannes Schindelin2b6ad0f2017-12-21 15:52:45 +01003378 struct commit_list *to_merge = NULL, **tail = &to_merge;
Johannes Schindeline145d992019-07-31 08:18:47 -07003379 const char *strategy = !opts->xopts_nr &&
3380 (!opts->strategy || !strcmp(opts->strategy, "recursive")) ?
3381 NULL : opts->strategy;
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02003382 struct merge_options o;
Johannes Schindelin2b6ad0f2017-12-21 15:52:45 +01003383 int merge_arg_len, oneline_offset, can_fast_forward, ret, k;
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02003384 static struct lock_file lock;
3385 const char *p;
3386
Nguyễn Thái Ngọc Duy3a95f312019-01-12 09:13:24 +07003387 if (repo_hold_locked_index(r, &lock, LOCK_REPORT_ON_ERROR) < 0) {
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02003388 ret = -1;
3389 goto leave_merge;
3390 }
3391
3392 head_commit = lookup_commit_reference_by_name("HEAD");
3393 if (!head_commit) {
3394 ret = error(_("cannot merge without a current revision"));
3395 goto leave_merge;
3396 }
3397
Johannes Schindelin2b6ad0f2017-12-21 15:52:45 +01003398 /*
3399 * For octopus merges, the arg starts with the list of revisions to be
3400 * merged. The list is optionally followed by '#' and the oneline.
3401 */
3402 merge_arg_len = oneline_offset = arg_len;
3403 for (p = arg; p - arg < arg_len; p += strspn(p, " \t\n")) {
3404 if (!*p)
3405 break;
3406 if (*p == '#' && (!p[1] || isspace(p[1]))) {
3407 p += 1 + strspn(p + 1, " \t\n");
3408 oneline_offset = p - arg;
3409 break;
3410 }
3411 k = strcspn(p, " \t\n");
3412 if (!k)
3413 continue;
3414 merge_commit = lookup_label(p, k, &ref_name);
3415 if (!merge_commit) {
3416 ret = error(_("unable to parse '%.*s'"), k, p);
3417 goto leave_merge;
3418 }
3419 tail = &commit_list_insert(merge_commit, tail)->next;
3420 p += k;
3421 merge_arg_len = p - arg;
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02003422 }
3423
Johannes Schindelin2b6ad0f2017-12-21 15:52:45 +01003424 if (!to_merge) {
3425 ret = error(_("nothing to merge: '%.*s'"), arg_len, arg);
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02003426 goto leave_merge;
3427 }
3428
Johannes Schindelin9c85a1c2018-05-04 01:01:28 +02003429 if (opts->have_squash_onto &&
Jeff King4a7e27e2018-08-28 17:22:40 -04003430 oideq(&head_commit->object.oid, &opts->squash_onto)) {
Johannes Schindelin9c85a1c2018-05-04 01:01:28 +02003431 /*
3432 * When the user tells us to "merge" something into a
3433 * "[new root]", let's simply fast-forward to the merge head.
3434 */
3435 rollback_lock_file(&lock);
Johannes Schindelin2b6ad0f2017-12-21 15:52:45 +01003436 if (to_merge->next)
3437 ret = error(_("octopus merge cannot be executed on "
3438 "top of a [new root]"));
3439 else
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003440 ret = fast_forward_to(r, &to_merge->item->object.oid,
Johannes Schindelin2b6ad0f2017-12-21 15:52:45 +01003441 &head_commit->object.oid, 0,
3442 opts);
Johannes Schindelin9c85a1c2018-05-04 01:01:28 +02003443 goto leave_merge;
3444 }
3445
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02003446 if (commit) {
Doan Tran Cong Danh5772b0c2019-11-11 13:03:40 +07003447 const char *encoding = get_commit_output_encoding();
3448 const char *message = logmsg_reencode(commit, NULL, encoding);
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02003449 const char *body;
3450 int len;
3451
3452 if (!message) {
3453 ret = error(_("could not get commit message of '%s'"),
3454 oid_to_hex(&commit->object.oid));
3455 goto leave_merge;
3456 }
3457 write_author_script(message);
3458 find_commit_subject(message, &body);
3459 len = strlen(body);
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003460 ret = write_message(body, len, git_path_merge_msg(r), 0);
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02003461 unuse_commit_buffer(commit, message);
3462 if (ret) {
3463 error_errno(_("could not write '%s'"),
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003464 git_path_merge_msg(r));
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02003465 goto leave_merge;
3466 }
3467 } else {
3468 struct strbuf buf = STRBUF_INIT;
3469 int len;
3470
3471 strbuf_addf(&buf, "author %s", git_author_info(0));
3472 write_author_script(buf.buf);
3473 strbuf_reset(&buf);
3474
3475 if (oneline_offset < arg_len) {
3476 p = arg + oneline_offset;
3477 len = arg_len - oneline_offset;
3478 } else {
Johannes Schindelin2b6ad0f2017-12-21 15:52:45 +01003479 strbuf_addf(&buf, "Merge %s '%.*s'",
3480 to_merge->next ? "branches" : "branch",
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02003481 merge_arg_len, arg);
3482 p = buf.buf;
3483 len = buf.len;
3484 }
3485
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003486 ret = write_message(p, len, git_path_merge_msg(r), 0);
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02003487 strbuf_release(&buf);
3488 if (ret) {
3489 error_errno(_("could not write '%s'"),
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003490 git_path_merge_msg(r));
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02003491 goto leave_merge;
3492 }
3493 }
3494
Johannes Schindelind1e8b012018-04-25 14:28:56 +02003495 /*
3496 * If HEAD is not identical to the first parent of the original merge
3497 * commit, we cannot fast-forward.
3498 */
3499 can_fast_forward = opts->allow_ff && commit && commit->parents &&
Jeff King4a7e27e2018-08-28 17:22:40 -04003500 oideq(&commit->parents->item->object.oid,
3501 &head_commit->object.oid);
Johannes Schindelind1e8b012018-04-25 14:28:56 +02003502
3503 /*
Johannes Schindelin2b6ad0f2017-12-21 15:52:45 +01003504 * If any merge head is different from the original one, we cannot
Johannes Schindelind1e8b012018-04-25 14:28:56 +02003505 * fast-forward.
3506 */
3507 if (can_fast_forward) {
Johannes Schindelin2b6ad0f2017-12-21 15:52:45 +01003508 struct commit_list *p = commit->parents->next;
Johannes Schindelind1e8b012018-04-25 14:28:56 +02003509
Johannes Schindelin2b6ad0f2017-12-21 15:52:45 +01003510 for (j = to_merge; j && p; j = j->next, p = p->next)
Jeff King9001dc22018-08-28 17:22:48 -04003511 if (!oideq(&j->item->object.oid,
Johannes Schindelin2b6ad0f2017-12-21 15:52:45 +01003512 &p->item->object.oid)) {
3513 can_fast_forward = 0;
3514 break;
3515 }
3516 /*
3517 * If the number of merge heads differs from the original merge
3518 * commit, we cannot fast-forward.
3519 */
3520 if (j || p)
Johannes Schindelind1e8b012018-04-25 14:28:56 +02003521 can_fast_forward = 0;
3522 }
3523
Johannes Schindelin2b6ad0f2017-12-21 15:52:45 +01003524 if (can_fast_forward) {
Johannes Schindelind1e8b012018-04-25 14:28:56 +02003525 rollback_lock_file(&lock);
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003526 ret = fast_forward_to(r, &commit->object.oid,
Johannes Schindelind1e8b012018-04-25 14:28:56 +02003527 &head_commit->object.oid, 0, opts);
Phillip Wood6df8df02019-05-02 11:22:49 +01003528 if (flags & TODO_EDIT_MERGE_MSG) {
3529 run_commit_flags |= AMEND_MSG;
3530 goto fast_forward_edit;
3531 }
Johannes Schindelind1e8b012018-04-25 14:28:56 +02003532 goto leave_merge;
3533 }
3534
Johannes Schindeline145d992019-07-31 08:18:47 -07003535 if (strategy || to_merge->next) {
Johannes Schindelin2b6ad0f2017-12-21 15:52:45 +01003536 /* Octopus merge */
3537 struct child_process cmd = CHILD_PROCESS_INIT;
3538
3539 if (read_env_script(&cmd.env_array)) {
3540 const char *gpg_opt = gpg_sign_opt_quoted(opts);
3541
3542 ret = error(_(staged_changes_advice), gpg_opt, gpg_opt);
3543 goto leave_merge;
3544 }
3545
3546 cmd.git_cmd = 1;
3547 argv_array_push(&cmd.args, "merge");
3548 argv_array_push(&cmd.args, "-s");
Johannes Schindeline145d992019-07-31 08:18:47 -07003549 if (!strategy)
3550 argv_array_push(&cmd.args, "octopus");
3551 else {
3552 argv_array_push(&cmd.args, strategy);
3553 for (k = 0; k < opts->xopts_nr; k++)
3554 argv_array_pushf(&cmd.args,
3555 "-X%s", opts->xopts[k]);
3556 }
Johannes Schindelin2b6ad0f2017-12-21 15:52:45 +01003557 argv_array_push(&cmd.args, "--no-edit");
3558 argv_array_push(&cmd.args, "--no-ff");
3559 argv_array_push(&cmd.args, "--no-log");
3560 argv_array_push(&cmd.args, "--no-stat");
3561 argv_array_push(&cmd.args, "-F");
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003562 argv_array_push(&cmd.args, git_path_merge_msg(r));
Johannes Schindelin2b6ad0f2017-12-21 15:52:45 +01003563 if (opts->gpg_sign)
3564 argv_array_push(&cmd.args, opts->gpg_sign);
3565
3566 /* Add the tips to be merged */
3567 for (j = to_merge; j; j = j->next)
3568 argv_array_push(&cmd.args,
3569 oid_to_hex(&j->item->object.oid));
3570
3571 strbuf_release(&ref_name);
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003572 unlink(git_path_cherry_pick_head(r));
Johannes Schindelin2b6ad0f2017-12-21 15:52:45 +01003573 rollback_lock_file(&lock);
3574
3575 rollback_lock_file(&lock);
3576 ret = run_command(&cmd);
3577
3578 /* force re-reading of the cache */
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003579 if (!ret && (discard_index(r->index) < 0 ||
Nguyễn Thái Ngọc Duye1ff0a32019-01-12 09:13:26 +07003580 repo_read_index(r) < 0))
Johannes Schindelin2b6ad0f2017-12-21 15:52:45 +01003581 ret = error(_("could not read index"));
3582 goto leave_merge;
3583 }
3584
3585 merge_commit = to_merge->item;
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02003586 bases = get_merge_bases(head_commit, merge_commit);
Jeff King4a7e27e2018-08-28 17:22:40 -04003587 if (bases && oideq(&merge_commit->object.oid,
3588 &bases->item->object.oid)) {
Johannes Schindelin7ccdf652018-04-25 14:29:31 +02003589 ret = 0;
3590 /* skip merging an ancestor of HEAD */
3591 goto leave_merge;
3592 }
3593
brian m. carlson4439c7a2019-08-18 20:04:16 +00003594 write_message(oid_to_hex(&merge_commit->object.oid), the_hash_algo->hexsz,
Junio C Hamanocde55542019-01-04 13:33:33 -08003595 git_path_merge_head(r), 0);
3596 write_message("no-ff", 5, git_path_merge_mode(r), 0);
Johannes Schindelin85f8d9d2018-11-12 15:25:58 -08003597
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02003598 for (j = bases; j; j = j->next)
3599 commit_list_insert(j->item, &reversed);
3600 free_commit_list(bases);
3601
Nguyễn Thái Ngọc Duye1ff0a32019-01-12 09:13:26 +07003602 repo_read_index(r);
Nguyễn Thái Ngọc Duy0d6caa22019-01-12 09:13:29 +07003603 init_merge_options(&o, r);
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02003604 o.branch1 = "HEAD";
3605 o.branch2 = ref_name.buf;
3606 o.buffer_output = 2;
3607
3608 ret = merge_recursive(&o, head_commit, merge_commit, reversed, &i);
3609 if (ret <= 0)
3610 fputs(o.obuf.buf, stdout);
3611 strbuf_release(&o.obuf);
3612 if (ret < 0) {
3613 error(_("could not even attempt to merge '%.*s'"),
3614 merge_arg_len, arg);
3615 goto leave_merge;
3616 }
3617 /*
3618 * The return value of merge_recursive() is 1 on clean, and 0 on
3619 * unclean merge.
3620 *
3621 * Let's reverse that, so that do_merge() returns 0 upon success and
3622 * 1 upon failed merge (keeping the return value -1 for the cases where
3623 * we will want to reschedule the `merge` command).
3624 */
3625 ret = !ret;
3626
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003627 if (r->index->cache_changed &&
3628 write_locked_index(r->index, &lock, COMMIT_LOCK)) {
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02003629 ret = error(_("merge: Unable to write new index file"));
3630 goto leave_merge;
3631 }
3632
3633 rollback_lock_file(&lock);
3634 if (ret)
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003635 repo_rerere(r, opts->allow_rerere_auto);
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02003636 else
3637 /*
3638 * In case of problems, we now want to return a positive
3639 * value (a negative one would indicate that the `merge`
3640 * command needs to be rescheduled).
3641 */
Phillip Wood6df8df02019-05-02 11:22:49 +01003642 fast_forward_edit:
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003643 ret = !!run_git_commit(r, git_path_merge_msg(r), opts,
3644 run_commit_flags);
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02003645
3646leave_merge:
3647 strbuf_release(&ref_name);
3648 rollback_lock_file(&lock);
Johannes Schindelin2b6ad0f2017-12-21 15:52:45 +01003649 free_commit_list(to_merge);
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02003650 return ret;
3651}
3652
Johannes Schindelin6e98de72017-01-02 16:27:07 +01003653static int is_final_fixup(struct todo_list *todo_list)
3654{
3655 int i = todo_list->current;
3656
3657 if (!is_fixup(todo_list->items[i].command))
3658 return 0;
3659
3660 while (++i < todo_list->nr)
3661 if (is_fixup(todo_list->items[i].command))
3662 return 0;
3663 else if (!is_noop(todo_list->items[i].command))
3664 break;
3665 return 1;
3666}
3667
Johannes Schindelin25cb8df2017-01-02 16:28:16 +01003668static enum todo_command peek_command(struct todo_list *todo_list, int offset)
3669{
3670 int i;
3671
3672 for (i = todo_list->current + offset; i < todo_list->nr; i++)
3673 if (!is_noop(todo_list->items[i].command))
3674 return todo_list->items[i].command;
3675
3676 return -1;
3677}
3678
Denton Liu0816f1d2020-04-07 10:28:03 -04003679void create_autostash(struct repository *r, const char *path,
3680 const char *default_reflog_action)
Johannes Schindelin796c7972017-01-02 16:28:27 +01003681{
Denton Liu0816f1d2020-04-07 10:28:03 -04003682 struct strbuf buf = STRBUF_INIT;
3683 struct lock_file lock_file = LOCK_INIT;
3684 int fd;
3685
3686 fd = repo_hold_locked_index(r, &lock_file, 0);
3687 refresh_index(r->index, REFRESH_QUIET, NULL, NULL, NULL);
3688 if (0 <= fd)
3689 repo_update_index_if_able(r, &lock_file);
3690 rollback_lock_file(&lock_file);
3691
3692 if (has_unstaged_changes(r, 1) ||
3693 has_uncommitted_changes(r, 1)) {
3694 struct child_process stash = CHILD_PROCESS_INIT;
3695 struct object_id oid;
3696
3697 argv_array_pushl(&stash.args,
3698 "stash", "create", "autostash", NULL);
3699 stash.git_cmd = 1;
3700 stash.no_stdin = 1;
3701 strbuf_reset(&buf);
3702 if (capture_command(&stash, &buf, GIT_MAX_HEXSZ))
3703 die(_("Cannot autostash"));
3704 strbuf_trim_trailing_newline(&buf);
3705 if (get_oid(buf.buf, &oid))
3706 die(_("Unexpected stash response: '%s'"),
3707 buf.buf);
3708 strbuf_reset(&buf);
3709 strbuf_add_unique_abbrev(&buf, &oid, DEFAULT_ABBREV);
3710
3711 if (safe_create_leading_directories_const(path))
3712 die(_("Could not create directory for '%s'"),
3713 path);
3714 write_file(path, "%s", oid_to_hex(&oid));
3715 printf(_("Created autostash: %s\n"), buf.buf);
3716 if (reset_head(r, NULL, "reset --hard",
3717 NULL, RESET_HEAD_HARD, NULL, NULL,
3718 default_reflog_action) < 0)
3719 die(_("could not reset --hard"));
3720
3721 if (discard_index(r->index) < 0 ||
3722 repo_read_index(r) < 0)
3723 die(_("could not read index"));
3724 }
3725 strbuf_release(&buf);
3726}
3727
Denton Liu804fe312020-04-07 10:28:06 -04003728static int apply_save_autostash_oid(const char *stash_oid, int attempt_apply)
Johannes Schindelin796c7972017-01-02 16:28:27 +01003729{
Johannes Schindelin796c7972017-01-02 16:28:27 +01003730 struct child_process child = CHILD_PROCESS_INIT;
3731 int ret = 0;
3732
Denton Liu12b6e132020-04-07 10:28:05 -04003733 if (attempt_apply) {
3734 child.git_cmd = 1;
3735 child.no_stdout = 1;
3736 child.no_stderr = 1;
3737 argv_array_push(&child.args, "stash");
3738 argv_array_push(&child.args, "apply");
Denton Liu804fe312020-04-07 10:28:06 -04003739 argv_array_push(&child.args, stash_oid);
Denton Liu12b6e132020-04-07 10:28:05 -04003740 ret = run_command(&child);
Johannes Schindelin796c7972017-01-02 16:28:27 +01003741 }
Johannes Schindelin796c7972017-01-02 16:28:27 +01003742
Denton Liu12b6e132020-04-07 10:28:05 -04003743 if (attempt_apply && !ret)
Johannes Schindelincdb866b2017-06-19 18:56:02 +01003744 fprintf(stderr, _("Applied autostash.\n"));
Johannes Schindelin796c7972017-01-02 16:28:27 +01003745 else {
3746 struct child_process store = CHILD_PROCESS_INIT;
3747
3748 store.git_cmd = 1;
3749 argv_array_push(&store.args, "stash");
3750 argv_array_push(&store.args, "store");
3751 argv_array_push(&store.args, "-m");
3752 argv_array_push(&store.args, "autostash");
3753 argv_array_push(&store.args, "-q");
Denton Liu804fe312020-04-07 10:28:06 -04003754 argv_array_push(&store.args, stash_oid);
Johannes Schindelin796c7972017-01-02 16:28:27 +01003755 if (run_command(&store))
Denton Liu804fe312020-04-07 10:28:06 -04003756 ret = error(_("cannot store %s"), stash_oid);
Johannes Schindelin796c7972017-01-02 16:28:27 +01003757 else
Johannes Schindelincdb866b2017-06-19 18:56:02 +01003758 fprintf(stderr,
Denton Liu12b6e132020-04-07 10:28:05 -04003759 _("%s\n"
Johannes Schindelincdb866b2017-06-19 18:56:02 +01003760 "Your changes are safe in the stash.\n"
3761 "You can run \"git stash pop\" or"
Denton Liu12b6e132020-04-07 10:28:05 -04003762 " \"git stash drop\" at any time.\n"),
3763 attempt_apply ?
3764 _("Applying autostash resulted in conflicts.") :
3765 _("Autostash exists; creating a new stash entry."));
Johannes Schindelin796c7972017-01-02 16:28:27 +01003766 }
3767
Johannes Schindelin796c7972017-01-02 16:28:27 +01003768 return ret;
3769}
3770
Denton Liu804fe312020-04-07 10:28:06 -04003771static int apply_save_autostash(const char *path, int attempt_apply)
3772{
3773 struct strbuf stash_oid = STRBUF_INIT;
3774 int ret = 0;
3775
3776 if (!read_oneliner(&stash_oid, path,
3777 READ_ONELINER_SKIP_IF_EMPTY)) {
3778 strbuf_release(&stash_oid);
3779 return 0;
3780 }
3781 strbuf_trim(&stash_oid);
3782
3783 ret = apply_save_autostash_oid(stash_oid.buf, attempt_apply);
3784
Denton Liu0dd562e2020-04-07 10:28:04 -04003785 unlink(path);
Denton Liufacca7f2020-04-07 10:27:57 -04003786 strbuf_release(&stash_oid);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05303787 return ret;
3788}
3789
Denton Liu12b6e132020-04-07 10:28:05 -04003790int save_autostash(const char *path)
3791{
3792 return apply_save_autostash(path, 0);
3793}
3794
3795int apply_autostash(const char *path)
3796{
3797 return apply_save_autostash(path, 1);
3798}
3799
Denton Liu804fe312020-04-07 10:28:06 -04003800int apply_autostash_oid(const char *stash_oid)
3801{
3802 return apply_save_autostash_oid(stash_oid, 1);
3803}
3804
Johannes Schindelin96e832a2017-01-02 16:28:09 +01003805static const char *reflog_message(struct replay_opts *opts,
3806 const char *sub_action, const char *fmt, ...)
3807{
3808 va_list ap;
3809 static struct strbuf buf = STRBUF_INIT;
Elijah Newren1f6965f2020-04-07 16:59:23 +00003810 char *reflog_action = getenv(GIT_REFLOG_ACTION);
Johannes Schindelin96e832a2017-01-02 16:28:09 +01003811
3812 va_start(ap, fmt);
3813 strbuf_reset(&buf);
Elijah Newren1f6965f2020-04-07 16:59:23 +00003814 strbuf_addstr(&buf, reflog_action ? reflog_action : action_name(opts));
Johannes Schindelin96e832a2017-01-02 16:28:09 +01003815 if (sub_action)
3816 strbuf_addf(&buf, " (%s)", sub_action);
3817 if (fmt) {
3818 strbuf_addstr(&buf, ": ");
3819 strbuf_vaddf(&buf, fmt, ap);
3820 }
3821 va_end(ap);
3822
3823 return buf.buf;
3824}
3825
Phillip Woodfc4a6732019-03-19 19:03:07 +00003826static int run_git_checkout(struct repository *r, struct replay_opts *opts,
3827 const char *commit, const char *action)
Alban Gruin2c584832018-08-10 18:51:33 +02003828{
3829 struct child_process cmd = CHILD_PROCESS_INIT;
Phillip Woodfc4a6732019-03-19 19:03:07 +00003830 int ret;
Alban Gruin2c584832018-08-10 18:51:33 +02003831
3832 cmd.git_cmd = 1;
3833
3834 argv_array_push(&cmd.args, "checkout");
3835 argv_array_push(&cmd.args, commit);
3836 argv_array_pushf(&cmd.env_array, GIT_REFLOG_ACTION "=%s", action);
3837
3838 if (opts->verbose)
Phillip Woodfc4a6732019-03-19 19:03:07 +00003839 ret = run_command(&cmd);
Alban Gruin2c584832018-08-10 18:51:33 +02003840 else
Phillip Woodfc4a6732019-03-19 19:03:07 +00003841 ret = run_command_silent_on_success(&cmd);
3842
3843 if (!ret)
3844 discard_index(r->index);
3845
3846 return ret;
Alban Gruin2c584832018-08-10 18:51:33 +02003847}
3848
Phillip Woodfc4a6732019-03-19 19:03:07 +00003849static int checkout_onto(struct repository *r, struct replay_opts *opts,
Phillip Wood7d3488e2019-04-17 15:30:39 +01003850 const char *onto_name, const struct object_id *onto,
Alban Gruin91f0d952018-08-28 14:10:37 +02003851 const char *orig_head)
Alban Gruin4df66c42018-08-10 18:51:34 +02003852{
3853 struct object_id oid;
3854 const char *action = reflog_message(opts, "start", "checkout %s", onto_name);
3855
3856 if (get_oid(orig_head, &oid))
3857 return error(_("%s: not a valid OID"), orig_head);
3858
Phillip Wood7d3488e2019-04-17 15:30:39 +01003859 if (run_git_checkout(r, opts, oid_to_hex(onto), action)) {
Denton Liube1bb602020-04-07 10:27:56 -04003860 apply_autostash(rebase_path_autostash());
Alban Gruin4df66c42018-08-10 18:51:34 +02003861 sequencer_remove_state(opts);
3862 return error(_("could not detach HEAD"));
3863 }
3864
3865 return update_ref(NULL, "ORIG_HEAD", &oid, NULL, 0, UPDATE_REFS_MSG_ON_ERR);
3866}
3867
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01003868static int stopped_at_head(struct repository *r)
Johannes Schindelin71f82462018-10-12 06:14:26 -07003869{
3870 struct object_id head;
3871 struct commit *commit;
3872 struct commit_message message;
3873
Junio C Hamano789b1f72018-11-02 11:04:58 +09003874 if (get_oid("HEAD", &head) ||
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01003875 !(commit = lookup_commit(r, &head)) ||
Johannes Schindelin71f82462018-10-12 06:14:26 -07003876 parse_commit(commit) || get_message(commit, &message))
3877 fprintf(stderr, _("Stopped at HEAD\n"));
3878 else {
3879 fprintf(stderr, _("Stopped at %s\n"), message.label);
3880 free_message(commit, &message);
3881 }
3882 return 0;
3883
3884}
3885
Johannes Schindelincb5206e2018-04-25 14:28:33 +02003886static const char rescheduled_advice[] =
3887N_("Could not execute the todo command\n"
3888"\n"
3889" %.*s"
3890"\n"
3891"It has been rescheduled; To edit the command before continuing, please\n"
3892"edit the todo list first:\n"
3893"\n"
3894" git rebase --edit-todo\n"
3895" git rebase --continue\n");
3896
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003897static int pick_commits(struct repository *r,
3898 struct todo_list *todo_list,
3899 struct replay_opts *opts)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05303900{
Johannes Schindelin9055e402018-04-25 14:28:47 +02003901 int res = 0, reschedule = 0;
Elijah Newren1f6965f2020-04-07 16:59:23 +00003902 char *prev_reflog_action;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05303903
Elijah Newren1f6965f2020-04-07 16:59:23 +00003904 /* Note that 0 for 3rd parameter of setenv means set only if not set */
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05303905 setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
Elijah Newren1f6965f2020-04-07 16:59:23 +00003906 prev_reflog_action = xstrdup(getenv(GIT_REFLOG_ACTION));
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05303907 if (opts->allow_ff)
3908 assert(!(opts->signoff || opts->no_commit ||
Junio C Hamano4d924522020-01-12 12:27:41 -08003909 opts->record_origin || opts->edit));
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003910 if (read_and_refresh_cache(r, opts))
Johannes Schindelin0d9c6dc2016-09-09 16:37:21 +02003911 return -1;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05303912
Johannes Schindelin004fefa2016-10-21 14:24:41 +02003913 while (todo_list->current < todo_list->nr) {
3914 struct todo_item *item = todo_list->items + todo_list->current;
Alban Gruin6ad656d2019-01-29 16:01:46 +01003915 const char *arg = todo_item_get_arg(todo_list, item);
Phillip Wooda47ba3c2019-08-19 02:18:22 -07003916 int check_todo = 0;
Alban Gruin6ad656d2019-01-29 16:01:46 +01003917
Johannes Schindelin004fefa2016-10-21 14:24:41 +02003918 if (save_todo(todo_list, opts))
Johannes Schindelin221675d2016-09-09 16:37:50 +02003919 return -1;
Johannes Schindelin6e98de72017-01-02 16:27:07 +01003920 if (is_rebase_i(opts)) {
Johannes Schindelinef800692017-01-02 16:36:20 +01003921 if (item->command != TODO_COMMENT) {
3922 FILE *f = fopen(rebase_path_msgnum(), "w");
3923
3924 todo_list->done_nr++;
3925
3926 if (f) {
3927 fprintf(f, "%d\n", todo_list->done_nr);
3928 fclose(f);
3929 }
Elijah Newren899b49c2018-12-11 08:11:36 -08003930 if (!opts->quiet)
Alban Gruin4d55d632020-03-28 14:05:15 +01003931 fprintf(stderr, _("Rebasing (%d/%d)%s"),
Elijah Newren899b49c2018-12-11 08:11:36 -08003932 todo_list->done_nr,
3933 todo_list->total_nr,
3934 opts->verbose ? "\n" : "\r");
Johannes Schindelinef800692017-01-02 16:36:20 +01003935 }
Johannes Schindelin6e98de72017-01-02 16:27:07 +01003936 unlink(rebase_path_message());
3937 unlink(rebase_path_author_script());
3938 unlink(rebase_path_stopped_sha());
3939 unlink(rebase_path_amend());
Nguyễn Thái Ngọc Duy34e77712019-06-27 16:28:52 +07003940 unlink(git_path_merge_head(r));
Nguyễn Thái Ngọc Duyfbd7a232018-02-11 16:43:28 +07003941 delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
Johannes Schindelin71f82462018-10-12 06:14:26 -07003942
SZEDER Gábord7d90882019-06-27 15:42:48 +02003943 if (item->command == TODO_BREAK) {
3944 if (!opts->verbose)
3945 term_clear_line();
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01003946 return stopped_at_head(r);
SZEDER Gábord7d90882019-06-27 15:42:48 +02003947 }
Johannes Schindelin6e98de72017-01-02 16:27:07 +01003948 }
3949 if (item->command <= TODO_SQUASH) {
Johannes Schindelin8ab37ef2017-01-02 16:28:13 +01003950 if (is_rebase_i(opts))
Elijah Newren1f6965f2020-04-07 16:59:23 +00003951 setenv(GIT_REFLOG_ACTION, reflog_message(opts,
Johannes Schindelin8ab37ef2017-01-02 16:28:13 +01003952 command_to_string(item->command), NULL),
3953 1);
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003954 res = do_pick_commit(r, item->command, item->commit,
Phillip Wooda47ba3c2019-08-19 02:18:22 -07003955 opts, is_final_fixup(todo_list),
3956 &check_todo);
Elijah Newren1f6965f2020-04-07 16:59:23 +00003957 if (is_rebase_i(opts))
3958 setenv(GIT_REFLOG_ACTION, prev_reflog_action, 1);
Johannes Schindelin9d7bf3c2017-01-02 16:28:34 +01003959 if (is_rebase_i(opts) && res < 0) {
3960 /* Reschedule */
Johannes Schindelincb5206e2018-04-25 14:28:33 +02003961 advise(_(rescheduled_advice),
3962 get_item_line_length(todo_list,
3963 todo_list->current),
3964 get_item_line(todo_list,
3965 todo_list->current));
Johannes Schindelin9d7bf3c2017-01-02 16:28:34 +01003966 todo_list->current--;
3967 if (save_todo(todo_list, opts))
3968 return -1;
3969 }
Johannes Schindelin56dc3ab2017-01-02 16:26:43 +01003970 if (item->command == TODO_EDIT) {
3971 struct commit *commit = item->commit;
SZEDER Gábord7d90882019-06-27 15:42:48 +02003972 if (!res) {
3973 if (!opts->verbose)
3974 term_clear_line();
Jeff King99429212017-03-16 20:19:42 -04003975 fprintf(stderr,
Brandon Williamsa42e1b42017-03-23 10:02:33 -07003976 _("Stopped at %s... %.*s\n"),
Johannes Schindelin56dc3ab2017-01-02 16:26:43 +01003977 short_commit_name(commit),
Alban Gruin6ad656d2019-01-29 16:01:46 +01003978 item->arg_len, arg);
SZEDER Gábord7d90882019-06-27 15:42:48 +02003979 }
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003980 return error_with_patch(r, commit,
Alban Gruin6ad656d2019-01-29 16:01:46 +01003981 arg, item->arg_len, opts, res, !res);
Johannes Schindelin56dc3ab2017-01-02 16:26:43 +01003982 }
Johannes Schindelin25cb8df2017-01-02 16:28:16 +01003983 if (is_rebase_i(opts) && !res)
3984 record_in_rewritten(&item->commit->object.oid,
3985 peek_command(todo_list, 1));
Johannes Schindelin6e98de72017-01-02 16:27:07 +01003986 if (res && is_fixup(item->command)) {
3987 if (res == 1)
3988 intend_to_amend();
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01003989 return error_failed_squash(r, item->commit, opts,
Alban Gruin6ad656d2019-01-29 16:01:46 +01003990 item->arg_len, arg);
Phillip Wooda9279c62018-06-19 13:46:51 +01003991 } else if (res && is_rebase_i(opts) && item->commit) {
3992 int to_amend = 0;
3993 struct object_id oid;
3994
3995 /*
3996 * If we are rewording and have either
3997 * fast-forwarded already, or are about to
3998 * create a new root commit, we want to amend,
3999 * otherwise we do not.
4000 */
4001 if (item->command == TODO_REWORD &&
4002 !get_oid("HEAD", &oid) &&
Jeff King4a7e27e2018-08-28 17:22:40 -04004003 (oideq(&item->commit->object.oid, &oid) ||
Phillip Wooda9279c62018-06-19 13:46:51 +01004004 (opts->have_squash_onto &&
Jeff King4a7e27e2018-08-28 17:22:40 -04004005 oideq(&opts->squash_onto, &oid))))
Phillip Wooda9279c62018-06-19 13:46:51 +01004006 to_amend = 1;
4007
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01004008 return res | error_with_patch(r, item->commit,
Alban Gruin6ad656d2019-01-29 16:01:46 +01004009 arg, item->arg_len, opts,
Phillip Wooda9279c62018-06-19 13:46:51 +01004010 res, to_amend);
4011 }
Johannes Schindelin311af522017-01-02 16:26:47 +01004012 } else if (item->command == TODO_EXEC) {
Alban Gruin6ad656d2019-01-29 16:01:46 +01004013 char *end_of_arg = (char *)(arg + item->arg_len);
Johannes Schindelin311af522017-01-02 16:26:47 +01004014 int saved = *end_of_arg;
4015
SZEDER Gábord7d90882019-06-27 15:42:48 +02004016 if (!opts->verbose)
4017 term_clear_line();
Johannes Schindelin311af522017-01-02 16:26:47 +01004018 *end_of_arg = '\0';
Alban Gruin6ad656d2019-01-29 16:01:46 +01004019 res = do_exec(r, arg);
Johannes Schindelin311af522017-01-02 16:26:47 +01004020 *end_of_arg = saved;
Stephen Hicks54fd3242017-04-26 21:17:40 +02004021
Johannes Schindelind421afa2018-12-10 11:04:58 -08004022 if (res) {
4023 if (opts->reschedule_failed_exec)
4024 reschedule = 1;
Stephen Hicks54fd3242017-04-26 21:17:40 +02004025 }
Phillip Wooda47ba3c2019-08-19 02:18:22 -07004026 check_todo = 1;
Johannes Schindelin9055e402018-04-25 14:28:47 +02004027 } else if (item->command == TODO_LABEL) {
Alban Gruin6ad656d2019-01-29 16:01:46 +01004028 if ((res = do_label(r, arg, item->arg_len)))
Johannes Schindelin9055e402018-04-25 14:28:47 +02004029 reschedule = 1;
4030 } else if (item->command == TODO_RESET) {
Alban Gruin6ad656d2019-01-29 16:01:46 +01004031 if ((res = do_reset(r, arg, item->arg_len, opts)))
Johannes Schindelin9055e402018-04-25 14:28:47 +02004032 reschedule = 1;
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02004033 } else if (item->command == TODO_MERGE) {
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01004034 if ((res = do_merge(r, item->commit,
Alban Gruin6ad656d2019-01-29 16:01:46 +01004035 arg, item->arg_len,
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02004036 item->flags, opts)) < 0)
4037 reschedule = 1;
Johannes Schindelin537e7d62018-04-25 14:29:29 +02004038 else if (item->commit)
4039 record_in_rewritten(&item->commit->object.oid,
4040 peek_command(todo_list, 1));
4041 if (res > 0)
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02004042 /* failed with merge conflicts */
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01004043 return error_with_patch(r, item->commit,
Alban Gruin6ad656d2019-01-29 16:01:46 +01004044 arg, item->arg_len,
4045 opts, res, 0);
Johannes Schindelin56dc3ab2017-01-02 16:26:43 +01004046 } else if (!is_noop(item->command))
Johannes Schindelin25c43662017-01-02 16:26:38 +01004047 return error(_("unknown command %d"), item->command);
4048
Johannes Schindelin9055e402018-04-25 14:28:47 +02004049 if (reschedule) {
4050 advise(_(rescheduled_advice),
4051 get_item_line_length(todo_list,
4052 todo_list->current),
4053 get_item_line(todo_list, todo_list->current));
4054 todo_list->current--;
4055 if (save_todo(todo_list, opts))
4056 return -1;
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02004057 if (item->commit)
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01004058 return error_with_patch(r,
4059 item->commit,
Alban Gruin6ad656d2019-01-29 16:01:46 +01004060 arg, item->arg_len,
4061 opts, res, 0);
SZEDER Gáborbefd4f62019-11-23 18:20:46 +01004062 } else if (is_rebase_i(opts) && check_todo && !res) {
Phillip Wooda47ba3c2019-08-19 02:18:22 -07004063 struct stat st;
4064
4065 if (stat(get_todo_path(opts), &st)) {
4066 res = error_errno(_("could not stat '%s'"),
4067 get_todo_path(opts));
4068 } else if (match_stat_data(&todo_list->stat, &st)) {
4069 /* Reread the todo file if it has changed. */
4070 todo_list_release(todo_list);
4071 if (read_populate_todo(r, todo_list, opts))
4072 res = -1; /* message was printed */
4073 /* `current` will be incremented below */
4074 todo_list->current = -1;
4075 }
Johannes Schindelin9055e402018-04-25 14:28:47 +02004076 }
4077
Johannes Schindelin004fefa2016-10-21 14:24:41 +02004078 todo_list->current++;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05304079 if (res)
4080 return res;
4081 }
4082
Johannes Schindelin56dc3ab2017-01-02 16:26:43 +01004083 if (is_rebase_i(opts)) {
Johannes Schindelin4b83ce92017-01-02 16:27:53 +01004084 struct strbuf head_ref = STRBUF_INIT, buf = STRBUF_INIT;
Johannes Schindelin25cb8df2017-01-02 16:28:16 +01004085 struct stat st;
Johannes Schindelin556907f2017-01-02 16:26:53 +01004086
Johannes Schindelin56dc3ab2017-01-02 16:26:43 +01004087 /* Stopped in the middle, as planned? */
4088 if (todo_list->current < todo_list->nr)
4089 return 0;
Johannes Schindelin556907f2017-01-02 16:26:53 +01004090
Johannes Schindelin4b83ce92017-01-02 16:27:53 +01004091 if (read_oneliner(&head_ref, rebase_path_head_name(), 0) &&
4092 starts_with(head_ref.buf, "refs/")) {
Johannes Schindelin96e832a2017-01-02 16:28:09 +01004093 const char *msg;
brian m. carlson092bbcd2017-07-13 23:49:22 +00004094 struct object_id head, orig;
Johannes Schindelin4b83ce92017-01-02 16:27:53 +01004095 int res;
4096
brian m. carlson092bbcd2017-07-13 23:49:22 +00004097 if (get_oid("HEAD", &head)) {
Johannes Schindelin4b83ce92017-01-02 16:27:53 +01004098 res = error(_("cannot read HEAD"));
4099cleanup_head_ref:
4100 strbuf_release(&head_ref);
4101 strbuf_release(&buf);
4102 return res;
4103 }
4104 if (!read_oneliner(&buf, rebase_path_orig_head(), 0) ||
brian m. carlson092bbcd2017-07-13 23:49:22 +00004105 get_oid_hex(buf.buf, &orig)) {
Johannes Schindelin4b83ce92017-01-02 16:27:53 +01004106 res = error(_("could not read orig-head"));
4107 goto cleanup_head_ref;
4108 }
Phillip Wood4ab867b2017-05-18 11:02:32 +01004109 strbuf_reset(&buf);
Johannes Schindelin4b83ce92017-01-02 16:27:53 +01004110 if (!read_oneliner(&buf, rebase_path_onto(), 0)) {
4111 res = error(_("could not read 'onto'"));
4112 goto cleanup_head_ref;
4113 }
Johannes Schindelin96e832a2017-01-02 16:28:09 +01004114 msg = reflog_message(opts, "finish", "%s onto %s",
4115 head_ref.buf, buf.buf);
brian m. carlsonae077772017-10-15 22:06:51 +00004116 if (update_ref(msg, head_ref.buf, &head, &orig,
Michael Haggerty91774af2017-11-05 09:42:06 +01004117 REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR)) {
Johannes Schindelin4b83ce92017-01-02 16:27:53 +01004118 res = error(_("could not update %s"),
4119 head_ref.buf);
4120 goto cleanup_head_ref;
4121 }
Johannes Schindelin96e832a2017-01-02 16:28:09 +01004122 msg = reflog_message(opts, "finish", "returning to %s",
Johannes Schindelin4b83ce92017-01-02 16:27:53 +01004123 head_ref.buf);
Johannes Schindelin96e832a2017-01-02 16:28:09 +01004124 if (create_symref("HEAD", head_ref.buf, msg)) {
Johannes Schindelin4b83ce92017-01-02 16:27:53 +01004125 res = error(_("could not update HEAD to %s"),
4126 head_ref.buf);
4127 goto cleanup_head_ref;
4128 }
4129 strbuf_reset(&buf);
4130 }
4131
Johannes Schindelin556907f2017-01-02 16:26:53 +01004132 if (opts->verbose) {
4133 struct rev_info log_tree_opt;
4134 struct object_id orig, head;
4135
4136 memset(&log_tree_opt, 0, sizeof(log_tree_opt));
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01004137 repo_init_revisions(r, &log_tree_opt, NULL);
Johannes Schindelin556907f2017-01-02 16:26:53 +01004138 log_tree_opt.diff = 1;
4139 log_tree_opt.diffopt.output_format =
4140 DIFF_FORMAT_DIFFSTAT;
4141 log_tree_opt.disable_stdin = 1;
4142
4143 if (read_oneliner(&buf, rebase_path_orig_head(), 0) &&
brian m. carlsone82caf32017-07-13 23:49:28 +00004144 !get_oid(buf.buf, &orig) &&
4145 !get_oid("HEAD", &head)) {
Brandon Williams66f414f2017-05-30 10:31:03 -07004146 diff_tree_oid(&orig, &head, "",
4147 &log_tree_opt.diffopt);
Johannes Schindelin556907f2017-01-02 16:26:53 +01004148 log_tree_diff_flush(&log_tree_opt);
4149 }
4150 }
Johannes Schindelin25cb8df2017-01-02 16:28:16 +01004151 flush_rewritten_pending();
4152 if (!stat(rebase_path_rewritten_list(), &st) &&
4153 st.st_size > 0) {
4154 struct child_process child = CHILD_PROCESS_INIT;
Johannes Schindelin79516042017-01-02 16:28:23 +01004155 const char *post_rewrite_hook =
4156 find_hook("post-rewrite");
Johannes Schindelin25cb8df2017-01-02 16:28:16 +01004157
4158 child.in = open(rebase_path_rewritten_list(), O_RDONLY);
4159 child.git_cmd = 1;
4160 argv_array_push(&child.args, "notes");
4161 argv_array_push(&child.args, "copy");
4162 argv_array_push(&child.args, "--for-rewrite=rebase");
4163 /* we don't care if this copying failed */
4164 run_command(&child);
Johannes Schindelin79516042017-01-02 16:28:23 +01004165
4166 if (post_rewrite_hook) {
4167 struct child_process hook = CHILD_PROCESS_INIT;
4168
4169 hook.in = open(rebase_path_rewritten_list(),
4170 O_RDONLY);
4171 hook.stdout_to_stderr = 1;
Jeff Hostetler62062862019-02-22 14:25:06 -08004172 hook.trace2_hook_name = "post-rewrite";
Johannes Schindelin79516042017-01-02 16:28:23 +01004173 argv_array_push(&hook.args, post_rewrite_hook);
4174 argv_array_push(&hook.args, "rebase");
4175 /* we don't care if this hook failed */
4176 run_command(&hook);
4177 }
Johannes Schindelin25cb8df2017-01-02 16:28:16 +01004178 }
Denton Liube1bb602020-04-07 10:27:56 -04004179 apply_autostash(rebase_path_autostash());
Johannes Schindelin25cb8df2017-01-02 16:28:16 +01004180
SZEDER Gábord7d90882019-06-27 15:42:48 +02004181 if (!opts->quiet) {
4182 if (!opts->verbose)
4183 term_clear_line();
Elijah Newren899b49c2018-12-11 08:11:36 -08004184 fprintf(stderr,
Alban Gruin4d55d632020-03-28 14:05:15 +01004185 _("Successfully rebased and updated %s.\n"),
Elijah Newren899b49c2018-12-11 08:11:36 -08004186 head_ref.buf);
SZEDER Gábord7d90882019-06-27 15:42:48 +02004187 }
Johannes Schindelin5da49662017-01-02 16:36:25 +01004188
Johannes Schindelin556907f2017-01-02 16:26:53 +01004189 strbuf_release(&buf);
Johannes Schindelin4b83ce92017-01-02 16:27:53 +01004190 strbuf_release(&head_ref);
Johannes Schindelin56dc3ab2017-01-02 16:26:43 +01004191 }
4192
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05304193 /*
4194 * Sequence of picks finished successfully; cleanup by
4195 * removing the .git/sequencer directory
4196 */
Johannes Schindelin28635842016-10-21 14:24:55 +02004197 return sequencer_remove_state(opts);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05304198}
4199
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01004200static int continue_single_pick(struct repository *r)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05304201{
4202 const char *argv[] = { "commit", NULL };
4203
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01004204 if (!file_exists(git_path_cherry_pick_head(r)) &&
4205 !file_exists(git_path_revert_head(r)))
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05304206 return error(_("no cherry-pick or revert in progress"));
4207 return run_command_v_opt(argv, RUN_GIT_CMD);
4208}
4209
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01004210static int commit_staged_changes(struct repository *r,
4211 struct replay_opts *opts,
Johannes Schindelin15ef6932018-04-27 22:48:30 +02004212 struct todo_list *todo_list)
Johannes Schindelin9d93ccd2017-01-02 16:27:21 +01004213{
Johannes Schindelin789b3ef2017-03-23 17:07:11 +01004214 unsigned int flags = ALLOW_EMPTY | EDIT_MSG;
Johannes Schindelin15ef6932018-04-27 22:48:30 +02004215 unsigned int final_fixup = 0, is_clean;
Johannes Schindelin9d93ccd2017-01-02 16:27:21 +01004216
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01004217 if (has_unstaged_changes(r, 1))
Johannes Schindelin9d93ccd2017-01-02 16:27:21 +01004218 return error(_("cannot rebase: You have unstaged changes."));
Johannes Schindelin52632202017-01-02 16:27:25 +01004219
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01004220 is_clean = !has_uncommitted_changes(r, 0);
Johannes Schindelin9d93ccd2017-01-02 16:27:21 +01004221
4222 if (file_exists(rebase_path_amend())) {
4223 struct strbuf rev = STRBUF_INIT;
brian m. carlson092bbcd2017-07-13 23:49:22 +00004224 struct object_id head, to_amend;
Johannes Schindelin9d93ccd2017-01-02 16:27:21 +01004225
brian m. carlson092bbcd2017-07-13 23:49:22 +00004226 if (get_oid("HEAD", &head))
Johannes Schindelin9d93ccd2017-01-02 16:27:21 +01004227 return error(_("cannot amend non-existing commit"));
4228 if (!read_oneliner(&rev, rebase_path_amend(), 0))
4229 return error(_("invalid file: '%s'"), rebase_path_amend());
brian m. carlson092bbcd2017-07-13 23:49:22 +00004230 if (get_oid_hex(rev.buf, &to_amend))
Johannes Schindelin9d93ccd2017-01-02 16:27:21 +01004231 return error(_("invalid contents: '%s'"),
4232 rebase_path_amend());
Jeff King9001dc22018-08-28 17:22:48 -04004233 if (!is_clean && !oideq(&head, &to_amend))
Johannes Schindelin9d93ccd2017-01-02 16:27:21 +01004234 return error(_("\nYou have uncommitted changes in your "
4235 "working tree. Please, commit them\n"
4236 "first and then run 'git rebase "
4237 "--continue' again."));
Johannes Schindelin15ef6932018-04-27 22:48:30 +02004238 /*
4239 * When skipping a failed fixup/squash, we need to edit the
4240 * commit message, the current fixup list and count, and if it
4241 * was the last fixup/squash in the chain, we need to clean up
4242 * the commit message and if there was a squash, let the user
4243 * edit it.
4244 */
Johannes Schindelin10d2f352018-08-31 16:45:04 -07004245 if (!is_clean || !opts->current_fixup_count)
4246 ; /* this is not the final fixup */
Junio C Hamano87ae8a12018-09-24 10:30:45 -07004247 else if (!oideq(&head, &to_amend) ||
Johannes Schindelin10d2f352018-08-31 16:45:04 -07004248 !file_exists(rebase_path_stopped_sha())) {
4249 /* was a final fixup or squash done manually? */
4250 if (!is_fixup(peek_command(todo_list, 0))) {
4251 unlink(rebase_path_fixup_msg());
4252 unlink(rebase_path_squash_msg());
4253 unlink(rebase_path_current_fixups());
4254 strbuf_reset(&opts->current_fixups);
4255 opts->current_fixup_count = 0;
4256 }
4257 } else {
4258 /* we are in a fixup/squash chain */
Johannes Schindelin15ef6932018-04-27 22:48:30 +02004259 const char *p = opts->current_fixups.buf;
4260 int len = opts->current_fixups.len;
4261
4262 opts->current_fixup_count--;
4263 if (!len)
4264 BUG("Incorrect current_fixups:\n%s", p);
4265 while (len && p[len - 1] != '\n')
4266 len--;
4267 strbuf_setlen(&opts->current_fixups, len);
4268 if (write_message(p, len, rebase_path_current_fixups(),
4269 0) < 0)
4270 return error(_("could not write file: '%s'"),
4271 rebase_path_current_fixups());
4272
4273 /*
4274 * If a fixup/squash in a fixup/squash chain failed, the
4275 * commit message is already correct, no need to commit
4276 * it again.
4277 *
4278 * Only if it is the final command in the fixup/squash
4279 * chain, and only if the chain is longer than a single
4280 * fixup/squash command (which was just skipped), do we
4281 * actually need to re-commit with a cleaned up commit
4282 * message.
4283 */
4284 if (opts->current_fixup_count > 0 &&
4285 !is_fixup(peek_command(todo_list, 0))) {
4286 final_fixup = 1;
4287 /*
4288 * If there was not a single "squash" in the
4289 * chain, we only need to clean up the commit
4290 * message, no need to bother the user with
4291 * opening the commit message in the editor.
4292 */
4293 if (!starts_with(p, "squash ") &&
4294 !strstr(p, "\nsquash "))
4295 flags = (flags & ~EDIT_MSG) | CLEANUP_MSG;
4296 } else if (is_fixup(peek_command(todo_list, 0))) {
4297 /*
4298 * We need to update the squash message to skip
4299 * the latest commit message.
4300 */
4301 struct commit *commit;
4302 const char *path = rebase_path_squash_msg();
Doan Tran Cong Danhb3757442019-11-08 16:43:48 +07004303 const char *encoding = get_commit_output_encoding();
Johannes Schindelin15ef6932018-04-27 22:48:30 +02004304
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01004305 if (parse_head(r, &commit) ||
Doan Tran Cong Danhb3757442019-11-08 16:43:48 +07004306 !(p = logmsg_reencode(commit, NULL, encoding)) ||
Johannes Schindelin15ef6932018-04-27 22:48:30 +02004307 write_message(p, strlen(p), path, 0)) {
4308 unuse_commit_buffer(commit, p);
4309 return error(_("could not write file: "
4310 "'%s'"), path);
4311 }
4312 unuse_commit_buffer(commit, p);
4313 }
4314 }
Johannes Schindelin9d93ccd2017-01-02 16:27:21 +01004315
4316 strbuf_release(&rev);
Johannes Schindelin789b3ef2017-03-23 17:07:11 +01004317 flags |= AMEND_MSG;
Johannes Schindelin9d93ccd2017-01-02 16:27:21 +01004318 }
4319
Johannes Schindelin15ef6932018-04-27 22:48:30 +02004320 if (is_clean) {
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01004321 const char *cherry_pick_head = git_path_cherry_pick_head(r);
Johannes Schindelin15ef6932018-04-27 22:48:30 +02004322
4323 if (file_exists(cherry_pick_head) && unlink(cherry_pick_head))
4324 return error(_("could not remove CHERRY_PICK_HEAD"));
4325 if (!final_fixup)
4326 return 0;
4327 }
4328
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01004329 if (run_git_commit(r, final_fixup ? NULL : rebase_path_message(),
Johannes Schindelin15ef6932018-04-27 22:48:30 +02004330 opts, flags))
Johannes Schindelin9d93ccd2017-01-02 16:27:21 +01004331 return error(_("could not commit staged changes."));
4332 unlink(rebase_path_amend());
Nguyễn Thái Ngọc Duy34e77712019-06-27 16:28:52 +07004333 unlink(git_path_merge_head(r));
Johannes Schindelin15ef6932018-04-27 22:48:30 +02004334 if (final_fixup) {
4335 unlink(rebase_path_fixup_msg());
4336 unlink(rebase_path_squash_msg());
4337 }
4338 if (opts->current_fixup_count > 0) {
4339 /*
4340 * Whether final fixup or not, we just cleaned up the commit
4341 * message...
4342 */
4343 unlink(rebase_path_current_fixups());
4344 strbuf_reset(&opts->current_fixups);
4345 opts->current_fixup_count = 0;
4346 }
Johannes Schindelin9d93ccd2017-01-02 16:27:21 +01004347 return 0;
4348}
4349
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01004350int sequencer_continue(struct repository *r, struct replay_opts *opts)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05304351{
Johannes Schindelin004fefa2016-10-21 14:24:41 +02004352 struct todo_list todo_list = TODO_LIST_INIT;
4353 int res;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05304354
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01004355 if (read_and_refresh_cache(r, opts))
Johannes Schindelin28635842016-10-21 14:24:55 +02004356 return -1;
4357
Johannes Schindelin15ef6932018-04-27 22:48:30 +02004358 if (read_populate_opts(opts))
4359 return -1;
Johannes Schindelin9d93ccd2017-01-02 16:27:21 +01004360 if (is_rebase_i(opts)) {
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01004361 if ((res = read_populate_todo(r, &todo_list, opts)))
Johannes Schindelin15ef6932018-04-27 22:48:30 +02004362 goto release_todo_list;
Alban Gruin5a5445d2020-01-28 22:12:46 +01004363
4364 if (file_exists(rebase_path_dropped())) {
4365 if ((res = todo_list_check_against_backup(r, &todo_list)))
4366 goto release_todo_list;
4367
4368 unlink(rebase_path_dropped());
4369 }
4370
Alban Gruinf6b94132019-11-29 00:02:03 +01004371 if (commit_staged_changes(r, opts, &todo_list)) {
4372 res = -1;
4373 goto release_todo_list;
4374 }
Johannes Schindelin4258a6d2017-01-02 16:27:30 +01004375 } else if (!file_exists(get_todo_path(opts)))
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01004376 return continue_single_pick(r);
4377 else if ((res = read_populate_todo(r, &todo_list, opts)))
Johannes Schindelin004fefa2016-10-21 14:24:41 +02004378 goto release_todo_list;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05304379
Johannes Schindelin4258a6d2017-01-02 16:27:30 +01004380 if (!is_rebase_i(opts)) {
4381 /* Verify that the conflict has been resolved */
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01004382 if (file_exists(git_path_cherry_pick_head(r)) ||
4383 file_exists(git_path_revert_head(r))) {
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01004384 res = continue_single_pick(r);
Johannes Schindelin4258a6d2017-01-02 16:27:30 +01004385 if (res)
4386 goto release_todo_list;
4387 }
Nguyễn Thái Ngọc Duyffc00a42018-11-10 06:49:04 +01004388 if (index_differs_from(r, "HEAD", NULL, 0)) {
Nguyễn Thái Ngọc Duye1ff0a32019-01-12 09:13:26 +07004389 res = error_dirty_index(r, opts);
Johannes Schindelin004fefa2016-10-21 14:24:41 +02004390 goto release_todo_list;
Johannes Schindelin4258a6d2017-01-02 16:27:30 +01004391 }
4392 todo_list.current++;
Johannes Schindelinca98c6d2017-01-02 16:28:20 +01004393 } else if (file_exists(rebase_path_stopped_sha())) {
4394 struct strbuf buf = STRBUF_INIT;
4395 struct object_id oid;
4396
Denton Liu3442c3d2020-04-07 10:27:52 -04004397 if (read_oneliner(&buf, rebase_path_stopped_sha(),
4398 READ_ONELINER_SKIP_IF_EMPTY) &&
brian m. carlsone82caf32017-07-13 23:49:28 +00004399 !get_oid_committish(buf.buf, &oid))
Johannes Schindelinca98c6d2017-01-02 16:28:20 +01004400 record_in_rewritten(&oid, peek_command(&todo_list, 0));
4401 strbuf_release(&buf);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05304402 }
Johannes Schindelin4258a6d2017-01-02 16:27:30 +01004403
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01004404 res = pick_commits(r, &todo_list, opts);
Johannes Schindelin004fefa2016-10-21 14:24:41 +02004405release_todo_list:
4406 todo_list_release(&todo_list);
4407 return res;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05304408}
4409
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01004410static int single_pick(struct repository *r,
4411 struct commit *cmit,
4412 struct replay_opts *opts)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05304413{
Phillip Wooda47ba3c2019-08-19 02:18:22 -07004414 int check_todo;
4415
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05304416 setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01004417 return do_pick_commit(r, opts->action == REPLAY_PICK ?
Phillip Wooda47ba3c2019-08-19 02:18:22 -07004418 TODO_PICK : TODO_REVERT, cmit, opts, 0,
4419 &check_todo);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05304420}
4421
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01004422int sequencer_pick_revisions(struct repository *r,
4423 struct replay_opts *opts)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05304424{
Johannes Schindelin004fefa2016-10-21 14:24:41 +02004425 struct todo_list todo_list = TODO_LIST_INIT;
brian m. carlson1e43ed92017-05-06 22:10:09 +00004426 struct object_id oid;
Johannes Schindelin004fefa2016-10-21 14:24:41 +02004427 int i, res;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05304428
Johannes Schindelin28635842016-10-21 14:24:55 +02004429 assert(opts->revs);
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01004430 if (read_and_refresh_cache(r, opts))
Johannes Schindelin0d9c6dc2016-09-09 16:37:21 +02004431 return -1;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05304432
Miklos Vajna21246db2013-04-11 15:06:52 +02004433 for (i = 0; i < opts->revs->pending.nr; i++) {
brian m. carlson1e43ed92017-05-06 22:10:09 +00004434 struct object_id oid;
Miklos Vajna21246db2013-04-11 15:06:52 +02004435 const char *name = opts->revs->pending.objects[i].name;
4436
4437 /* This happens when using --stdin. */
4438 if (!strlen(name))
4439 continue;
4440
brian m. carlson1e43ed92017-05-06 22:10:09 +00004441 if (!get_oid(name, &oid)) {
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01004442 if (!lookup_commit_reference_gently(r, &oid, 1)) {
4443 enum object_type type = oid_object_info(r,
Stefan Beller0df8e962018-04-25 11:20:59 -07004444 &oid,
brian m. carlsonabef9022018-03-12 02:27:46 +00004445 NULL);
Johannes Schindelinb9b946d2016-08-26 15:47:10 +02004446 return error(_("%s: can't cherry-pick a %s"),
Brandon Williamsdebca9d2018-02-14 10:59:24 -08004447 name, type_name(type));
Junio C Hamano7c0b0d82013-05-09 13:27:49 -07004448 }
Miklos Vajna21246db2013-04-11 15:06:52 +02004449 } else
Johannes Schindelinb9b946d2016-08-26 15:47:10 +02004450 return error(_("%s: bad revision"), name);
Miklos Vajna21246db2013-04-11 15:06:52 +02004451 }
4452
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05304453 /*
4454 * If we were called as "git cherry-pick <commit>", just
4455 * cherry-pick/revert it, set CHERRY_PICK_HEAD /
4456 * REVERT_HEAD, and don't touch the sequencer state.
4457 * This means it is possible to cherry-pick in the middle
4458 * of a cherry-pick sequence.
4459 */
4460 if (opts->revs->cmdline.nr == 1 &&
4461 opts->revs->cmdline.rev->whence == REV_CMD_REV &&
4462 opts->revs->no_walk &&
4463 !opts->revs->cmdline.rev->flags) {
4464 struct commit *cmit;
4465 if (prepare_revision_walk(opts->revs))
Johannes Schindelinb9b946d2016-08-26 15:47:10 +02004466 return error(_("revision walk setup failed"));
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05304467 cmit = get_revision(opts->revs);
Jeff Kingc5e358d2018-07-10 00:32:08 -04004468 if (!cmit)
4469 return error(_("empty commit set passed"));
4470 if (get_revision(opts->revs))
4471 BUG("unexpected extra commit from walk");
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01004472 return single_pick(r, cmit, opts);
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05304473 }
4474
4475 /*
4476 * Start a new cherry-pick/ revert sequence; but
4477 * first, make sure that an existing one isn't in
4478 * progress
4479 */
4480
Johannes Schindelin34b05282016-09-09 16:37:15 +02004481 if (walk_revs_populate_todo(&todo_list, opts) ||
Rohit Ashiwal6a1f9042019-07-02 14:41:25 +05304482 create_seq_dir(r) < 0)
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05304483 return -1;
brian m. carlson1e43ed92017-05-06 22:10:09 +00004484 if (get_oid("HEAD", &oid) && (opts->action == REPLAY_REVERT))
Johannes Schindelin93b3df62016-10-21 14:26:25 +02004485 return error(_("can't revert as initial commit"));
brian m. carlson1e43ed92017-05-06 22:10:09 +00004486 if (save_head(oid_to_hex(&oid)))
Johannes Schindelin311fd392016-09-09 16:37:47 +02004487 return -1;
Johannes Schindelin88d5a272016-09-09 16:37:53 +02004488 if (save_opts(opts))
4489 return -1;
Stephan Beyer1e412292016-12-07 22:51:32 +01004490 update_abort_safety_file();
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01004491 res = pick_commits(r, &todo_list, opts);
Johannes Schindelin004fefa2016-10-21 14:24:41 +02004492 todo_list_release(&todo_list);
4493 return res;
Ramkumar Ramachandra043a4492012-01-11 23:45:57 +05304494}
Miklos Vajna5ed75e22012-09-14 08:52:03 +02004495
Jeff King66e83d92018-08-22 20:50:51 -04004496void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag)
Miklos Vajna5ed75e22012-09-14 08:52:03 +02004497{
Brandon Caseybab4d102013-02-12 02:17:35 -08004498 unsigned no_dup_sob = flag & APPEND_SIGNOFF_DEDUP;
Miklos Vajna5ed75e22012-09-14 08:52:03 +02004499 struct strbuf sob = STRBUF_INIT;
Brandon Caseybab4d102013-02-12 02:17:35 -08004500 int has_footer;
Miklos Vajna5ed75e22012-09-14 08:52:03 +02004501
4502 strbuf_addstr(&sob, sign_off_header);
William Hubbs39ab4d02019-02-04 12:48:50 -06004503 strbuf_addstr(&sob, fmt_name(WANT_COMMITTER_IDENT));
Miklos Vajna5ed75e22012-09-14 08:52:03 +02004504 strbuf_addch(&sob, '\n');
Brandon Caseybab4d102013-02-12 02:17:35 -08004505
Jonathan Tan44dc7382017-04-26 13:50:03 -07004506 if (!ignore_footer)
4507 strbuf_complete_line(msgbuf);
4508
Brandon Caseybab4d102013-02-12 02:17:35 -08004509 /*
4510 * If the whole message buffer is equal to the sob, pretend that we
4511 * found a conforming footer with a matching sob
4512 */
4513 if (msgbuf->len - ignore_footer == sob.len &&
4514 !strncmp(msgbuf->buf, sob.buf, sob.len))
4515 has_footer = 3;
4516 else
4517 has_footer = has_conforming_footer(msgbuf, &sob, ignore_footer);
4518
Brandon Casey33f2f9a2013-02-12 02:33:42 -08004519 if (!has_footer) {
4520 const char *append_newlines = NULL;
4521 size_t len = msgbuf->len - ignore_footer;
4522
Brandon Casey8c613fd2013-02-22 14:05:27 -08004523 if (!len) {
4524 /*
4525 * The buffer is completely empty. Leave foom for
4526 * the title and body to be filled in by the user.
4527 */
Brandon Casey33f2f9a2013-02-12 02:33:42 -08004528 append_newlines = "\n\n";
Brandon Casey8c613fd2013-02-22 14:05:27 -08004529 } else if (len == 1) {
4530 /*
4531 * Buffer contains a single newline. Add another
4532 * so that we leave room for the title and body.
4533 */
Brandon Casey33f2f9a2013-02-12 02:33:42 -08004534 append_newlines = "\n";
Brandon Casey8c613fd2013-02-22 14:05:27 -08004535 } else if (msgbuf->buf[len - 2] != '\n') {
4536 /*
4537 * Buffer ends with a single newline. Add another
4538 * so that there is an empty line between the message
4539 * body and the sob.
4540 */
4541 append_newlines = "\n";
4542 } /* else, the buffer already ends with two newlines. */
Brandon Casey33f2f9a2013-02-12 02:33:42 -08004543
4544 if (append_newlines)
4545 strbuf_splice(msgbuf, msgbuf->len - ignore_footer, 0,
4546 append_newlines, strlen(append_newlines));
Miklos Vajna5ed75e22012-09-14 08:52:03 +02004547 }
Brandon Caseybab4d102013-02-12 02:17:35 -08004548
4549 if (has_footer != 3 && (!no_dup_sob || has_footer != 2))
4550 strbuf_splice(msgbuf, msgbuf->len - ignore_footer, 0,
4551 sob.buf, sob.len);
4552
Miklos Vajna5ed75e22012-09-14 08:52:03 +02004553 strbuf_release(&sob);
4554}
Johannes Schindelin62db5242017-07-14 16:44:58 +02004555
Johannes Schindelin1644c732018-04-25 14:29:03 +02004556struct labels_entry {
4557 struct hashmap_entry entry;
4558 char label[FLEX_ARRAY];
4559};
4560
Eric Wong939af162019-10-06 23:30:37 +00004561static int labels_cmp(const void *fndata, const struct hashmap_entry *eptr,
4562 const struct hashmap_entry *entry_or_key, const void *key)
Johannes Schindelin1644c732018-04-25 14:29:03 +02004563{
Eric Wong939af162019-10-06 23:30:37 +00004564 const struct labels_entry *a, *b;
4565
4566 a = container_of(eptr, const struct labels_entry, entry);
4567 b = container_of(entry_or_key, const struct labels_entry, entry);
4568
Johannes Schindelin1644c732018-04-25 14:29:03 +02004569 return key ? strcmp(a->label, key) : strcmp(a->label, b->label);
4570}
4571
4572struct string_entry {
4573 struct oidmap_entry entry;
4574 char string[FLEX_ARRAY];
4575};
4576
4577struct label_state {
4578 struct oidmap commit2label;
4579 struct hashmap labels;
4580 struct strbuf buf;
4581};
4582
4583static const char *label_oid(struct object_id *oid, const char *label,
4584 struct label_state *state)
4585{
4586 struct labels_entry *labels_entry;
4587 struct string_entry *string_entry;
4588 struct object_id dummy;
Johannes Schindelin1644c732018-04-25 14:29:03 +02004589 int i;
4590
4591 string_entry = oidmap_get(&state->commit2label, oid);
4592 if (string_entry)
4593 return string_entry->string;
4594
4595 /*
4596 * For "uninteresting" commits, i.e. commits that are not to be
4597 * rebased, and which can therefore not be labeled, we use a unique
4598 * abbreviation of the commit name. This is slightly more complicated
4599 * than calling find_unique_abbrev() because we also need to make
4600 * sure that the abbreviation does not conflict with any other
4601 * label.
4602 *
4603 * We disallow "interesting" commits to be labeled by a string that
4604 * is a valid full-length hash, to ensure that we always can find an
4605 * abbreviation for any uninteresting commit's names that does not
4606 * clash with any other label.
4607 */
Johannes Schindelin867bc1d2019-11-17 23:16:09 +00004608 strbuf_reset(&state->buf);
Johannes Schindelin1644c732018-04-25 14:29:03 +02004609 if (!label) {
4610 char *p;
4611
brian m. carlson4439c7a2019-08-18 20:04:16 +00004612 strbuf_grow(&state->buf, GIT_MAX_HEXSZ);
Johannes Schindelin1644c732018-04-25 14:29:03 +02004613 label = p = state->buf.buf;
4614
4615 find_unique_abbrev_r(p, oid, default_abbrev);
4616
4617 /*
4618 * We may need to extend the abbreviated hash so that there is
4619 * no conflicting label.
4620 */
4621 if (hashmap_get_from_hash(&state->labels, strihash(p), p)) {
4622 size_t i = strlen(p) + 1;
4623
4624 oid_to_hex_r(p, oid);
brian m. carlson4439c7a2019-08-18 20:04:16 +00004625 for (; i < the_hash_algo->hexsz; i++) {
Johannes Schindelin1644c732018-04-25 14:29:03 +02004626 char save = p[i];
4627 p[i] = '\0';
4628 if (!hashmap_get_from_hash(&state->labels,
4629 strihash(p), p))
4630 break;
4631 p[i] = save;
4632 }
4633 }
Johannes Schindelin867bc1d2019-11-17 23:16:09 +00004634 } else {
Johannes Schindelin1644c732018-04-25 14:29:03 +02004635 struct strbuf *buf = &state->buf;
4636
Matthew Rogerscd552222019-11-17 23:16:10 +00004637 /*
4638 * Sanitize labels by replacing non-alpha-numeric characters
4639 * (including white-space ones) by dashes, as they might be
4640 * illegal in file names (and hence in ref names).
4641 *
4642 * Note that we retain non-ASCII UTF-8 characters (identified
4643 * via the most significant bit). They should be all acceptable
4644 * in file names. We do not validate the UTF-8 here, that's not
4645 * the job of this function.
4646 */
Johannes Schindelin867bc1d2019-11-17 23:16:09 +00004647 for (; *label; label++)
Matthew Rogerscd552222019-11-17 23:16:10 +00004648 if ((*label & 0x80) || isalnum(*label))
4649 strbuf_addch(buf, *label);
4650 /* avoid leading dash and double-dashes */
4651 else if (buf->len && buf->buf[buf->len - 1] != '-')
4652 strbuf_addch(buf, '-');
4653 if (!buf->len) {
4654 strbuf_addstr(buf, "rev-");
4655 strbuf_add_unique_abbrev(buf, oid, default_abbrev);
Johannes Schindelin1644c732018-04-25 14:29:03 +02004656 }
Johannes Schindelin1644c732018-04-25 14:29:03 +02004657 label = buf->buf;
Johannes Schindelin867bc1d2019-11-17 23:16:09 +00004658
4659 if ((buf->len == the_hash_algo->hexsz &&
4660 !get_oid_hex(label, &dummy)) ||
4661 (buf->len == 1 && *label == '#') ||
4662 hashmap_get_from_hash(&state->labels,
4663 strihash(label), label)) {
4664 /*
4665 * If the label already exists, or if the label is a
4666 * valid full OID, or the label is a '#' (which we use
4667 * as a separator between merge heads and oneline), we
4668 * append a dash and a number to make it unique.
4669 */
4670 size_t len = buf->len;
4671
4672 for (i = 2; ; i++) {
4673 strbuf_setlen(buf, len);
4674 strbuf_addf(buf, "-%d", i);
4675 if (!hashmap_get_from_hash(&state->labels,
4676 strihash(buf->buf),
4677 buf->buf))
4678 break;
4679 }
4680
4681 label = buf->buf;
4682 }
Johannes Schindelin1644c732018-04-25 14:29:03 +02004683 }
4684
4685 FLEX_ALLOC_STR(labels_entry, label, label);
Eric Wongd22245a2019-10-06 23:30:27 +00004686 hashmap_entry_init(&labels_entry->entry, strihash(label));
Eric Wongb94e5c12019-10-06 23:30:29 +00004687 hashmap_add(&state->labels, &labels_entry->entry);
Johannes Schindelin1644c732018-04-25 14:29:03 +02004688
4689 FLEX_ALLOC_STR(string_entry, string, label);
4690 oidcpy(&string_entry->entry.oid, oid);
4691 oidmap_put(&state->commit2label, string_entry);
4692
4693 return string_entry->string;
4694}
4695
4696static int make_script_with_merges(struct pretty_print_context *pp,
Alban Gruind358fc22019-03-05 20:17:56 +01004697 struct rev_info *revs, struct strbuf *out,
Johannes Schindelin1644c732018-04-25 14:29:03 +02004698 unsigned flags)
4699{
Elijah Newrenb9cbd292020-04-11 02:44:25 +00004700 int keep_empty = flags & TODO_LIST_KEEP_EMPTY;
Johannes Schindelin7543f6f2018-04-25 14:29:40 +02004701 int rebase_cousins = flags & TODO_LIST_REBASE_COUSINS;
Johannes Schindeline1fac532019-07-31 08:18:49 -07004702 int root_with_onto = flags & TODO_LIST_ROOT_WITH_ONTO;
Johannes Schindelin1644c732018-04-25 14:29:03 +02004703 struct strbuf buf = STRBUF_INIT, oneline = STRBUF_INIT;
4704 struct strbuf label = STRBUF_INIT;
4705 struct commit_list *commits = NULL, **tail = &commits, *iter;
4706 struct commit_list *tips = NULL, **tips_tail = &tips;
4707 struct commit *commit;
4708 struct oidmap commit2todo = OIDMAP_INIT;
4709 struct string_entry *entry;
4710 struct oidset interesting = OIDSET_INIT, child_seen = OIDSET_INIT,
4711 shown = OIDSET_INIT;
4712 struct label_state state = { OIDMAP_INIT, { NULL }, STRBUF_INIT };
4713
4714 int abbr = flags & TODO_LIST_ABBREVIATE_CMDS;
4715 const char *cmd_pick = abbr ? "p" : "pick",
4716 *cmd_label = abbr ? "l" : "label",
4717 *cmd_reset = abbr ? "t" : "reset",
4718 *cmd_merge = abbr ? "m" : "merge";
4719
4720 oidmap_init(&commit2todo, 0);
4721 oidmap_init(&state.commit2label, 0);
Eric Wong939af162019-10-06 23:30:37 +00004722 hashmap_init(&state.labels, labels_cmp, NULL, 0);
Johannes Schindelin1644c732018-04-25 14:29:03 +02004723 strbuf_init(&state.buf, 32);
4724
4725 if (revs->cmdline.nr && (revs->cmdline.rev[0].flags & BOTTOM)) {
Doan Tran Cong Danhe02058a2019-11-18 18:57:47 +07004726 struct labels_entry *onto_label_entry;
Johannes Schindelin1644c732018-04-25 14:29:03 +02004727 struct object_id *oid = &revs->cmdline.rev[0].item->oid;
4728 FLEX_ALLOC_STR(entry, string, "onto");
4729 oidcpy(&entry->entry.oid, oid);
4730 oidmap_put(&state.commit2label, entry);
Doan Tran Cong Danhe02058a2019-11-18 18:57:47 +07004731
4732 FLEX_ALLOC_STR(onto_label_entry, label, "onto");
4733 hashmap_entry_init(&onto_label_entry->entry, strihash("onto"));
4734 hashmap_add(&state.labels, &onto_label_entry->entry);
Johannes Schindelin1644c732018-04-25 14:29:03 +02004735 }
4736
4737 /*
4738 * First phase:
4739 * - get onelines for all commits
4740 * - gather all branch tips (i.e. 2nd or later parents of merges)
4741 * - label all branch tips
4742 */
4743 while ((commit = get_revision(revs))) {
4744 struct commit_list *to_merge;
Johannes Schindelin1644c732018-04-25 14:29:03 +02004745 const char *p1, *p2;
4746 struct object_id *oid;
4747 int is_empty;
4748
4749 tail = &commit_list_insert(commit, tail)->next;
4750 oidset_insert(&interesting, &commit->object.oid);
4751
4752 is_empty = is_original_commit_empty(commit);
4753 if (!is_empty && (commit->object.flags & PATCHSAME))
4754 continue;
Elijah Newrenb9cbd292020-04-11 02:44:25 +00004755 if (is_empty && !keep_empty)
4756 continue;
Johannes Schindelin1644c732018-04-25 14:29:03 +02004757
4758 strbuf_reset(&oneline);
4759 pretty_print_commit(pp, commit, &oneline);
4760
4761 to_merge = commit->parents ? commit->parents->next : NULL;
4762 if (!to_merge) {
4763 /* non-merge commit: easy case */
4764 strbuf_reset(&buf);
Johannes Schindelin1644c732018-04-25 14:29:03 +02004765 strbuf_addf(&buf, "%s %s %s", cmd_pick,
4766 oid_to_hex(&commit->object.oid),
4767 oneline.buf);
Elijah Newren1b5735f2020-04-11 02:44:24 +00004768 if (is_empty)
4769 strbuf_addf(&buf, " %c empty",
4770 comment_line_char);
Johannes Schindelin1644c732018-04-25 14:29:03 +02004771
4772 FLEX_ALLOC_STR(entry, string, buf.buf);
4773 oidcpy(&entry->entry.oid, &commit->object.oid);
4774 oidmap_put(&commit2todo, entry);
4775
4776 continue;
4777 }
4778
Johannes Schindelin1644c732018-04-25 14:29:03 +02004779 /* Create a label */
4780 strbuf_reset(&label);
4781 if (skip_prefix(oneline.buf, "Merge ", &p1) &&
4782 (p1 = strchr(p1, '\'')) &&
4783 (p2 = strchr(++p1, '\'')))
4784 strbuf_add(&label, p1, p2 - p1);
4785 else if (skip_prefix(oneline.buf, "Merge pull request ",
4786 &p1) &&
4787 (p1 = strstr(p1, " from ")))
4788 strbuf_addstr(&label, p1 + strlen(" from "));
4789 else
4790 strbuf_addbuf(&label, &oneline);
4791
Johannes Schindelin1644c732018-04-25 14:29:03 +02004792 strbuf_reset(&buf);
4793 strbuf_addf(&buf, "%s -C %s",
4794 cmd_merge, oid_to_hex(&commit->object.oid));
4795
Johannes Schindelin2b6ad0f2017-12-21 15:52:45 +01004796 /* label the tips of merged branches */
4797 for (; to_merge; to_merge = to_merge->next) {
4798 oid = &to_merge->item->object.oid;
4799 strbuf_addch(&buf, ' ');
Johannes Schindelin1644c732018-04-25 14:29:03 +02004800
Johannes Schindelin2b6ad0f2017-12-21 15:52:45 +01004801 if (!oidset_contains(&interesting, oid)) {
4802 strbuf_addstr(&buf, label_oid(oid, NULL,
4803 &state));
4804 continue;
4805 }
4806
Johannes Schindelin1644c732018-04-25 14:29:03 +02004807 tips_tail = &commit_list_insert(to_merge->item,
4808 tips_tail)->next;
4809
4810 strbuf_addstr(&buf, label_oid(oid, label.buf, &state));
4811 }
4812 strbuf_addf(&buf, " # %s", oneline.buf);
4813
4814 FLEX_ALLOC_STR(entry, string, buf.buf);
4815 oidcpy(&entry->entry.oid, &commit->object.oid);
4816 oidmap_put(&commit2todo, entry);
4817 }
4818
4819 /*
4820 * Second phase:
4821 * - label branch points
4822 * - add HEAD to the branch tips
4823 */
4824 for (iter = commits; iter; iter = iter->next) {
4825 struct commit_list *parent = iter->item->parents;
4826 for (; parent; parent = parent->next) {
4827 struct object_id *oid = &parent->item->object.oid;
4828 if (!oidset_contains(&interesting, oid))
4829 continue;
René Scharfe6e8fc702018-10-03 15:06:49 +02004830 if (oidset_insert(&child_seen, oid))
Johannes Schindelin1644c732018-04-25 14:29:03 +02004831 label_oid(oid, "branch-point", &state);
4832 }
4833
Elijah Newren15beaaa2019-11-05 17:07:23 +00004834 /* Add HEAD as implicit "tip of branch" */
Johannes Schindelin1644c732018-04-25 14:29:03 +02004835 if (!iter->next)
4836 tips_tail = &commit_list_insert(iter->item,
4837 tips_tail)->next;
4838 }
4839
4840 /*
4841 * Third phase: output the todo list. This is a bit tricky, as we
4842 * want to avoid jumping back and forth between revisions. To
4843 * accomplish that goal, we walk backwards from the branch tips,
4844 * gathering commits not yet shown, reversing the list on the fly,
4845 * then outputting that list (labeling revisions as needed).
4846 */
Alban Gruind358fc22019-03-05 20:17:56 +01004847 strbuf_addf(out, "%s onto\n", cmd_label);
Johannes Schindelin1644c732018-04-25 14:29:03 +02004848 for (iter = tips; iter; iter = iter->next) {
4849 struct commit_list *list = NULL, *iter2;
4850
4851 commit = iter->item;
4852 if (oidset_contains(&shown, &commit->object.oid))
4853 continue;
4854 entry = oidmap_get(&state.commit2label, &commit->object.oid);
4855
4856 if (entry)
Alban Gruind358fc22019-03-05 20:17:56 +01004857 strbuf_addf(out, "\n%c Branch %s\n", comment_line_char, entry->string);
Johannes Schindelin1644c732018-04-25 14:29:03 +02004858 else
Alban Gruind358fc22019-03-05 20:17:56 +01004859 strbuf_addch(out, '\n');
Johannes Schindelin1644c732018-04-25 14:29:03 +02004860
4861 while (oidset_contains(&interesting, &commit->object.oid) &&
4862 !oidset_contains(&shown, &commit->object.oid)) {
4863 commit_list_insert(commit, &list);
4864 if (!commit->parents) {
4865 commit = NULL;
4866 break;
4867 }
4868 commit = commit->parents->item;
4869 }
4870
4871 if (!commit)
Alban Gruind358fc22019-03-05 20:17:56 +01004872 strbuf_addf(out, "%s %s\n", cmd_reset,
Johannes Schindeline1fac532019-07-31 08:18:49 -07004873 rebase_cousins || root_with_onto ?
4874 "onto" : "[new root]");
Johannes Schindelin1644c732018-04-25 14:29:03 +02004875 else {
4876 const char *to = NULL;
4877
4878 entry = oidmap_get(&state.commit2label,
4879 &commit->object.oid);
4880 if (entry)
4881 to = entry->string;
Johannes Schindelin7543f6f2018-04-25 14:29:40 +02004882 else if (!rebase_cousins)
4883 to = label_oid(&commit->object.oid, NULL,
4884 &state);
Johannes Schindelin1644c732018-04-25 14:29:03 +02004885
4886 if (!to || !strcmp(to, "onto"))
Alban Gruind358fc22019-03-05 20:17:56 +01004887 strbuf_addf(out, "%s onto\n", cmd_reset);
Johannes Schindelin1644c732018-04-25 14:29:03 +02004888 else {
4889 strbuf_reset(&oneline);
4890 pretty_print_commit(pp, commit, &oneline);
Alban Gruind358fc22019-03-05 20:17:56 +01004891 strbuf_addf(out, "%s %s # %s\n",
4892 cmd_reset, to, oneline.buf);
Johannes Schindelin1644c732018-04-25 14:29:03 +02004893 }
4894 }
4895
4896 for (iter2 = list; iter2; iter2 = iter2->next) {
4897 struct object_id *oid = &iter2->item->object.oid;
4898 entry = oidmap_get(&commit2todo, oid);
4899 /* only show if not already upstream */
4900 if (entry)
Alban Gruind358fc22019-03-05 20:17:56 +01004901 strbuf_addf(out, "%s\n", entry->string);
Johannes Schindelin1644c732018-04-25 14:29:03 +02004902 entry = oidmap_get(&state.commit2label, oid);
4903 if (entry)
Alban Gruind358fc22019-03-05 20:17:56 +01004904 strbuf_addf(out, "%s %s\n",
4905 cmd_label, entry->string);
Johannes Schindelin1644c732018-04-25 14:29:03 +02004906 oidset_insert(&shown, oid);
4907 }
4908
4909 free_commit_list(list);
4910 }
4911
4912 free_commit_list(commits);
4913 free_commit_list(tips);
4914
4915 strbuf_release(&label);
4916 strbuf_release(&oneline);
4917 strbuf_release(&buf);
4918
4919 oidmap_free(&commit2todo, 1);
4920 oidmap_free(&state.commit2label, 1);
Eric Wongc8e424c2019-10-06 23:30:40 +00004921 hashmap_free_entries(&state.labels, struct labels_entry, entry);
Johannes Schindelin1644c732018-04-25 14:29:03 +02004922 strbuf_release(&state.buf);
4923
4924 return 0;
4925}
4926
Alban Gruind358fc22019-03-05 20:17:56 +01004927int sequencer_make_script(struct repository *r, struct strbuf *out, int argc,
4928 const char **argv, unsigned flags)
Johannes Schindelin62db5242017-07-14 16:44:58 +02004929{
4930 char *format = NULL;
4931 struct pretty_print_context pp = {0};
Johannes Schindelin62db5242017-07-14 16:44:58 +02004932 struct rev_info revs;
4933 struct commit *commit;
Elijah Newrenb9cbd292020-04-11 02:44:25 +00004934 int keep_empty = flags & TODO_LIST_KEEP_EMPTY;
Liam Beguind8ae6c82017-12-05 12:52:34 -05004935 const char *insn = flags & TODO_LIST_ABBREVIATE_CMDS ? "p" : "pick";
Johannes Schindelin1644c732018-04-25 14:29:03 +02004936 int rebase_merges = flags & TODO_LIST_REBASE_MERGES;
Jonathan Tan0fcb4f62020-04-11 02:44:27 +00004937 int reapply_cherry_picks = flags & TODO_LIST_REAPPLY_CHERRY_PICKS;
Johannes Schindelin62db5242017-07-14 16:44:58 +02004938
Nguyễn Thái Ngọc Duyf11c9582018-11-10 06:48:56 +01004939 repo_init_revisions(r, &revs, NULL);
Johannes Schindelin62db5242017-07-14 16:44:58 +02004940 revs.verbose_header = 1;
Johannes Schindelin1644c732018-04-25 14:29:03 +02004941 if (!rebase_merges)
4942 revs.max_parents = 1;
Jonathan Tan0fcb4f62020-04-11 02:44:27 +00004943 revs.cherry_mark = !reapply_cherry_picks;
Johannes Schindelin62db5242017-07-14 16:44:58 +02004944 revs.limited = 1;
4945 revs.reverse = 1;
4946 revs.right_only = 1;
4947 revs.sort_order = REV_SORT_IN_GRAPH_ORDER;
4948 revs.topo_order = 1;
4949
4950 revs.pretty_given = 1;
4951 git_config_get_string("rebase.instructionFormat", &format);
4952 if (!format || !*format) {
4953 free(format);
4954 format = xstrdup("%s");
4955 }
4956 get_commit_format(format, &revs);
4957 free(format);
4958 pp.fmt = revs.commit_format;
4959 pp.output_encoding = get_log_output_encoding();
4960
4961 if (setup_revisions(argc, argv, &revs, NULL) > 1)
4962 return error(_("make_script: unhandled options"));
4963
4964 if (prepare_revision_walk(&revs) < 0)
4965 return error(_("make_script: error preparing revisions"));
4966
Johannes Schindelin1644c732018-04-25 14:29:03 +02004967 if (rebase_merges)
4968 return make_script_with_merges(&pp, &revs, out, flags);
4969
Johannes Schindelin62db5242017-07-14 16:44:58 +02004970 while ((commit = get_revision(&revs))) {
Elijah Newrend48e5e22020-02-15 21:36:24 +00004971 int is_empty = is_original_commit_empty(commit);
Phillip Wood76ea2352018-03-20 10:03:14 +00004972
4973 if (!is_empty && (commit->object.flags & PATCHSAME))
4974 continue;
Elijah Newrenb9cbd292020-04-11 02:44:25 +00004975 if (is_empty && !keep_empty)
4976 continue;
Alban Gruind358fc22019-03-05 20:17:56 +01004977 strbuf_addf(out, "%s %s ", insn,
Liam Beguind8ae6c82017-12-05 12:52:34 -05004978 oid_to_hex(&commit->object.oid));
Alban Gruind358fc22019-03-05 20:17:56 +01004979 pretty_print_commit(&pp, commit, out);
Elijah Newren1b5735f2020-04-11 02:44:24 +00004980 if (is_empty)
4981 strbuf_addf(out, " %c empty", comment_line_char);
Alban Gruind358fc22019-03-05 20:17:56 +01004982 strbuf_addch(out, '\n');
Johannes Schindelin62db5242017-07-14 16:44:58 +02004983 }
Johannes Schindelin62db5242017-07-14 16:44:58 +02004984 return 0;
4985}
Johannes Schindelin3546c8d2017-07-14 16:45:11 +02004986
Liam Beguin0cce4a22017-12-05 12:52:33 -05004987/*
4988 * Add commands after pick and (series of) squash/fixup commands
4989 * in the todo list.
4990 */
Alban Gruin1ba204d2019-03-05 20:17:58 +01004991void todo_list_add_exec_commands(struct todo_list *todo_list,
4992 struct string_list *commands)
Johannes Schindelin3546c8d2017-07-14 16:45:11 +02004993{
Alban Gruin683153a2019-03-05 20:17:54 +01004994 struct strbuf *buf = &todo_list->buf;
4995 size_t base_offset = buf->len;
4996 int i, insert, nr = 0, alloc = 0;
4997 struct todo_item *items = NULL, *base_items = NULL;
Johannes Schindelin3546c8d2017-07-14 16:45:11 +02004998
Alban Gruin683153a2019-03-05 20:17:54 +01004999 base_items = xcalloc(commands->nr, sizeof(struct todo_item));
5000 for (i = 0; i < commands->nr; i++) {
5001 size_t command_len = strlen(commands->items[i].string);
Johannes Schindelin3546c8d2017-07-14 16:45:11 +02005002
Alban Gruin683153a2019-03-05 20:17:54 +01005003 strbuf_addstr(buf, commands->items[i].string);
5004 strbuf_addch(buf, '\n');
5005
5006 base_items[i].command = TODO_EXEC;
5007 base_items[i].offset_in_buf = base_offset;
5008 base_items[i].arg_offset = base_offset + strlen("exec ");
5009 base_items[i].arg_len = command_len - strlen("exec ");
5010
5011 base_offset += command_len + 1;
Johannes Schindelin3546c8d2017-07-14 16:45:11 +02005012 }
5013
Johannes Schindelin1ace63b2018-08-09 02:41:11 -07005014 /*
5015 * Insert <commands> after every pick. Here, fixup/squash chains
5016 * are considered part of the pick, so we insert the commands *after*
5017 * those chains if there are any.
Alban Gruin683153a2019-03-05 20:17:54 +01005018 *
Elijah Newren15beaaa2019-11-05 17:07:23 +00005019 * As we insert the exec commands immediately after rearranging
Alban Gruin683153a2019-03-05 20:17:54 +01005020 * any fixups and before the user edits the list, a fixup chain
5021 * can never contain comments (any comments are empty picks that
5022 * have been commented out because the user did not specify
5023 * --keep-empty). So, it is safe to insert an exec command
5024 * without looking at the command following a comment.
Johannes Schindelin1ace63b2018-08-09 02:41:11 -07005025 */
Alban Gruin683153a2019-03-05 20:17:54 +01005026 insert = 0;
5027 for (i = 0; i < todo_list->nr; i++) {
5028 enum todo_command command = todo_list->items[i].command;
5029 if (insert && !is_fixup(command)) {
5030 ALLOC_GROW(items, nr + commands->nr, alloc);
5031 COPY_ARRAY(items + nr, base_items, commands->nr);
5032 nr += commands->nr;
Johannes Schindelin1ace63b2018-08-09 02:41:11 -07005033
Alban Gruin683153a2019-03-05 20:17:54 +01005034 insert = 0;
Johannes Schindelin3546c8d2017-07-14 16:45:11 +02005035 }
Johannes Schindelin1ace63b2018-08-09 02:41:11 -07005036
Alban Gruin683153a2019-03-05 20:17:54 +01005037 ALLOC_GROW(items, nr + 1, alloc);
5038 items[nr++] = todo_list->items[i];
5039
Johannes Schindelin1ace63b2018-08-09 02:41:11 -07005040 if (command == TODO_PICK || command == TODO_MERGE)
Alban Gruin683153a2019-03-05 20:17:54 +01005041 insert = 1;
Johannes Schindelin3546c8d2017-07-14 16:45:11 +02005042 }
Liam Beguin0cce4a22017-12-05 12:52:33 -05005043
Johannes Schindelin1ace63b2018-08-09 02:41:11 -07005044 /* insert or append final <commands> */
Alban Gruin683153a2019-03-05 20:17:54 +01005045 if (insert || nr == todo_list->nr) {
5046 ALLOC_GROW(items, nr + commands->nr, alloc);
5047 COPY_ARRAY(items + nr, base_items, commands->nr);
5048 nr += commands->nr;
Johannes Schindelin3546c8d2017-07-14 16:45:11 +02005049 }
5050
Alban Gruin683153a2019-03-05 20:17:54 +01005051 free(base_items);
5052 FREE_AND_NULL(todo_list->items);
5053 todo_list->items = items;
5054 todo_list->nr = nr;
5055 todo_list->alloc = alloc;
5056}
5057
Alban Gruin616d7742019-01-29 16:01:48 +01005058static void todo_list_to_strbuf(struct repository *r, struct todo_list *todo_list,
5059 struct strbuf *buf, int num, unsigned flags)
Johannes Schindelin3546c8d2017-07-14 16:45:11 +02005060{
Johannes Schindelin3546c8d2017-07-14 16:45:11 +02005061 struct todo_item *item;
Alban Gruin616d7742019-01-29 16:01:48 +01005062 int i, max = todo_list->nr;
Johannes Schindelin3546c8d2017-07-14 16:45:11 +02005063
Alban Gruin616d7742019-01-29 16:01:48 +01005064 if (num > 0 && num < max)
5065 max = num;
5066
5067 for (item = todo_list->items, i = 0; i < max; i++, item++) {
Alban Gruin68e70902020-03-30 14:42:35 +02005068 char cmd;
5069
Liam Beguin8dccc7a2017-12-05 12:52:30 -05005070 /* if the item is not a command write it and continue */
5071 if (item->command >= TODO_COMMENT) {
Alban Gruin616d7742019-01-29 16:01:48 +01005072 strbuf_addf(buf, "%.*s\n", item->arg_len,
Alban Gruincbef27d2019-01-29 16:01:47 +01005073 todo_item_get_arg(todo_list, item));
Liam Beguin8dccc7a2017-12-05 12:52:30 -05005074 continue;
Johannes Schindelin3546c8d2017-07-14 16:45:11 +02005075 }
Liam Beguin8dccc7a2017-12-05 12:52:30 -05005076
5077 /* add command to the buffer */
Alban Gruin68e70902020-03-30 14:42:35 +02005078 cmd = command_to_char(item->command);
5079 if ((flags & TODO_LIST_ABBREVIATE_CMDS) && cmd)
5080 strbuf_addch(buf, cmd);
Liam Beguind8ae6c82017-12-05 12:52:34 -05005081 else
Alban Gruin616d7742019-01-29 16:01:48 +01005082 strbuf_addstr(buf, command_to_string(item->command));
Liam Beguin8dccc7a2017-12-05 12:52:30 -05005083
5084 /* add commit id */
5085 if (item->commit) {
Liam Beguin313a48e2017-12-05 12:52:32 -05005086 const char *oid = flags & TODO_LIST_SHORTEN_IDS ?
Liam Beguin8dccc7a2017-12-05 12:52:30 -05005087 short_commit_name(item->commit) :
5088 oid_to_hex(&item->commit->object.oid);
5089
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02005090 if (item->command == TODO_MERGE) {
5091 if (item->flags & TODO_EDIT_MERGE_MSG)
Alban Gruin616d7742019-01-29 16:01:48 +01005092 strbuf_addstr(buf, " -c");
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02005093 else
Alban Gruin616d7742019-01-29 16:01:48 +01005094 strbuf_addstr(buf, " -C");
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02005095 }
5096
Alban Gruin616d7742019-01-29 16:01:48 +01005097 strbuf_addf(buf, " %s", oid);
Liam Beguin8dccc7a2017-12-05 12:52:30 -05005098 }
Johannes Schindelin4c68e7d2018-04-25 14:28:54 +02005099
Liam Beguin8dccc7a2017-12-05 12:52:30 -05005100 /* add all the rest */
Johannes Schindelinc7b4d792017-12-23 00:56:00 +01005101 if (!item->arg_len)
Alban Gruin616d7742019-01-29 16:01:48 +01005102 strbuf_addch(buf, '\n');
Johannes Schindelinc7b4d792017-12-23 00:56:00 +01005103 else
Alban Gruin616d7742019-01-29 16:01:48 +01005104 strbuf_addf(buf, " %.*s\n", item->arg_len,
Alban Gruincbef27d2019-01-29 16:01:47 +01005105 todo_item_get_arg(todo_list, item));
Johannes Schindelin3546c8d2017-07-14 16:45:11 +02005106 }
Johannes Schindelin3546c8d2017-07-14 16:45:11 +02005107}
Johannes Schindelin94399942017-07-14 16:45:21 +02005108
Alban Gruin616d7742019-01-29 16:01:48 +01005109int todo_list_write_to_file(struct repository *r, struct todo_list *todo_list,
5110 const char *file, const char *shortrevisions,
5111 const char *shortonto, int num, unsigned flags)
Johannes Schindelin94399942017-07-14 16:45:21 +02005112{
Alban Gruinaf1fc3a2019-03-05 20:18:02 +01005113 int res;
Alban Gruin616d7742019-01-29 16:01:48 +01005114 struct strbuf buf = STRBUF_INIT;
Johannes Schindelin94399942017-07-14 16:45:21 +02005115
Alban Gruin616d7742019-01-29 16:01:48 +01005116 todo_list_to_strbuf(r, todo_list, &buf, num, flags);
Alban Gruinaf1fc3a2019-03-05 20:18:02 +01005117 if (flags & TODO_LIST_APPEND_TODO_HELP)
Elijah Newrend48e5e22020-02-15 21:36:24 +00005118 append_todo_help(count_commands(todo_list),
Alban Gruinaf1fc3a2019-03-05 20:18:02 +01005119 shortrevisions, shortonto, &buf);
Johannes Schindelin94399942017-07-14 16:45:21 +02005120
Alban Gruin616d7742019-01-29 16:01:48 +01005121 res = write_message(buf.buf, buf.len, file, 0);
Alban Gruincbef27d2019-01-29 16:01:47 +01005122 strbuf_release(&buf);
Johannes Schindelin94399942017-07-14 16:45:21 +02005123
5124 return res;
5125}
Johannes Schindelincdac2b02017-07-14 16:45:25 +02005126
5127/* skip picking commits whose parents are unchanged */
Alban Gruin6bfeb7f2019-03-05 20:18:00 +01005128static int skip_unnecessary_picks(struct repository *r,
5129 struct todo_list *todo_list,
5130 struct object_id *base_oid)
Johannes Schindelincdac2b02017-07-14 16:45:25 +02005131{
Alban Gruind4ed5d72018-08-10 18:51:36 +02005132 struct object_id *parent_oid;
Alban Gruin6bfeb7f2019-03-05 20:18:00 +01005133 int i;
Johannes Schindelincdac2b02017-07-14 16:45:25 +02005134
Alban Gruin6bfeb7f2019-03-05 20:18:00 +01005135 for (i = 0; i < todo_list->nr; i++) {
5136 struct todo_item *item = todo_list->items + i;
Johannes Schindelincdac2b02017-07-14 16:45:25 +02005137
5138 if (item->command >= TODO_NOOP)
5139 continue;
5140 if (item->command != TODO_PICK)
5141 break;
5142 if (parse_commit(item->commit)) {
Johannes Schindelincdac2b02017-07-14 16:45:25 +02005143 return error(_("could not parse commit '%s'"),
5144 oid_to_hex(&item->commit->object.oid));
5145 }
5146 if (!item->commit->parents)
5147 break; /* root commit */
5148 if (item->commit->parents->next)
5149 break; /* merge commit */
5150 parent_oid = &item->commit->parents->item->object.oid;
Alban Gruin6bfeb7f2019-03-05 20:18:00 +01005151 if (!oideq(parent_oid, base_oid))
Johannes Schindelincdac2b02017-07-14 16:45:25 +02005152 break;
Alban Gruin6bfeb7f2019-03-05 20:18:00 +01005153 oidcpy(base_oid, &item->commit->object.oid);
Johannes Schindelincdac2b02017-07-14 16:45:25 +02005154 }
5155 if (i > 0) {
Johannes Schindelincdac2b02017-07-14 16:45:25 +02005156 const char *done_path = rebase_path_done();
5157
Alban Gruin6bfeb7f2019-03-05 20:18:00 +01005158 if (todo_list_write_to_file(r, todo_list, done_path, NULL, NULL, i, 0)) {
Johannes Schindelincdac2b02017-07-14 16:45:25 +02005159 error_errno(_("could not write to '%s'"), done_path);
Johannes Schindelincdac2b02017-07-14 16:45:25 +02005160 return -1;
5161 }
Johannes Schindelincdac2b02017-07-14 16:45:25 +02005162
Alban Gruin6bfeb7f2019-03-05 20:18:00 +01005163 MOVE_ARRAY(todo_list->items, todo_list->items + i, todo_list->nr - i);
5164 todo_list->nr -= i;
5165 todo_list->current = 0;
Alban Gruin34065542019-11-24 18:43:29 +01005166 todo_list->done_nr += i;
Alban Gruin6bfeb7f2019-03-05 20:18:00 +01005167
5168 if (is_fixup(peek_command(todo_list, 0)))
5169 record_in_rewritten(base_oid, peek_command(todo_list, 0));
Johannes Schindelincdac2b02017-07-14 16:45:25 +02005170 }
5171
Johannes Schindelincdac2b02017-07-14 16:45:25 +02005172 return 0;
5173}
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005174
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01005175int complete_action(struct repository *r, struct replay_opts *opts, unsigned flags,
Alban Gruinb97e1872018-08-28 14:10:36 +02005176 const char *shortrevisions, const char *onto_name,
Phillip Wood7d3488e2019-04-17 15:30:39 +01005177 struct commit *onto, const char *orig_head,
5178 struct string_list *commands, unsigned autosquash,
5179 struct todo_list *todo_list)
Alban Gruinb97e1872018-08-28 14:10:36 +02005180{
5181 const char *shortonto, *todo_file = rebase_path_todo();
Alban Gruin94bcad72019-03-05 20:17:57 +01005182 struct todo_list new_todo = TODO_LIST_INIT;
Johannes Schindelinb6992262020-01-23 12:28:18 +00005183 struct strbuf *buf = &todo_list->buf, buf2 = STRBUF_INIT;
Phillip Wood7d3488e2019-04-17 15:30:39 +01005184 struct object_id oid = onto->object.oid;
Alban Gruin1451d0f2019-03-05 20:18:04 +01005185 int res;
Alban Gruinb97e1872018-08-28 14:10:36 +02005186
Alban Gruinb97e1872018-08-28 14:10:36 +02005187 shortonto = find_unique_abbrev(&oid, DEFAULT_ABBREV);
5188
Alban Gruinb97e1872018-08-28 14:10:36 +02005189 if (buf->len == 0) {
Alban Gruin94bcad72019-03-05 20:17:57 +01005190 struct todo_item *item = append_new_todo(todo_list);
5191 item->command = TODO_NOOP;
5192 item->commit = NULL;
5193 item->arg_len = item->arg_offset = item->flags = item->offset_in_buf = 0;
5194 }
Alban Gruinb97e1872018-08-28 14:10:36 +02005195
Alban Gruin94bcad72019-03-05 20:17:57 +01005196 if (autosquash && todo_list_rearrange_squash(todo_list))
Alban Gruinb97e1872018-08-28 14:10:36 +02005197 return -1;
5198
Alban Gruin683153a2019-03-05 20:17:54 +01005199 if (commands->nr)
Alban Gruin94bcad72019-03-05 20:17:57 +01005200 todo_list_add_exec_commands(todo_list, commands);
Alban Gruinb97e1872018-08-28 14:10:36 +02005201
Alban Gruin94bcad72019-03-05 20:17:57 +01005202 if (count_commands(todo_list) == 0) {
Denton Liube1bb602020-04-07 10:27:56 -04005203 apply_autostash(rebase_path_autostash());
Alban Gruinb97e1872018-08-28 14:10:36 +02005204 sequencer_remove_state(opts);
Alban Gruinb97e1872018-08-28 14:10:36 +02005205
5206 return error(_("nothing to do"));
5207 }
5208
Alban Gruin1451d0f2019-03-05 20:18:04 +01005209 res = edit_todo_list(r, todo_list, &new_todo, shortrevisions,
5210 shortonto, flags);
5211 if (res == -1)
5212 return -1;
5213 else if (res == -2) {
Denton Liube1bb602020-04-07 10:27:56 -04005214 apply_autostash(rebase_path_autostash());
Alban Gruinb97e1872018-08-28 14:10:36 +02005215 sequencer_remove_state(opts);
Alban Gruinb97e1872018-08-28 14:10:36 +02005216
Alban Gruinb97e1872018-08-28 14:10:36 +02005217 return -1;
Alban Gruin1451d0f2019-03-05 20:18:04 +01005218 } else if (res == -3) {
Denton Liube1bb602020-04-07 10:27:56 -04005219 apply_autostash(rebase_path_autostash());
Alban Gruinb97e1872018-08-28 14:10:36 +02005220 sequencer_remove_state(opts);
Alban Gruin94bcad72019-03-05 20:17:57 +01005221 todo_list_release(&new_todo);
Alban Gruinb97e1872018-08-28 14:10:36 +02005222
5223 return error(_("nothing to do"));
Alban Gruin5a5445d2020-01-28 22:12:46 +01005224 } else if (res == -4) {
Phillip Wood7d3488e2019-04-17 15:30:39 +01005225 checkout_onto(r, opts, onto_name, &onto->object.oid, orig_head);
Alban Gruin94bcad72019-03-05 20:17:57 +01005226 todo_list_release(&new_todo);
5227
Alban Gruinb97e1872018-08-28 14:10:36 +02005228 return -1;
5229 }
5230
Johannes Schindelinb6992262020-01-23 12:28:18 +00005231 /* Expand the commit IDs */
5232 todo_list_to_strbuf(r, &new_todo, &buf2, -1, 0);
5233 strbuf_swap(&new_todo.buf, &buf2);
5234 strbuf_release(&buf2);
5235 new_todo.total_nr -= new_todo.nr;
5236 if (todo_list_parse_insn_buffer(r, new_todo.buf.buf, &new_todo) < 0)
5237 BUG("invalid todo list after expanding IDs:\n%s",
5238 new_todo.buf.buf);
5239
Alban Gruin6bfeb7f2019-03-05 20:18:00 +01005240 if (opts->allow_ff && skip_unnecessary_picks(r, &new_todo, &oid)) {
5241 todo_list_release(&new_todo);
Alban Gruinb97e1872018-08-28 14:10:36 +02005242 return error(_("could not skip unnecessary pick commands"));
Alban Gruin6bfeb7f2019-03-05 20:18:00 +01005243 }
5244
Alban Gruin94bcad72019-03-05 20:17:57 +01005245 if (todo_list_write_to_file(r, &new_todo, todo_file, NULL, NULL, -1,
5246 flags & ~(TODO_LIST_SHORTEN_IDS))) {
5247 todo_list_release(&new_todo);
5248 return error_errno(_("could not write '%s'"), todo_file);
5249 }
5250
Alban Gruin393adf72019-11-24 18:43:32 +01005251 res = -1;
Alban Gruinb97e1872018-08-28 14:10:36 +02005252
Phillip Wood7d3488e2019-04-17 15:30:39 +01005253 if (checkout_onto(r, opts, onto_name, &oid, orig_head))
Alban Gruin393adf72019-11-24 18:43:32 +01005254 goto cleanup;
Nguyễn Thái Ngọc Duy29d51e22018-11-03 15:32:29 +01005255
Nguyễn Thái Ngọc Duy005af332018-11-10 06:48:57 +01005256 if (require_clean_work_tree(r, "rebase", "", 1, 1))
Alban Gruin393adf72019-11-24 18:43:32 +01005257 goto cleanup;
Alban Gruinb97e1872018-08-28 14:10:36 +02005258
Alban Gruin393adf72019-11-24 18:43:32 +01005259 todo_list_write_total_nr(&new_todo);
5260 res = pick_commits(r, &new_todo, opts);
5261
5262cleanup:
5263 todo_list_release(&new_todo);
5264
5265 return res;
Alban Gruinb97e1872018-08-28 14:10:36 +02005266}
5267
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005268struct subject2item_entry {
5269 struct hashmap_entry entry;
5270 int i;
5271 char subject[FLEX_ARRAY];
5272};
5273
5274static int subject2item_cmp(const void *fndata,
Eric Wong939af162019-10-06 23:30:37 +00005275 const struct hashmap_entry *eptr,
5276 const struct hashmap_entry *entry_or_key,
5277 const void *key)
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005278{
Eric Wong939af162019-10-06 23:30:37 +00005279 const struct subject2item_entry *a, *b;
5280
5281 a = container_of(eptr, const struct subject2item_entry, entry);
5282 b = container_of(entry_or_key, const struct subject2item_entry, entry);
5283
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005284 return key ? strcmp(a->subject, key) : strcmp(a->subject, b->subject);
5285}
5286
Nguyễn Thái Ngọc Duy3cc02872018-05-19 07:28:23 +02005287define_commit_slab(commit_todo_item, struct todo_item *);
5288
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005289/*
5290 * Rearrange the todo list that has both "pick commit-id msg" and "pick
5291 * commit-id fixup!/squash! msg" in it so that the latter is put immediately
5292 * after the former, and change "pick" to "fixup"/"squash".
5293 *
5294 * Note that if the config has specified a custom instruction format, each log
5295 * message will have to be retrieved from the commit (as the oneline in the
5296 * script cannot be trusted) in order to normalize the autosquash arrangement.
5297 */
Alban Gruin79d7e882019-03-05 20:17:59 +01005298int todo_list_rearrange_squash(struct todo_list *todo_list)
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005299{
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005300 struct hashmap subject2item;
Alban Gruinf2a04902019-03-05 20:17:55 +01005301 int rearranged = 0, *next, *tail, i, nr = 0, alloc = 0;
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005302 char **subjects;
Nguyễn Thái Ngọc Duy3cc02872018-05-19 07:28:23 +02005303 struct commit_todo_item commit_todo;
Alban Gruinf2a04902019-03-05 20:17:55 +01005304 struct todo_item *items = NULL;
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005305
Nguyễn Thái Ngọc Duy3cc02872018-05-19 07:28:23 +02005306 init_commit_todo_item(&commit_todo);
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005307 /*
5308 * The hashmap maps onelines to the respective todo list index.
5309 *
5310 * If any items need to be rearranged, the next[i] value will indicate
5311 * which item was moved directly after the i'th.
5312 *
5313 * In that case, last[i] will indicate the index of the latest item to
5314 * be moved to appear after the i'th.
5315 */
Eric Wong939af162019-10-06 23:30:37 +00005316 hashmap_init(&subject2item, subject2item_cmp, NULL, todo_list->nr);
Alban Gruinf2a04902019-03-05 20:17:55 +01005317 ALLOC_ARRAY(next, todo_list->nr);
5318 ALLOC_ARRAY(tail, todo_list->nr);
5319 ALLOC_ARRAY(subjects, todo_list->nr);
5320 for (i = 0; i < todo_list->nr; i++) {
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005321 struct strbuf buf = STRBUF_INIT;
Alban Gruinf2a04902019-03-05 20:17:55 +01005322 struct todo_item *item = todo_list->items + i;
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005323 const char *commit_buffer, *subject, *p;
5324 size_t subject_len;
5325 int i2 = -1;
5326 struct subject2item_entry *entry;
5327
5328 next[i] = tail[i] = -1;
Johannes Schindelin2f6b1d12018-04-25 14:28:25 +02005329 if (!item->commit || item->command == TODO_DROP) {
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005330 subjects[i] = NULL;
5331 continue;
5332 }
5333
5334 if (is_fixup(item->command)) {
Nguyễn Thái Ngọc Duy3cc02872018-05-19 07:28:23 +02005335 clear_commit_todo_item(&commit_todo);
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005336 return error(_("the script was already rearranged."));
5337 }
5338
Nguyễn Thái Ngọc Duy3cc02872018-05-19 07:28:23 +02005339 *commit_todo_item_at(&commit_todo, item->commit) = item;
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005340
5341 parse_commit(item->commit);
Doan Tran Cong Danh0798d162019-11-08 16:43:46 +07005342 commit_buffer = logmsg_reencode(item->commit, NULL, "UTF-8");
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005343 find_commit_subject(commit_buffer, &subject);
5344 format_subject(&buf, subject, " ");
5345 subject = subjects[i] = strbuf_detach(&buf, &subject_len);
5346 unuse_commit_buffer(item->commit, commit_buffer);
5347 if ((skip_prefix(subject, "fixup! ", &p) ||
5348 skip_prefix(subject, "squash! ", &p))) {
5349 struct commit *commit2;
5350
5351 for (;;) {
5352 while (isspace(*p))
5353 p++;
5354 if (!skip_prefix(p, "fixup! ", &p) &&
5355 !skip_prefix(p, "squash! ", &p))
5356 break;
5357 }
5358
Eric Wongf23a4652019-10-06 23:30:36 +00005359 entry = hashmap_get_entry_from_hash(&subject2item,
5360 strhash(p), p,
5361 struct subject2item_entry,
5362 entry);
5363 if (entry)
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005364 /* found by title */
5365 i2 = entry->i;
5366 else if (!strchr(p, ' ') &&
5367 (commit2 =
5368 lookup_commit_reference_by_name(p)) &&
Nguyễn Thái Ngọc Duy3cc02872018-05-19 07:28:23 +02005369 *commit_todo_item_at(&commit_todo, commit2))
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005370 /* found by commit name */
Nguyễn Thái Ngọc Duy3cc02872018-05-19 07:28:23 +02005371 i2 = *commit_todo_item_at(&commit_todo, commit2)
Alban Gruinf2a04902019-03-05 20:17:55 +01005372 - todo_list->items;
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005373 else {
5374 /* copy can be a prefix of the commit subject */
5375 for (i2 = 0; i2 < i; i2++)
5376 if (subjects[i2] &&
5377 starts_with(subjects[i2], p))
5378 break;
5379 if (i2 == i)
5380 i2 = -1;
5381 }
5382 }
5383 if (i2 >= 0) {
5384 rearranged = 1;
Alban Gruinf2a04902019-03-05 20:17:55 +01005385 todo_list->items[i].command =
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005386 starts_with(subject, "fixup!") ?
5387 TODO_FIXUP : TODO_SQUASH;
5388 if (next[i2] < 0)
5389 next[i2] = i;
5390 else
5391 next[tail[i2]] = i;
5392 tail[i2] = i;
5393 } else if (!hashmap_get_from_hash(&subject2item,
5394 strhash(subject), subject)) {
5395 FLEX_ALLOC_MEM(entry, subject, subject, subject_len);
5396 entry->i = i;
Eric Wongd22245a2019-10-06 23:30:27 +00005397 hashmap_entry_init(&entry->entry,
5398 strhash(entry->subject));
Eric Wong26b455f2019-10-06 23:30:32 +00005399 hashmap_put(&subject2item, &entry->entry);
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005400 }
5401 }
5402
5403 if (rearranged) {
Alban Gruinf2a04902019-03-05 20:17:55 +01005404 for (i = 0; i < todo_list->nr; i++) {
5405 enum todo_command command = todo_list->items[i].command;
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005406 int cur = i;
5407
5408 /*
5409 * Initially, all commands are 'pick's. If it is a
5410 * fixup or a squash now, we have rearranged it.
5411 */
5412 if (is_fixup(command))
5413 continue;
5414
5415 while (cur >= 0) {
Alban Gruinf2a04902019-03-05 20:17:55 +01005416 ALLOC_GROW(items, nr + 1, alloc);
5417 items[nr++] = todo_list->items[cur];
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005418 cur = next[cur];
5419 }
5420 }
5421
Alban Gruinf2a04902019-03-05 20:17:55 +01005422 FREE_AND_NULL(todo_list->items);
5423 todo_list->items = items;
5424 todo_list->nr = nr;
5425 todo_list->alloc = alloc;
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005426 }
5427
5428 free(next);
5429 free(tail);
Alban Gruinf2a04902019-03-05 20:17:55 +01005430 for (i = 0; i < todo_list->nr; i++)
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005431 free(subjects[i]);
5432 free(subjects);
Eric Wongc8e424c2019-10-06 23:30:40 +00005433 hashmap_free_entries(&subject2item, struct subject2item_entry, entry);
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005434
Nguyễn Thái Ngọc Duy3cc02872018-05-19 07:28:23 +02005435 clear_commit_todo_item(&commit_todo);
Alban Gruinf2a04902019-03-05 20:17:55 +01005436
5437 return 0;
Johannes Schindelinc44a4c62017-07-14 16:45:31 +02005438}
Phillip Wood901ba7b2019-12-06 16:06:11 +00005439
5440int sequencer_determine_whence(struct repository *r, enum commit_whence *whence)
5441{
5442 if (file_exists(git_path_cherry_pick_head(r))) {
Phillip Wood430b75f2019-12-06 16:06:12 +00005443 struct object_id cherry_pick_head, rebase_head;
5444
5445 if (file_exists(git_path_seq_dir()))
5446 *whence = FROM_CHERRY_PICK_MULTI;
5447 if (file_exists(rebase_path()) &&
5448 !get_oid("REBASE_HEAD", &rebase_head) &&
5449 !get_oid("CHERRY_PICK_HEAD", &cherry_pick_head) &&
5450 oideq(&rebase_head, &cherry_pick_head))
5451 *whence = FROM_REBASE_PICK;
5452 else
5453 *whence = FROM_CHERRY_PICK_SINGLE;
5454
Phillip Wood901ba7b2019-12-06 16:06:11 +00005455 return 1;
5456 }
5457
5458 return 0;
5459}