@@ -1101,22 +1101,26 @@ static void emit_binary_diff(mmfile_t *one, mmfile_t *two)
11011101static void setup_diff_attr_check (struct git_attr_check * check )
11021102{
11031103 static struct git_attr * attr_diff ;
1104+ static struct git_attr * attr_diff_func_name ;
11041105
11051106 if (!attr_diff ) {
11061107 attr_diff = git_attr ("diff" , 4 );
1108+ attr_diff_func_name = git_attr ("funcname" , 8 );
11071109 }
11081110 check [0 ].attr = attr_diff ;
1111+ check [1 ].attr = attr_diff_func_name ;
11091112}
11101113
11111114static void diff_filespec_check_attr (struct diff_filespec * one )
11121115{
1113- struct git_attr_check attr_diff_check [1 ];
1116+ struct git_attr_check attr_diff_check [2 ];
11141117
11151118 if (one -> checked_attr )
11161119 return ;
11171120
11181121 setup_diff_attr_check (attr_diff_check );
11191122 one -> is_binary = 0 ;
1123+ one -> hunk_header_ident = NULL ;
11201124
11211125 if (!git_checkattr (one -> path , ARRAY_SIZE (attr_diff_check ), attr_diff_check )) {
11221126 const char * value ;
@@ -1127,6 +1131,13 @@ static void diff_filespec_check_attr(struct diff_filespec *one)
11271131 ;
11281132 else if (ATTR_FALSE (value ))
11291133 one -> is_binary = 1 ;
1134+
1135+ /* hunk header ident */
1136+ value = attr_diff_check [1 ].value ;
1137+ if (ATTR_TRUE (value ) || ATTR_FALSE (value ) || ATTR_UNSET (value ))
1138+ ;
1139+ else
1140+ one -> hunk_header_ident = value ;
11301141 }
11311142
11321143 if (!one -> data && DIFF_FILE_VALID (one ))
@@ -1143,6 +1154,82 @@ int diff_filespec_is_binary(struct diff_filespec *one)
11431154 return one -> is_binary ;
11441155}
11451156
1157+ static struct hunk_header_regexp {
1158+ char * name ;
1159+ char * regexp ;
1160+ struct hunk_header_regexp * next ;
1161+ } * hunk_header_regexp_list , * * hunk_header_regexp_tail ;
1162+
1163+ static int hunk_header_config (const char * var , const char * value )
1164+ {
1165+ static const char funcname [] = "funcname." ;
1166+ struct hunk_header_regexp * hh ;
1167+
1168+ if (prefixcmp (var , funcname ))
1169+ return 0 ;
1170+ var += strlen (funcname );
1171+ for (hh = hunk_header_regexp_list ; hh ; hh = hh -> next )
1172+ if (!strcmp (var , hh -> name )) {
1173+ free (hh -> regexp );
1174+ hh -> regexp = xstrdup (value );
1175+ return 0 ;
1176+ }
1177+ hh = xcalloc (1 , sizeof (* hh ));
1178+ hh -> name = xstrdup (var );
1179+ hh -> regexp = xstrdup (value );
1180+ hh -> next = NULL ;
1181+ * hunk_header_regexp_tail = hh ;
1182+ return 0 ;
1183+ }
1184+
1185+ static const char * hunk_header_regexp (const char * ident )
1186+ {
1187+ struct hunk_header_regexp * hh ;
1188+
1189+ if (!hunk_header_regexp_tail ) {
1190+ hunk_header_regexp_tail = & hunk_header_regexp_list ;
1191+ git_config (hunk_header_config );
1192+ }
1193+ for (hh = hunk_header_regexp_list ; hh ; hh = hh -> next )
1194+ if (!strcmp (ident , hh -> name ))
1195+ return hh -> regexp ;
1196+ return NULL ;
1197+ }
1198+
1199+ static const char * diff_hunk_header_regexp (struct diff_filespec * one )
1200+ {
1201+ const char * ident , * regexp ;
1202+
1203+ diff_filespec_check_attr (one );
1204+ ident = one -> hunk_header_ident ;
1205+
1206+ if (!ident )
1207+ /*
1208+ * If the config file has "funcname.default" defined, that
1209+ * regexp is used; otherwise NULL is returned and xemit uses
1210+ * the built-in default.
1211+ */
1212+ return hunk_header_regexp ("default" );
1213+
1214+ /* Look up custom "funcname.$ident" regexp from config. */
1215+ regexp = hunk_header_regexp (ident );
1216+ if (regexp )
1217+ return regexp ;
1218+
1219+ /*
1220+ * And define built-in fallback patterns here. Note that
1221+ * these can be overriden by the user's config settings.
1222+ */
1223+ if (!strcmp (ident , "java" ))
1224+ return "!^[ ]*\\(catch\\|do\\|for\\|if\\|instanceof\\|"
1225+ "new\\|return\\|switch\\|throw\\|while\\)\n"
1226+ "^[ ]*\\(\\([ ]*"
1227+ "[A-Za-z_][A-Za-z_0-9]*\\)\\{2,\\}"
1228+ "[ ]*([^;]*$\\)" ;
1229+
1230+ return NULL ;
1231+ }
1232+
11461233static void builtin_diff (const char * name_a ,
11471234 const char * name_b ,
11481235 struct diff_filespec * one ,
@@ -1217,6 +1304,11 @@ static void builtin_diff(const char *name_a,
12171304 xdemitconf_t xecfg ;
12181305 xdemitcb_t ecb ;
12191306 struct emit_callback ecbdata ;
1307+ const char * hunk_header_regexp ;
1308+
1309+ hunk_header_regexp = diff_hunk_header_regexp (one );
1310+ if (!hunk_header_regexp )
1311+ hunk_header_regexp = diff_hunk_header_regexp (two );
12201312
12211313 memset (& xecfg , 0 , sizeof (xecfg ));
12221314 memset (& ecbdata , 0 , sizeof (ecbdata ));
@@ -1226,6 +1318,8 @@ static void builtin_diff(const char *name_a,
12261318 xpp .flags = XDF_NEED_MINIMAL | o -> xdl_opts ;
12271319 xecfg .ctxlen = o -> context ;
12281320 xecfg .flags = XDL_EMIT_FUNCNAMES ;
1321+ if (hunk_header_regexp )
1322+ xdiff_set_find_func (& xecfg , hunk_header_regexp );
12291323 if (!diffopts )
12301324 ;
12311325 else if (!prefixcmp (diffopts , "--unified=" ))
0 commit comments