@@ -639,42 +639,64 @@ static int write_author_script(const char *message)
639639 else if (* message != '\'' )
640640 strbuf_addch (& buf , * (message ++ ));
641641 else
642- strbuf_addf (& buf , "'\\\\ %c'" , * (message ++ ));
642+ strbuf_addf (& buf , "'\\%c'" , * (message ++ ));
643643 strbuf_addstr (& buf , "'\nGIT_AUTHOR_EMAIL='" );
644644 while (* message && * message != '\n' && * message != '\r' )
645645 if (skip_prefix (message , "> " , & message ))
646646 break ;
647647 else if (* message != '\'' )
648648 strbuf_addch (& buf , * (message ++ ));
649649 else
650- strbuf_addf (& buf , "'\\\\ %c'" , * (message ++ ));
650+ strbuf_addf (& buf , "'\\%c'" , * (message ++ ));
651651 strbuf_addstr (& buf , "'\nGIT_AUTHOR_DATE='@" );
652652 while (* message && * message != '\n' && * message != '\r' )
653653 if (* message != '\'' )
654654 strbuf_addch (& buf , * (message ++ ));
655655 else
656- strbuf_addf (& buf , "'\\\\ %c'" , * (message ++ ));
656+ strbuf_addf (& buf , "'\\%c'" , * (message ++ ));
657657 strbuf_addch (& buf , '\'' );
658658 res = write_message (buf .buf , buf .len , rebase_path_author_script (), 1 );
659659 strbuf_release (& buf );
660660 return res ;
661661}
662662
663+
664+ /*
665+ * write_author_script() used to fail to terminate the last line with a "'" and
666+ * also escaped "'" incorrectly as "'\\\\''" rather than "'\\''". We check for
667+ * the terminating "'" on the last line to see how "'" has been escaped in case
668+ * git was upgraded while rebase was stopped.
669+ */
670+ static int quoting_is_broken (const char * s , size_t n )
671+ {
672+ /* Skip any empty lines in case the file was hand edited */
673+ while (n > 0 && s [-- n ] == '\n' )
674+ ; /* empty */
675+ if (n > 0 && s [n ] != '\'' )
676+ return 1 ;
677+
678+ return 0 ;
679+ }
680+
663681/*
664682 * Read a list of environment variable assignments (such as the author-script
665683 * file) into an environment block. Returns -1 on error, 0 otherwise.
666684 */
667685static int read_env_script (struct argv_array * env )
668686{
669687 struct strbuf script = STRBUF_INIT ;
670- int i , count = 0 ;
671- char * p , * p2 ;
688+ int i , count = 0 , sq_bug ;
689+ const char * p2 ;
690+ char * p ;
672691
673692 if (strbuf_read_file (& script , rebase_path_author_script (), 256 ) <= 0 )
674693 return -1 ;
675-
694+ /* write_author_script() used to quote incorrectly */
695+ sq_bug = quoting_is_broken (script .buf , script .len );
676696 for (p = script .buf ; * p ; p ++ )
677- if (skip_prefix (p , "'\\\\''" , (const char * * )& p2 ))
697+ if (sq_bug && skip_prefix (p , "'\\\\''" , & p2 ))
698+ strbuf_splice (& script , p - script .buf , p2 - p , "'" , 1 );
699+ else if (skip_prefix (p , "'\\''" , & p2 ))
678700 strbuf_splice (& script , p - script .buf , p2 - p , "'" , 1 );
679701 else if (* p == '\'' )
680702 strbuf_splice (& script , p -- - script .buf , 1 , "" , 0 );
@@ -798,11 +820,18 @@ static int run_git_commit(const char *defmsg, struct replay_opts *opts,
798820
799821 if ((flags & CREATE_ROOT_COMMIT ) && !(flags & AMEND_MSG )) {
800822 struct strbuf msg = STRBUF_INIT , script = STRBUF_INIT ;
801- const char * author = is_rebase_i (opts ) ?
802- read_author_ident (& script ) : NULL ;
823+ const char * author = NULL ;
803824 struct object_id root_commit , * cache_tree_oid ;
804825 int res = 0 ;
805826
827+ if (is_rebase_i (opts )) {
828+ author = read_author_ident (& script );
829+ if (!author ) {
830+ strbuf_release (& script );
831+ return -1 ;
832+ }
833+ }
834+
806835 if (!defmsg )
807836 BUG ("root commit without message" );
808837
0 commit comments