1717#include "argv-array.h"
1818#include "quote.h"
1919#include "trailer.h"
20+ #include "log-tree.h"
2021
2122#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
2223
@@ -44,6 +45,20 @@ static GIT_PATH_FUNC(rebase_path_todo, "rebase-merge/git-rebase-todo")
4445 * being rebased.
4546 */
4647static GIT_PATH_FUNC (rebase_path_author_script , "rebase-merge/author-script" )
48+ /*
49+ * When an "edit" rebase command is being processed, the SHA1 of the
50+ * commit to be edited is recorded in this file. When "git rebase
51+ * --continue" is executed, if there are any staged changes then they
52+ * will be amended to the HEAD commit, but only provided the HEAD
53+ * commit is still the commit to be edited. When any other rebase
54+ * command is processed, this file is deleted.
55+ */
56+ static GIT_PATH_FUNC (rebase_path_amend , "rebase-merge/amend" )
57+ /*
58+ * When we stop at a given patch via the "edit" command, this file contains
59+ * the abbreviated commit name of the corresponding patch.
60+ */
61+ static GIT_PATH_FUNC (rebase_path_stopped_sha , "rebase-merge/stopped-sha" )
4762/*
4863 * The following files are written by git-rebase just after parsing the
4964 * command-line (and are only consumed, not modified, by the sequencer).
@@ -616,13 +631,15 @@ enum todo_command {
616631 /* commands that handle commits */
617632 TODO_PICK = 0 ,
618633 TODO_REVERT ,
634+ TODO_EDIT ,
619635 /* commands that do nothing but are counted for reporting progress */
620636 TODO_NOOP
621637};
622638
623639static const char * todo_command_strings [] = {
624640 "pick" ,
625641 "revert" ,
642+ "edit" ,
626643 "noop"
627644};
628645
@@ -1302,9 +1319,87 @@ static int save_opts(struct replay_opts *opts)
13021319 return res ;
13031320}
13041321
1322+ static int make_patch (struct commit * commit , struct replay_opts * opts )
1323+ {
1324+ struct strbuf buf = STRBUF_INIT ;
1325+ struct rev_info log_tree_opt ;
1326+ const char * subject , * p ;
1327+ int res = 0 ;
1328+
1329+ p = short_commit_name (commit );
1330+ if (write_message (p , strlen (p ), rebase_path_stopped_sha (), 1 ) < 0 )
1331+ return -1 ;
1332+
1333+ strbuf_addf (& buf , "%s/patch" , get_dir (opts ));
1334+ memset (& log_tree_opt , 0 , sizeof (log_tree_opt ));
1335+ init_revisions (& log_tree_opt , NULL );
1336+ log_tree_opt .abbrev = 0 ;
1337+ log_tree_opt .diff = 1 ;
1338+ log_tree_opt .diffopt .output_format = DIFF_FORMAT_PATCH ;
1339+ log_tree_opt .disable_stdin = 1 ;
1340+ log_tree_opt .no_commit_id = 1 ;
1341+ log_tree_opt .diffopt .file = fopen (buf .buf , "w" );
1342+ log_tree_opt .diffopt .use_color = GIT_COLOR_NEVER ;
1343+ if (!log_tree_opt .diffopt .file )
1344+ res |= error_errno (_ ("could not open '%s'" ), buf .buf );
1345+ else {
1346+ res |= log_tree_commit (& log_tree_opt , commit );
1347+ fclose (log_tree_opt .diffopt .file );
1348+ }
1349+ strbuf_reset (& buf );
1350+
1351+ strbuf_addf (& buf , "%s/message" , get_dir (opts ));
1352+ if (!file_exists (buf .buf )) {
1353+ const char * commit_buffer = get_commit_buffer (commit , NULL );
1354+ find_commit_subject (commit_buffer , & subject );
1355+ res |= write_message (subject , strlen (subject ), buf .buf , 1 );
1356+ unuse_commit_buffer (commit , commit_buffer );
1357+ }
1358+ strbuf_release (& buf );
1359+
1360+ return res ;
1361+ }
1362+
1363+ static int intend_to_amend (void )
1364+ {
1365+ unsigned char head [20 ];
1366+ char * p ;
1367+
1368+ if (get_sha1 ("HEAD" , head ))
1369+ return error (_ ("cannot read HEAD" ));
1370+
1371+ p = sha1_to_hex (head );
1372+ return write_message (p , strlen (p ), rebase_path_amend (), 1 );
1373+ }
1374+
1375+ static int error_with_patch (struct commit * commit ,
1376+ const char * subject , int subject_len ,
1377+ struct replay_opts * opts , int exit_code , int to_amend )
1378+ {
1379+ if (make_patch (commit , opts ))
1380+ return -1 ;
1381+
1382+ if (to_amend ) {
1383+ if (intend_to_amend ())
1384+ return -1 ;
1385+
1386+ fprintf (stderr , "You can amend the commit now, with\n"
1387+ "\n"
1388+ " git commit --amend %s\n"
1389+ "\n"
1390+ "Once you are satisfied with your changes, run\n"
1391+ "\n"
1392+ " git rebase --continue\n" , gpg_sign_opt_quoted (opts ));
1393+ } else if (exit_code )
1394+ fprintf (stderr , "Could not apply %s... %.*s\n" ,
1395+ short_commit_name (commit ), subject_len , subject );
1396+
1397+ return exit_code ;
1398+ }
1399+
13051400static int pick_commits (struct todo_list * todo_list , struct replay_opts * opts )
13061401{
1307- int res ;
1402+ int res = 0 ;
13081403
13091404 setenv (GIT_REFLOG_ACTION , action_name (opts ), 0 );
13101405 if (opts -> allow_ff )
@@ -1317,17 +1412,33 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
13171412 struct todo_item * item = todo_list -> items + todo_list -> current ;
13181413 if (save_todo (todo_list , opts ))
13191414 return -1 ;
1320- if (item -> command <= TODO_REVERT )
1415+ if (item -> command <= TODO_EDIT ) {
13211416 res = do_pick_commit (item -> command , item -> commit ,
13221417 opts );
1323- else if (!is_noop (item -> command ))
1418+ if (item -> command == TODO_EDIT ) {
1419+ struct commit * commit = item -> commit ;
1420+ if (!res )
1421+ warning (_ ("stopped at %s... %.*s" ),
1422+ short_commit_name (commit ),
1423+ item -> arg_len , item -> arg );
1424+ return error_with_patch (commit ,
1425+ item -> arg , item -> arg_len , opts , res ,
1426+ !res );
1427+ }
1428+ } else if (!is_noop (item -> command ))
13241429 return error (_ ("unknown command %d" ), item -> command );
13251430
13261431 todo_list -> current ++ ;
13271432 if (res )
13281433 return res ;
13291434 }
13301435
1436+ if (is_rebase_i (opts )) {
1437+ /* Stopped in the middle, as planned? */
1438+ if (todo_list -> current < todo_list -> nr )
1439+ return 0 ;
1440+ }
1441+
13311442 /*
13321443 * Sequence of picks finished successfully; cleanup by
13331444 * removing the .git/sequencer directory
0 commit comments