@@ -102,12 +102,12 @@ static int same_trailer(struct trailer_item *a, struct arg_item *b)
102
102
return same_token (a , b ) && same_value (a , b );
103
103
}
104
104
105
- static inline int contains_only_spaces (const char * str )
105
+ static inline int is_blank_line (const char * str )
106
106
{
107
107
const char * s = str ;
108
- while (* s && isspace (* s ))
108
+ while (* s && * s != '\n' && isspace (* s ))
109
109
s ++ ;
110
- return !* s ;
110
+ return !* s || * s == '\n' ;
111
111
}
112
112
113
113
static inline void strbuf_replace (struct strbuf * sb , const char * a , const char * b )
@@ -702,51 +702,71 @@ static void process_command_line_args(struct list_head *arg_head,
702
702
free (cl_separators );
703
703
}
704
704
705
- static struct strbuf * * read_input_file ( const char * file )
705
+ static void read_input_file ( struct strbuf * sb , const char * file )
706
706
{
707
- struct strbuf * * lines ;
708
- struct strbuf sb = STRBUF_INIT ;
709
-
710
707
if (file ) {
711
- if (strbuf_read_file (& sb , file , 0 ) < 0 )
708
+ if (strbuf_read_file (sb , file , 0 ) < 0 )
712
709
die_errno (_ ("could not read input file '%s'" ), file );
713
710
} else {
714
- if (strbuf_read (& sb , fileno (stdin ), 0 ) < 0 )
711
+ if (strbuf_read (sb , fileno (stdin ), 0 ) < 0 )
715
712
die_errno (_ ("could not read from stdin" ));
716
713
}
714
+ }
717
715
718
- lines = strbuf_split (& sb , '\n' );
716
+ static const char * next_line (const char * str )
717
+ {
718
+ const char * nl = strchrnul (str , '\n' );
719
+ return nl + !!* nl ;
720
+ }
719
721
720
- strbuf_release (& sb );
722
+ /*
723
+ * Return the position of the start of the last line. If len is 0, return -1.
724
+ */
725
+ static int last_line (const char * buf , size_t len )
726
+ {
727
+ int i ;
728
+ if (len == 0 )
729
+ return -1 ;
730
+ if (len == 1 )
731
+ return 0 ;
732
+ /*
733
+ * Skip the last character (in addition to the null terminator),
734
+ * because if the last character is a newline, it is considered as part
735
+ * of the last line anyway.
736
+ */
737
+ i = len - 2 ;
721
738
722
- return lines ;
739
+ for (; i >= 0 ; i -- ) {
740
+ if (buf [i ] == '\n' )
741
+ return i + 1 ;
742
+ }
743
+ return 0 ;
723
744
}
724
745
725
746
/*
726
- * Return the (0 based) index of the start of the patch or the line
727
- * count if there is no patch in the message.
747
+ * Return the position of the start of the patch or the length of str if there
748
+ * is no patch in the message.
728
749
*/
729
- static int find_patch_start (struct strbuf * * lines , int count )
750
+ static int find_patch_start (const char * str )
730
751
{
731
- int i ;
752
+ const char * s ;
732
753
733
- /* Get the start of the patch part if any */
734
- for (i = 0 ; i < count ; i ++ ) {
735
- if (starts_with (lines [i ]-> buf , "---" ))
736
- return i ;
754
+ for (s = str ; * s ; s = next_line (s )) {
755
+ if (starts_with (s , "---" ))
756
+ return s - str ;
737
757
}
738
758
739
- return count ;
759
+ return s - str ;
740
760
}
741
761
742
762
/*
743
- * Return the (0 based) index of the first trailer line or count if
744
- * there are no trailers. Trailers are searched only in the lines from
745
- * index (count - 1) down to index 0.
763
+ * Return the position of the first trailer line or len if there are no
764
+ * trailers.
746
765
*/
747
- static int find_trailer_start (struct strbuf * * lines , int count )
766
+ static int find_trailer_start (const char * buf , size_t len )
748
767
{
749
- int start , end_of_title , only_spaces = 1 ;
768
+ const char * s ;
769
+ int end_of_title , l , only_spaces = 1 ;
750
770
int recognized_prefix = 0 , trailer_lines = 0 , non_trailer_lines = 0 ;
751
771
/*
752
772
* Number of possible continuation lines encountered. This will be
@@ -758,53 +778,56 @@ static int find_trailer_start(struct strbuf **lines, int count)
758
778
int possible_continuation_lines = 0 ;
759
779
760
780
/* The first paragraph is the title and cannot be trailers */
761
- for (start = 0 ; start < count ; start ++ ) {
762
- if (lines [ start ] -> buf [0 ] == comment_line_char )
781
+ for (s = buf ; s < buf + len ; s = next_line ( s ) ) {
782
+ if (s [0 ] == comment_line_char )
763
783
continue ;
764
- if (contains_only_spaces ( lines [ start ] -> buf ))
784
+ if (is_blank_line ( s ))
765
785
break ;
766
786
}
767
- end_of_title = start ;
787
+ end_of_title = s - buf ;
768
788
769
789
/*
770
790
* Get the start of the trailers by looking starting from the end for a
771
791
* blank line before a set of non-blank lines that (i) are all
772
792
* trailers, or (ii) contains at least one Git-generated trailer and
773
793
* consists of at least 25% trailers.
774
794
*/
775
- for (start = count - 1 ; start >= end_of_title ; start -- ) {
795
+ for (l = last_line (buf , len );
796
+ l >= end_of_title ;
797
+ l = last_line (buf , l )) {
798
+ const char * bol = buf + l ;
776
799
const char * * p ;
777
800
int separator_pos ;
778
801
779
- if (lines [ start ] -> buf [0 ] == comment_line_char ) {
802
+ if (bol [0 ] == comment_line_char ) {
780
803
non_trailer_lines += possible_continuation_lines ;
781
804
possible_continuation_lines = 0 ;
782
805
continue ;
783
806
}
784
- if (contains_only_spaces ( lines [ start ] -> buf )) {
807
+ if (is_blank_line ( bol )) {
785
808
if (only_spaces )
786
809
continue ;
787
810
non_trailer_lines += possible_continuation_lines ;
788
811
if (recognized_prefix &&
789
812
trailer_lines * 3 >= non_trailer_lines )
790
- return start + 1 ;
791
- if (trailer_lines && !non_trailer_lines )
792
- return start + 1 ;
793
- return count ;
813
+ return next_line ( bol ) - buf ;
814
+ else if (trailer_lines && !non_trailer_lines )
815
+ return next_line ( bol ) - buf ;
816
+ return len ;
794
817
}
795
818
only_spaces = 0 ;
796
819
797
820
for (p = git_generated_prefixes ; * p ; p ++ ) {
798
- if (starts_with (lines [ start ] -> buf , * p )) {
821
+ if (starts_with (bol , * p )) {
799
822
trailer_lines ++ ;
800
823
possible_continuation_lines = 0 ;
801
824
recognized_prefix = 1 ;
802
825
goto continue_outer_loop ;
803
826
}
804
827
}
805
828
806
- separator_pos = find_separator (lines [ start ] -> buf , separators );
807
- if (separator_pos >= 1 && !isspace (lines [ start ] -> buf [0 ])) {
829
+ separator_pos = find_separator (bol , separators );
830
+ if (separator_pos >= 1 && !isspace (bol [0 ])) {
808
831
struct list_head * pos ;
809
832
810
833
trailer_lines ++ ;
@@ -814,13 +837,13 @@ static int find_trailer_start(struct strbuf **lines, int count)
814
837
list_for_each (pos , & conf_head ) {
815
838
struct arg_item * item ;
816
839
item = list_entry (pos , struct arg_item , list );
817
- if (token_matches_item (lines [ start ] -> buf , item ,
840
+ if (token_matches_item (bol , item ,
818
841
separator_pos )) {
819
842
recognized_prefix = 1 ;
820
843
break ;
821
844
}
822
845
}
823
- } else if (isspace (lines [ start ] -> buf [0 ]))
846
+ } else if (isspace (bol [0 ]))
824
847
possible_continuation_lines ++ ;
825
848
else {
826
849
non_trailer_lines ++ ;
@@ -831,95 +854,78 @@ static int find_trailer_start(struct strbuf **lines, int count)
831
854
;
832
855
}
833
856
834
- return count ;
835
- }
836
-
837
- /* Get the index of the end of the trailers */
838
- static int find_trailer_end (struct strbuf * * lines , int patch_start )
839
- {
840
- struct strbuf sb = STRBUF_INIT ;
841
- int i , ignore_bytes ;
842
-
843
- for (i = 0 ; i < patch_start ; i ++ )
844
- strbuf_addbuf (& sb , lines [i ]);
845
- ignore_bytes = ignore_non_trailer (sb .buf , sb .len );
846
- strbuf_release (& sb );
847
- for (i = patch_start - 1 ; i >= 0 && ignore_bytes > 0 ; i -- )
848
- ignore_bytes -= lines [i ]-> len ;
849
-
850
- return i + 1 ;
857
+ return len ;
851
858
}
852
859
853
- static int has_blank_line_before (struct strbuf * * lines , int start )
860
+ /* Return the position of the end of the trailers. */
861
+ static int find_trailer_end (const char * buf , size_t len )
854
862
{
855
- for (;start >= 0 ; start -- ) {
856
- if (lines [start ]-> buf [0 ] == comment_line_char )
857
- continue ;
858
- return contains_only_spaces (lines [start ]-> buf );
859
- }
860
- return 0 ;
863
+ return len - ignore_non_trailer (buf , len );
861
864
}
862
865
863
- static void print_lines ( FILE * outfile , struct strbuf * * lines , int start , int end )
866
+ static int ends_with_blank_line ( const char * buf , size_t len )
864
867
{
865
- int i ;
866
- for (i = start ; lines [i ] && i < end ; i ++ )
867
- fprintf (outfile , "%s" , lines [i ]-> buf );
868
+ int ll = last_line (buf , len );
869
+ if (ll < 0 )
870
+ return 0 ;
871
+ return is_blank_line (buf + ll );
868
872
}
869
873
870
874
static int process_input_file (FILE * outfile ,
871
- struct strbuf * * lines ,
875
+ const char * str ,
872
876
struct list_head * head )
873
877
{
874
- int count = 0 ;
875
- int patch_start , trailer_start , trailer_end , i ;
878
+ int patch_start , trailer_start , trailer_end ;
876
879
struct strbuf tok = STRBUF_INIT ;
877
880
struct strbuf val = STRBUF_INIT ;
878
881
struct trailer_item * last = NULL ;
882
+ struct strbuf * trailer , * * trailer_lines , * * ptr ;
879
883
880
- /* Get the line count */
881
- while (lines [count ])
882
- count ++ ;
883
-
884
- patch_start = find_patch_start (lines , count );
885
- trailer_end = find_trailer_end (lines , patch_start );
886
- trailer_start = find_trailer_start (lines , trailer_end );
884
+ patch_start = find_patch_start (str );
885
+ trailer_end = find_trailer_end (str , patch_start );
886
+ trailer_start = find_trailer_start (str , trailer_end );
887
887
888
888
/* Print lines before the trailers as is */
889
- print_lines ( outfile , lines , 0 , trailer_start );
889
+ fwrite ( str , 1 , trailer_start , outfile );
890
890
891
- if (!has_blank_line_before ( lines , trailer_start - 1 ))
891
+ if (!ends_with_blank_line ( str , trailer_start ))
892
892
fprintf (outfile , "\n" );
893
893
894
894
/* Parse trailer lines */
895
- for (i = trailer_start ; i < trailer_end ; i ++ ) {
895
+ trailer_lines = strbuf_split_buf (str + trailer_start ,
896
+ trailer_end - trailer_start ,
897
+ '\n' ,
898
+ 0 );
899
+ for (ptr = trailer_lines ; * ptr ; ptr ++ ) {
896
900
int separator_pos ;
897
- if (lines [i ]-> buf [0 ] == comment_line_char )
901
+ trailer = * ptr ;
902
+ if (trailer -> buf [0 ] == comment_line_char )
898
903
continue ;
899
- if (last && isspace (lines [ i ] -> buf [0 ])) {
904
+ if (last && isspace (trailer -> buf [0 ])) {
900
905
struct strbuf sb = STRBUF_INIT ;
901
- strbuf_addf (& sb , "%s\n%s" , last -> value , lines [ i ] -> buf );
906
+ strbuf_addf (& sb , "%s\n%s" , last -> value , trailer -> buf );
902
907
strbuf_strip_suffix (& sb , "\n" );
903
908
free (last -> value );
904
909
last -> value = strbuf_detach (& sb , NULL );
905
910
continue ;
906
911
}
907
- separator_pos = find_separator (lines [ i ] -> buf , separators );
912
+ separator_pos = find_separator (trailer -> buf , separators );
908
913
if (separator_pos >= 1 ) {
909
- parse_trailer (& tok , & val , NULL , lines [ i ] -> buf ,
914
+ parse_trailer (& tok , & val , NULL , trailer -> buf ,
910
915
separator_pos );
911
916
last = add_trailer_item (head ,
912
917
strbuf_detach (& tok , NULL ),
913
918
strbuf_detach (& val , NULL ));
914
919
} else {
915
- strbuf_addbuf (& val , lines [ i ] );
920
+ strbuf_addbuf (& val , trailer );
916
921
strbuf_strip_suffix (& val , "\n" );
917
922
add_trailer_item (head ,
918
923
NULL ,
919
924
strbuf_detach (& val , NULL ));
920
925
last = NULL ;
921
926
}
922
927
}
928
+ strbuf_list_free (trailer_lines );
923
929
924
930
return trailer_end ;
925
931
}
@@ -968,21 +974,21 @@ void process_trailers(const char *file, int in_place, int trim_empty, struct str
968
974
{
969
975
LIST_HEAD (head );
970
976
LIST_HEAD (arg_head );
971
- struct strbuf * * lines ;
977
+ struct strbuf sb = STRBUF_INIT ;
972
978
int trailer_end ;
973
979
FILE * outfile = stdout ;
974
980
975
981
/* Default config must be setup first */
976
982
git_config (git_trailer_default_config , NULL );
977
983
git_config (git_trailer_config , NULL );
978
984
979
- lines = read_input_file (file );
985
+ read_input_file (& sb , file );
980
986
981
987
if (in_place )
982
988
outfile = create_in_place_tempfile (file );
983
989
984
990
/* Print the lines before the trailers */
985
- trailer_end = process_input_file (outfile , lines , & head );
991
+ trailer_end = process_input_file (outfile , sb . buf , & head );
986
992
987
993
process_command_line_args (& arg_head , trailers );
988
994
@@ -993,11 +999,11 @@ void process_trailers(const char *file, int in_place, int trim_empty, struct str
993
999
free_all (& head );
994
1000
995
1001
/* Print the lines after the trailers as is */
996
- print_lines ( outfile , lines , trailer_end , INT_MAX );
1002
+ fwrite ( sb . buf + trailer_end , 1 , sb . len - trailer_end , outfile );
997
1003
998
1004
if (in_place )
999
1005
if (rename_tempfile (& trailers_tempfile , file ))
1000
1006
die_errno (_ ("could not rename temporary file to %s" ), file );
1001
1007
1002
- strbuf_list_free ( lines );
1008
+ strbuf_release ( & sb );
1003
1009
}
0 commit comments