@@ -69,6 +69,14 @@ static int same_trailer(struct trailer_item *a, struct trailer_item *b)
6969 return same_token (a , b ) && same_value (a , b );
7070}
7171
72+ static inline int contains_only_spaces (const char * str )
73+ {
74+ const char * s = str ;
75+ while (* s && isspace (* s ))
76+ s ++ ;
77+ return !* s ;
78+ }
79+
7280static void free_trailer_item (struct trailer_item * item )
7381{
7482 free (item -> conf .name );
@@ -574,3 +582,118 @@ static struct trailer_item *process_command_line_args(struct string_list *traile
574582
575583 return arg_tok_first ;
576584}
585+
586+ static struct strbuf * * read_input_file (const char * file )
587+ {
588+ struct strbuf * * lines ;
589+ struct strbuf sb = STRBUF_INIT ;
590+
591+ if (file ) {
592+ if (strbuf_read_file (& sb , file , 0 ) < 0 )
593+ die_errno (_ ("could not read input file '%s'" ), file );
594+ } else {
595+ if (strbuf_read (& sb , fileno (stdin ), 0 ) < 0 )
596+ die_errno (_ ("could not read from stdin" ));
597+ }
598+
599+ lines = strbuf_split (& sb , '\n' );
600+
601+ strbuf_release (& sb );
602+
603+ return lines ;
604+ }
605+
606+ /*
607+ * Return the (0 based) index of the start of the patch or the line
608+ * count if there is no patch in the message.
609+ */
610+ static int find_patch_start (struct strbuf * * lines , int count )
611+ {
612+ int i ;
613+
614+ /* Get the start of the patch part if any */
615+ for (i = 0 ; i < count ; i ++ ) {
616+ if (starts_with (lines [i ]-> buf , "---" ))
617+ return i ;
618+ }
619+
620+ return count ;
621+ }
622+
623+ /*
624+ * Return the (0 based) index of the first trailer line or count if
625+ * there are no trailers. Trailers are searched only in the lines from
626+ * index (count - 1) down to index 0.
627+ */
628+ static int find_trailer_start (struct strbuf * * lines , int count )
629+ {
630+ int start , only_spaces = 1 ;
631+
632+ /*
633+ * Get the start of the trailers by looking starting from the end
634+ * for a line with only spaces before lines with one separator.
635+ */
636+ for (start = count - 1 ; start >= 0 ; start -- ) {
637+ if (lines [start ]-> buf [0 ] == comment_line_char )
638+ continue ;
639+ if (contains_only_spaces (lines [start ]-> buf )) {
640+ if (only_spaces )
641+ continue ;
642+ return start + 1 ;
643+ }
644+ if (strcspn (lines [start ]-> buf , separators ) < lines [start ]-> len ) {
645+ if (only_spaces )
646+ only_spaces = 0 ;
647+ continue ;
648+ }
649+ return count ;
650+ }
651+
652+ return only_spaces ? count : 0 ;
653+ }
654+
655+ static int has_blank_line_before (struct strbuf * * lines , int start )
656+ {
657+ for (;start >= 0 ; start -- ) {
658+ if (lines [start ]-> buf [0 ] == comment_line_char )
659+ continue ;
660+ return contains_only_spaces (lines [start ]-> buf );
661+ }
662+ return 0 ;
663+ }
664+
665+ static void print_lines (struct strbuf * * lines , int start , int end )
666+ {
667+ int i ;
668+ for (i = start ; lines [i ] && i < end ; i ++ )
669+ printf ("%s" , lines [i ]-> buf );
670+ }
671+
672+ static int process_input_file (struct strbuf * * lines ,
673+ struct trailer_item * * in_tok_first ,
674+ struct trailer_item * * in_tok_last )
675+ {
676+ int count = 0 ;
677+ int patch_start , trailer_start , i ;
678+
679+ /* Get the line count */
680+ while (lines [count ])
681+ count ++ ;
682+
683+ patch_start = find_patch_start (lines , count );
684+ trailer_start = find_trailer_start (lines , patch_start );
685+
686+ /* Print lines before the trailers as is */
687+ print_lines (lines , 0 , trailer_start );
688+
689+ if (!has_blank_line_before (lines , trailer_start - 1 ))
690+ printf ("\n" );
691+
692+ /* Parse trailer lines */
693+ for (i = trailer_start ; i < patch_start ; i ++ ) {
694+ struct trailer_item * new = create_trailer_item (lines [i ]-> buf );
695+ add_trailer_item (in_tok_first , in_tok_last , new );
696+ }
697+
698+ return patch_start ;
699+ }
0 commit comments