@@ -639,42 +639,64 @@ static int write_author_script(const char *message)
639
639
else if (* message != '\'' )
640
640
strbuf_addch (& buf , * (message ++ ));
641
641
else
642
- strbuf_addf (& buf , "'\\\\ %c'" , * (message ++ ));
642
+ strbuf_addf (& buf , "'\\%c'" , * (message ++ ));
643
643
strbuf_addstr (& buf , "'\nGIT_AUTHOR_EMAIL='" );
644
644
while (* message && * message != '\n' && * message != '\r' )
645
645
if (skip_prefix (message , "> " , & message ))
646
646
break ;
647
647
else if (* message != '\'' )
648
648
strbuf_addch (& buf , * (message ++ ));
649
649
else
650
- strbuf_addf (& buf , "'\\\\ %c'" , * (message ++ ));
650
+ strbuf_addf (& buf , "'\\%c'" , * (message ++ ));
651
651
strbuf_addstr (& buf , "'\nGIT_AUTHOR_DATE='@" );
652
652
while (* message && * message != '\n' && * message != '\r' )
653
653
if (* message != '\'' )
654
654
strbuf_addch (& buf , * (message ++ ));
655
655
else
656
- strbuf_addf (& buf , "'\\\\ %c'" , * (message ++ ));
656
+ strbuf_addf (& buf , "'\\%c'" , * (message ++ ));
657
657
strbuf_addch (& buf , '\'' );
658
658
res = write_message (buf .buf , buf .len , rebase_path_author_script (), 1 );
659
659
strbuf_release (& buf );
660
660
return res ;
661
661
}
662
662
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
+
663
681
/*
664
682
* Read a list of environment variable assignments (such as the author-script
665
683
* file) into an environment block. Returns -1 on error, 0 otherwise.
666
684
*/
667
685
static int read_env_script (struct argv_array * env )
668
686
{
669
687
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 ;
672
691
673
692
if (strbuf_read_file (& script , rebase_path_author_script (), 256 ) <= 0 )
674
693
return -1 ;
675
-
694
+ /* write_author_script() used to quote incorrectly */
695
+ sq_bug = quoting_is_broken (script .buf , script .len );
676
696
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 ))
678
700
strbuf_splice (& script , p - script .buf , p2 - p , "'" , 1 );
679
701
else if (* p == '\'' )
680
702
strbuf_splice (& script , p -- - script .buf , 1 , "" , 0 );
@@ -798,11 +820,18 @@ static int run_git_commit(const char *defmsg, struct replay_opts *opts,
798
820
799
821
if ((flags & CREATE_ROOT_COMMIT ) && !(flags & AMEND_MSG )) {
800
822
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 ;
803
824
struct object_id root_commit , * cache_tree_oid ;
804
825
int res = 0 ;
805
826
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
+
806
835
if (!defmsg )
807
836
BUG ("root commit without message" );
808
837
0 commit comments