1515#include "merge-recursive.h"
1616#include "refs.h"
1717#include "argv-array.h"
18+ #include "log-tree.h"
1819
1920#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
2021
@@ -35,6 +36,20 @@ static GIT_PATH_FUNC(git_path_rebase_dir, "rebase-merge")
3536 * file and written to the tail of 'done'.
3637 */
3738static GIT_PATH_FUNC (git_path_rebase_todo , "rebase-merge/git-rebase-todo" )
39+ /*
40+ * When an "edit" rebase command is being processed, the SHA1 of the
41+ * commit to be edited is recorded in this file. When "git rebase
42+ * --continue" is executed, if there are any staged changes then they
43+ * will be amended to the HEAD commit, but only provided the HEAD
44+ * commit is still the commit to be edited. When any other rebase
45+ * command is processed, this file is deleted.
46+ */
47+ static GIT_PATH_FUNC (git_path_rebase_amend , "rebase-merge/amend" )
48+ /*
49+ * When we stop at a given patch via the "edit" command, this file contains
50+ * the long commit name of the corresponding patch.
51+ */
52+ static GIT_PATH_FUNC (stopped_sha , "rebase-merge/stopped-sha" )
3853
3954#define IS_REBASE_I () (opts->action == REPLAY_INTERACTIVE_REBASE)
4055
@@ -488,12 +503,14 @@ static int allow_empty(struct replay_opts *opts, struct commit *commit)
488503enum todo_command {
489504 TODO_PICK ,
490505 TODO_REVERT ,
506+ TODO_EDIT ,
491507 TODO_NOOP
492508};
493509
494510static const char * todo_command_strings [] = {
495511 "pick" ,
496512 "revert" ,
513+ "edit" ,
497514 "noop"
498515};
499516
@@ -1065,10 +1082,67 @@ static int save_opts(struct replay_opts *opts)
10651082 return res ;
10661083}
10671084
1068- static int pick_commits (struct todo_list * todo_list , struct replay_opts * opts )
1085+ static int make_patch (struct commit * commit , struct replay_opts * opts )
10691086{
1087+ struct strbuf buf = STRBUF_INIT ;
1088+ struct rev_info log_tree_opt ;
1089+ const char * commit_buffer = get_commit_buffer (commit , NULL ), * subject ;
10701090 int res ;
10711091
1092+ write_file (stopped_sha (), "%s\n" , short_commit_name (commit ));
1093+
1094+ strbuf_addf (& buf , "%s/patch" , get_dir (opts ));
1095+ freopen (buf .buf , "w" , stdout );
1096+ memset (& log_tree_opt , 0 , sizeof (log_tree_opt ));
1097+ init_revisions (& log_tree_opt , NULL );
1098+ log_tree_opt .abbrev = 0 ;
1099+ log_tree_opt .diff = 1 ;
1100+ log_tree_opt .diffopt .output_format = DIFF_FORMAT_PATCH ;
1101+ log_tree_opt .disable_stdin = 1 ;
1102+ log_tree_opt .no_commit_id = 1 ;
1103+ res = log_tree_commit (& log_tree_opt , commit );
1104+ strbuf_reset (& buf );
1105+
1106+ strbuf_addf (& buf , "%s/message" , get_dir (opts ));
1107+ if (!file_exists (buf .buf )) {
1108+ find_commit_subject (commit_buffer , & subject );
1109+ write_file (buf .buf , "%s\n" , subject );
1110+ unuse_commit_buffer (commit , commit_buffer );
1111+ }
1112+ strbuf_release (& buf );
1113+
1114+ return res ;
1115+ }
1116+
1117+ static int error_with_patch (struct commit * commit ,
1118+ struct replay_opts * opts , int exit_code )
1119+ {
1120+ unsigned char head [20 ];
1121+
1122+ if (get_sha1 ("HEAD" , head ))
1123+ return error ("Cannot read HEAD" );
1124+
1125+ if (make_patch (commit , opts ))
1126+ return -1 ;
1127+
1128+ write_file (git_path_rebase_amend (),
1129+ "%s\n" , sha1_to_hex (head ));
1130+
1131+ fprintf (stderr , "You can amend the commit now, with\n"
1132+ "\n"
1133+ " git commit --amend\n" /* TODO: $gpg_sign_opt_quoted */
1134+ "\n"
1135+ "Once you are satisfied with your changes, run\n"
1136+ "\n"
1137+ " git rebase --continue\n" );
1138+
1139+ return exit_code ;
1140+ }
1141+
1142+ static int pick_commits (struct todo_list * todo_list , struct replay_opts * opts )
1143+ {
1144+ int res = 0 ;
1145+
10721146 setenv (GIT_REFLOG_ACTION , action_name (opts ), 0 );
10731147 if (opts -> allow_ff )
10741148 assert (!(opts -> signoff || opts -> no_commit ||
@@ -1080,9 +1154,18 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
10801154 struct todo_item * item = todo_list -> items + todo_list -> current ;
10811155 if (save_todo (todo_list , opts ))
10821156 return -1 ;
1083- if (item -> command <= TODO_REVERT )
1157+ if (item -> command <= TODO_EDIT ) {
10841158 res = do_pick_commit (item -> command , item -> commit ,
10851159 opts );
1160+ if (item -> command == TODO_EDIT ) {
1161+ struct commit * commit = item -> commit ;
1162+ if (!res )
1163+ warning ("Stopped at %s... %.*s" ,
1164+ short_commit_name (commit ),
1165+ item -> arg_len , item -> arg );
1166+ return error_with_patch (commit , opts , res );
1167+ }
1168+ }
10861169 else if (item -> command != TODO_NOOP )
10871170 return error ("Unknown command %d" , item -> command );
10881171
@@ -1091,6 +1174,12 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
10911174 return res ;
10921175 }
10931176
1177+ if (IS_REBASE_I ()) {
1178+ /* Stopped in the middle, as planned? */
1179+ if (todo_list -> current < todo_list -> nr )
1180+ return 0 ;
1181+ }
1182+
10941183 /*
10951184 * Sequence of picks finished successfully; cleanup by
10961185 * removing the .git/sequencer directory
0 commit comments