@@ -592,6 +592,18 @@ static int read_env_script(struct argv_array *env)
592592 return 0 ;
593593}
594594
595+ static char * get_author (const char * message )
596+ {
597+ size_t len ;
598+ const char * a ;
599+
600+ a = find_commit_header (message , "author" , & len );
601+ if (a )
602+ return xmemdupz (a , len );
603+
604+ return NULL ;
605+ }
606+
595607static const char staged_changes_advice [] =
596608N_ ("you have staged changes in your working tree\n"
597609"If these changes are meant to be squashed into the previous commit, run:\n"
@@ -984,6 +996,160 @@ void print_commit_summary(const char *prefix, const struct object_id *oid,
984996 strbuf_release (& format );
985997}
986998
999+ static int parse_head (struct commit * * head )
1000+ {
1001+ struct commit * current_head ;
1002+ struct object_id oid ;
1003+
1004+ if (get_oid ("HEAD" , & oid )) {
1005+ current_head = NULL ;
1006+ } else {
1007+ current_head = lookup_commit_reference (& oid );
1008+ if (!current_head )
1009+ return error (_ ("could not parse HEAD" ));
1010+ if (oidcmp (& oid , & current_head -> object .oid )) {
1011+ warning (_ ("HEAD %s is not a commit!" ),
1012+ oid_to_hex (& oid ));
1013+ }
1014+ if (parse_commit (current_head ))
1015+ return error (_ ("could not parse HEAD commit" ));
1016+ }
1017+ * head = current_head ;
1018+
1019+ return 0 ;
1020+ }
1021+
1022+ /*
1023+ * Try to commit without forking 'git commit'. In some cases we need
1024+ * to run 'git commit' to display an error message
1025+ *
1026+ * Returns:
1027+ * -1 - error unable to commit
1028+ * 0 - success
1029+ * 1 - run 'git commit'
1030+ */
1031+ static int try_to_commit (struct strbuf * msg , const char * author ,
1032+ struct replay_opts * opts , unsigned int flags ,
1033+ struct object_id * oid )
1034+ {
1035+ struct object_id tree ;
1036+ struct commit * current_head ;
1037+ struct commit_list * parents = NULL ;
1038+ struct commit_extra_header * extra = NULL ;
1039+ struct strbuf err = STRBUF_INIT ;
1040+ struct strbuf amend_msg = STRBUF_INIT ;
1041+ char * amend_author = NULL ;
1042+ const char * gpg_sign ;
1043+ enum commit_msg_cleanup_mode cleanup ;
1044+ int res = 0 ;
1045+
1046+ if (parse_head (& current_head ))
1047+ return -1 ;
1048+
1049+ if (flags & AMEND_MSG ) {
1050+ const char * exclude_gpgsig [] = { "gpgsig" , NULL };
1051+ const char * out_enc = get_commit_output_encoding ();
1052+ const char * message = logmsg_reencode (current_head , NULL ,
1053+ out_enc );
1054+
1055+ if (!msg ) {
1056+ const char * orig_message = NULL ;
1057+
1058+ find_commit_subject (message , & orig_message );
1059+ msg = & amend_msg ;
1060+ strbuf_addstr (msg , orig_message );
1061+ }
1062+ author = amend_author = get_author (message );
1063+ unuse_commit_buffer (current_head , message );
1064+ if (!author ) {
1065+ res = error (_ ("unable to parse commit author" ));
1066+ goto out ;
1067+ }
1068+ parents = copy_commit_list (current_head -> parents );
1069+ extra = read_commit_extra_headers (current_head , exclude_gpgsig );
1070+ } else if (current_head ) {
1071+ commit_list_insert (current_head , & parents );
1072+ }
1073+
1074+ cleanup = (flags & CLEANUP_MSG ) ? COMMIT_MSG_CLEANUP_ALL :
1075+ default_msg_cleanup ;
1076+ if (cleanup != COMMIT_MSG_CLEANUP_NONE )
1077+ strbuf_stripspace (msg , cleanup == COMMIT_MSG_CLEANUP_ALL );
1078+ if (!opts -> allow_empty_message && message_is_empty (msg , cleanup )) {
1079+ res = 1 ; /* run 'git commit' to display error message */
1080+ goto out ;
1081+ }
1082+
1083+ gpg_sign = opts -> gpg_sign ? opts -> gpg_sign : default_gpg_sign ;
1084+
1085+ if (write_cache_as_tree (tree .hash , 0 , NULL )) {
1086+ res = error (_ ("git write-tree failed to write a tree" ));
1087+ goto out ;
1088+ }
1089+
1090+ if (!(flags & ALLOW_EMPTY ) && !oidcmp (current_head ?
1091+ & current_head -> tree -> object .oid :
1092+ & empty_tree_oid , & tree )) {
1093+ res = 1 ; /* run 'git commit' to display error message */
1094+ goto out ;
1095+ }
1096+
1097+ if (commit_tree_extended (msg -> buf , msg -> len , tree .hash , parents ,
1098+ oid -> hash , author , gpg_sign , extra )) {
1099+ res = error (_ ("failed to write commit object" ));
1100+ goto out ;
1101+ }
1102+
1103+ if (update_head_with_reflog (current_head , oid ,
1104+ getenv ("GIT_REFLOG_ACTION" ), msg , & err )) {
1105+ res = error ("%s" , err .buf );
1106+ goto out ;
1107+ }
1108+
1109+ if (flags & AMEND_MSG )
1110+ commit_post_rewrite (current_head , oid );
1111+
1112+ out :
1113+ free_commit_extra_headers (extra );
1114+ strbuf_release (& err );
1115+ strbuf_release (& amend_msg );
1116+ free (amend_author );
1117+
1118+ return res ;
1119+ }
1120+
1121+ static int do_commit (const char * msg_file , const char * author ,
1122+ struct replay_opts * opts , unsigned int flags )
1123+ {
1124+ int res = 1 ;
1125+
1126+ if (!(flags & EDIT_MSG ) && !(flags & VERIFY_MSG )) {
1127+ struct object_id oid ;
1128+ struct strbuf sb = STRBUF_INIT ;
1129+
1130+ if (msg_file && strbuf_read_file (& sb , msg_file , 2048 ) < 0 )
1131+ return error_errno (_ ("unable to read commit message "
1132+ "from '%s'" ),
1133+ msg_file );
1134+
1135+ res = try_to_commit (msg_file ? & sb : NULL , author , opts , flags ,
1136+ & oid );
1137+ strbuf_release (& sb );
1138+ if (!res ) {
1139+ unlink (git_path_cherry_pick_head ());
1140+ unlink (git_path_merge_msg ());
1141+ if (!is_rebase_i (opts ))
1142+ print_commit_summary (NULL , & oid ,
1143+ SUMMARY_SHOW_AUTHOR_DATE );
1144+ return res ;
1145+ }
1146+ }
1147+ if (res == 1 )
1148+ return run_git_commit (msg_file , opts , flags );
1149+
1150+ return res ;
1151+ }
1152+
9871153static int is_original_commit_empty (struct commit * commit )
9881154{
9891155 const struct object_id * ptree_oid ;
@@ -1235,6 +1401,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
12351401 struct object_id head ;
12361402 struct commit * base , * next , * parent ;
12371403 const char * base_label , * next_label ;
1404+ char * author = NULL ;
12381405 struct commit_message msg = { NULL , NULL , NULL , NULL };
12391406 struct strbuf msgbuf = STRBUF_INIT ;
12401407 int res , unborn = 0 , allow ;
@@ -1351,6 +1518,8 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
13511518 strbuf_addstr (& msgbuf , oid_to_hex (& commit -> object .oid ));
13521519 strbuf_addstr (& msgbuf , ")\n" );
13531520 }
1521+ if (!is_fixup (command ))
1522+ author = get_author (msg .message );
13541523 }
13551524
13561525 if (command == TODO_REWORD )
@@ -1436,9 +1605,13 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
14361605 goto leave ;
14371606 } else if (allow )
14381607 flags |= ALLOW_EMPTY ;
1439- if (!opts -> no_commit )
1608+ if (!opts -> no_commit ) {
14401609fast_forward_edit :
1441- res = run_git_commit (msg_file , opts , flags );
1610+ if (author || command == TODO_REVERT || (flags & AMEND_MSG ))
1611+ res = do_commit (msg_file , author , opts , flags );
1612+ else
1613+ res = error (_ ("unable to parse commit author" ));
1614+ }
14421615
14431616 if (!res && final_fixup ) {
14441617 unlink (rebase_path_fixup_msg ());
@@ -1447,6 +1620,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
14471620
14481621leave :
14491622 free_message (commit , & msg );
1623+ free (author );
14501624 update_abort_safety_file ();
14511625
14521626 return res ;
0 commit comments