@@ -817,28 +817,56 @@ static ssize_t last_line(const char *buf, size_t len)
817
817
}
818
818
819
819
/*
820
- * Return the position of the start of the patch or the length of str if there
821
- * is no patch in the message.
820
+ * Find the end of the log message as an offset from the start of the input
821
+ * (where callers of this function are interested in looking for a trailers
822
+ * block in the same input). We have to consider two categories of content that
823
+ * can come at the end of the input which we want to ignore (because they don't
824
+ * belong in the log message):
825
+ *
826
+ * (1) the "patch part" which begins with a "---" divider and has patch
827
+ * information (like the output of git-format-patch), and
828
+ *
829
+ * (2) any trailing comment lines, blank lines like in the output of "git
830
+ * commit -v", or stuff below the "cut" (scissor) line.
831
+ *
832
+ * As a formula, the situation looks like this:
833
+ *
834
+ * INPUT = LOG MESSAGE + IGNORED
835
+ *
836
+ * where IGNORED can be either of the two categories described above. It may be
837
+ * that there is nothing to ignore. Now it may be the case that the LOG MESSAGE
838
+ * contains a trailer block, but that's not the concern of this function.
822
839
*/
823
- static size_t find_patch_start (const char * str )
840
+ static size_t find_end_of_log_message (const char * input , int no_divider )
824
841
{
842
+ size_t end ;
825
843
const char * s ;
826
844
827
- for (s = str ; * s ; s = next_line (s )) {
845
+ /* Assume the naive end of the input is already what we want. */
846
+ end = strlen (input );
847
+
848
+ if (no_divider )
849
+ return end ;
850
+
851
+ /* Optionally skip over any patch part ("---" line and below). */
852
+ for (s = input ; * s ; s = next_line (s )) {
828
853
const char * v ;
829
854
830
- if (skip_prefix (s , "---" , & v ) && isspace (* v ))
831
- return s - str ;
855
+ if (skip_prefix (s , "---" , & v ) && isspace (* v )) {
856
+ end = s - input ;
857
+ break ;
858
+ }
832
859
}
833
860
834
- return s - str ;
861
+ /* Skip over other ignorable bits. */
862
+ return end - ignored_log_message_bytes (input , end );
835
863
}
836
864
837
865
/*
838
866
* Return the position of the first trailer line or len if there are no
839
867
* trailers.
840
868
*/
841
- static size_t find_trailer_start (const char * buf , size_t len )
869
+ static size_t find_trailer_block_start (const char * buf , size_t len )
842
870
{
843
871
const char * s ;
844
872
ssize_t end_of_title , l ;
@@ -933,12 +961,6 @@ static size_t find_trailer_start(const char *buf, size_t len)
933
961
return len ;
934
962
}
935
963
936
- /* Return the position of the end of the trailers. */
937
- static size_t find_trailer_end (const char * buf , size_t len )
938
- {
939
- return len - ignore_non_trailer (buf , len );
940
- }
941
-
942
964
static int ends_with_blank_line (const char * buf , size_t len )
943
965
{
944
966
ssize_t ll = last_line (buf , len );
@@ -1060,7 +1082,6 @@ void process_trailers(const char *file,
1060
1082
LIST_HEAD (head );
1061
1083
struct strbuf sb = STRBUF_INIT ;
1062
1084
struct trailer_info info ;
1063
- size_t trailer_end ;
1064
1085
FILE * outfile = stdout ;
1065
1086
1066
1087
ensure_configured ();
@@ -1071,11 +1092,10 @@ void process_trailers(const char *file,
1071
1092
outfile = create_in_place_tempfile (file );
1072
1093
1073
1094
parse_trailers (& info , sb .buf , & head , opts );
1074
- trailer_end = info .trailer_end - sb .buf ;
1075
1095
1076
1096
/* Print the lines before the trailers */
1077
1097
if (!opts -> only_trailers )
1078
- fwrite (sb .buf , 1 , info .trailer_start - sb . buf , outfile );
1098
+ fwrite (sb .buf , 1 , info .trailer_block_start , outfile );
1079
1099
1080
1100
if (!opts -> only_trailers && !info .blank_line_before_trailer )
1081
1101
fprintf (outfile , "\n" );
@@ -1097,7 +1117,7 @@ void process_trailers(const char *file,
1097
1117
1098
1118
/* Print the lines after the trailers as is */
1099
1119
if (!opts -> only_trailers )
1100
- fwrite (sb .buf + trailer_end , 1 , sb .len - trailer_end , outfile );
1120
+ fwrite (sb .buf + info . trailer_block_end , 1 , sb .len - info . trailer_block_end , outfile );
1101
1121
1102
1122
if (opts -> in_place )
1103
1123
if (rename_tempfile (& trailers_tempfile , file ))
@@ -1109,24 +1129,19 @@ void process_trailers(const char *file,
1109
1129
void trailer_info_get (struct trailer_info * info , const char * str ,
1110
1130
const struct process_trailer_options * opts )
1111
1131
{
1112
- int patch_start , trailer_end , trailer_start ;
1132
+ size_t end_of_log_message = 0 , trailer_block_start = 0 ;
1113
1133
struct strbuf * * trailer_lines , * * ptr ;
1114
1134
char * * trailer_strings = NULL ;
1115
1135
size_t nr = 0 , alloc = 0 ;
1116
1136
char * * last = NULL ;
1117
1137
1118
1138
ensure_configured ();
1119
1139
1120
- if (opts -> no_divider )
1121
- patch_start = strlen (str );
1122
- else
1123
- patch_start = find_patch_start (str );
1124
-
1125
- trailer_end = find_trailer_end (str , patch_start );
1126
- trailer_start = find_trailer_start (str , trailer_end );
1140
+ end_of_log_message = find_end_of_log_message (str , opts -> no_divider );
1141
+ trailer_block_start = find_trailer_block_start (str , end_of_log_message );
1127
1142
1128
- trailer_lines = strbuf_split_buf (str + trailer_start ,
1129
- trailer_end - trailer_start ,
1143
+ trailer_lines = strbuf_split_buf (str + trailer_block_start ,
1144
+ end_of_log_message - trailer_block_start ,
1130
1145
'\n' ,
1131
1146
0 );
1132
1147
for (ptr = trailer_lines ; * ptr ; ptr ++ ) {
@@ -1147,9 +1162,9 @@ void trailer_info_get(struct trailer_info *info, const char *str,
1147
1162
strbuf_list_free (trailer_lines );
1148
1163
1149
1164
info -> blank_line_before_trailer = ends_with_blank_line (str ,
1150
- trailer_start );
1151
- info -> trailer_start = str + trailer_start ;
1152
- info -> trailer_end = str + trailer_end ;
1165
+ trailer_block_start );
1166
+ info -> trailer_block_start = trailer_block_start ;
1167
+ info -> trailer_block_end = end_of_log_message ;
1153
1168
info -> trailers = trailer_strings ;
1154
1169
info -> trailer_nr = nr ;
1155
1170
}
@@ -1164,6 +1179,7 @@ void trailer_info_release(struct trailer_info *info)
1164
1179
1165
1180
static void format_trailer_info (struct strbuf * out ,
1166
1181
const struct trailer_info * info ,
1182
+ const char * msg ,
1167
1183
const struct process_trailer_options * opts )
1168
1184
{
1169
1185
size_t origlen = out -> len ;
@@ -1173,8 +1189,8 @@ static void format_trailer_info(struct strbuf *out,
1173
1189
if (!opts -> only_trailers && !opts -> unfold && !opts -> filter &&
1174
1190
!opts -> separator && !opts -> key_only && !opts -> value_only &&
1175
1191
!opts -> key_value_separator ) {
1176
- strbuf_add (out , info -> trailer_start ,
1177
- info -> trailer_end - info -> trailer_start );
1192
+ strbuf_add (out , msg + info -> trailer_block_start ,
1193
+ info -> trailer_block_end - info -> trailer_block_start );
1178
1194
return ;
1179
1195
}
1180
1196
@@ -1228,7 +1244,7 @@ void format_trailers_from_commit(struct strbuf *out, const char *msg,
1228
1244
struct trailer_info info ;
1229
1245
1230
1246
trailer_info_get (& info , msg , opts );
1231
- format_trailer_info (out , & info , opts );
1247
+ format_trailer_info (out , & info , msg , opts );
1232
1248
trailer_info_release (& info );
1233
1249
}
1234
1250
0 commit comments