@@ -69,6 +69,14 @@ static int same_trailer(struct trailer_item *a, struct trailer_item *b)
69
69
return same_token (a , b ) && same_value (a , b );
70
70
}
71
71
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
+
72
80
static void free_trailer_item (struct trailer_item * item )
73
81
{
74
82
free (item -> conf .name );
@@ -574,3 +582,118 @@ static struct trailer_item *process_command_line_args(struct string_list *traile
574
582
575
583
return arg_tok_first ;
576
584
}
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