@@ -127,8 +127,8 @@ static struct used_atom {
127
127
unsigned int nobracket : 1 , push : 1 , push_remote : 1 ;
128
128
} remote_ref ;
129
129
struct {
130
- enum { C_BARE , C_BODY , C_BODY_DEP , C_LENGTH ,
131
- C_LINES , C_SIG , C_SUB , C_TRAILERS } option ;
130
+ enum { C_BARE , C_BODY , C_BODY_DEP , C_LENGTH , C_LINES ,
131
+ C_SIG , C_SUB , C_SUB_SANITIZE , C_TRAILERS } option ;
132
132
struct process_trailer_options trailer_opts ;
133
133
unsigned int nlines ;
134
134
} contents ;
@@ -139,7 +139,10 @@ static struct used_atom {
139
139
struct {
140
140
enum { O_FULL , O_LENGTH , O_SHORT } option ;
141
141
unsigned int length ;
142
- } objectname ;
142
+ } oid ;
143
+ struct email_option {
144
+ enum { EO_RAW , EO_TRIM , EO_LOCALPART } option ;
145
+ } email_option ;
143
146
struct refname_atom refname ;
144
147
char * head ;
145
148
} u ;
@@ -298,9 +301,12 @@ static int body_atom_parser(const struct ref_format *format, struct used_atom *a
298
301
static int subject_atom_parser (const struct ref_format * format , struct used_atom * atom ,
299
302
const char * arg , struct strbuf * err )
300
303
{
301
- if (arg )
302
- return strbuf_addf_ret (err , -1 , _ ("%%(subject) does not take arguments" ));
303
- atom -> u .contents .option = C_SUB ;
304
+ if (!arg )
305
+ atom -> u .contents .option = C_SUB ;
306
+ else if (!strcmp (arg , "sanitize" ))
307
+ atom -> u .contents .option = C_SUB_SANITIZE ;
308
+ else
309
+ return strbuf_addf_ret (err , -1 , _ ("unrecognized %%(subject) argument: %s" ), arg );
304
310
return 0 ;
305
311
}
306
312
@@ -360,22 +366,36 @@ static int contents_atom_parser(const struct ref_format *format, struct used_ato
360
366
return 0 ;
361
367
}
362
368
363
- static int objectname_atom_parser (const struct ref_format * format , struct used_atom * atom ,
364
- const char * arg , struct strbuf * err )
369
+ static int oid_atom_parser (const struct ref_format * format , struct used_atom * atom ,
370
+ const char * arg , struct strbuf * err )
365
371
{
366
372
if (!arg )
367
- atom -> u .objectname .option = O_FULL ;
373
+ atom -> u .oid .option = O_FULL ;
368
374
else if (!strcmp (arg , "short" ))
369
- atom -> u .objectname .option = O_SHORT ;
375
+ atom -> u .oid .option = O_SHORT ;
370
376
else if (skip_prefix (arg , "short=" , & arg )) {
371
- atom -> u .objectname .option = O_LENGTH ;
372
- if (strtoul_ui (arg , 10 , & atom -> u .objectname .length ) ||
373
- atom -> u .objectname .length == 0 )
374
- return strbuf_addf_ret (err , -1 , _ ("positive value expected objectname:short=%s " ), arg );
375
- if (atom -> u .objectname .length < MINIMUM_ABBREV )
376
- atom -> u .objectname .length = MINIMUM_ABBREV ;
377
+ atom -> u .oid .option = O_LENGTH ;
378
+ if (strtoul_ui (arg , 10 , & atom -> u .oid .length ) ||
379
+ atom -> u .oid .length == 0 )
380
+ return strbuf_addf_ret (err , -1 , _ ("positive value expected '%s' in %%(%s) " ), arg , atom -> name );
381
+ if (atom -> u .oid .length < MINIMUM_ABBREV )
382
+ atom -> u .oid .length = MINIMUM_ABBREV ;
377
383
} else
378
- return strbuf_addf_ret (err , -1 , _ ("unrecognized %%(objectname) argument: %s" ), arg );
384
+ return strbuf_addf_ret (err , -1 , _ ("unrecognized argument '%s' in %%(%s)" ), arg , atom -> name );
385
+ return 0 ;
386
+ }
387
+
388
+ static int person_email_atom_parser (const struct ref_format * format , struct used_atom * atom ,
389
+ const char * arg , struct strbuf * err )
390
+ {
391
+ if (!arg )
392
+ atom -> u .email_option .option = EO_RAW ;
393
+ else if (!strcmp (arg , "trim" ))
394
+ atom -> u .email_option .option = EO_TRIM ;
395
+ else if (!strcmp (arg , "localpart" ))
396
+ atom -> u .email_option .option = EO_LOCALPART ;
397
+ else
398
+ return strbuf_addf_ret (err , -1 , _ ("unrecognized email option: %s" ), arg );
379
399
return 0 ;
380
400
}
381
401
@@ -480,25 +500,25 @@ static struct {
480
500
{ "refname" , SOURCE_NONE , FIELD_STR , refname_atom_parser },
481
501
{ "objecttype" , SOURCE_OTHER , FIELD_STR , objecttype_atom_parser },
482
502
{ "objectsize" , SOURCE_OTHER , FIELD_ULONG , objectsize_atom_parser },
483
- { "objectname" , SOURCE_OTHER , FIELD_STR , objectname_atom_parser },
503
+ { "objectname" , SOURCE_OTHER , FIELD_STR , oid_atom_parser },
484
504
{ "deltabase" , SOURCE_OTHER , FIELD_STR , deltabase_atom_parser },
485
- { "tree" , SOURCE_OBJ },
486
- { "parent" , SOURCE_OBJ },
505
+ { "tree" , SOURCE_OBJ , FIELD_STR , oid_atom_parser },
506
+ { "parent" , SOURCE_OBJ , FIELD_STR , oid_atom_parser },
487
507
{ "numparent" , SOURCE_OBJ , FIELD_ULONG },
488
508
{ "object" , SOURCE_OBJ },
489
509
{ "type" , SOURCE_OBJ },
490
510
{ "tag" , SOURCE_OBJ },
491
511
{ "author" , SOURCE_OBJ },
492
512
{ "authorname" , SOURCE_OBJ },
493
- { "authoremail" , SOURCE_OBJ },
513
+ { "authoremail" , SOURCE_OBJ , FIELD_STR , person_email_atom_parser },
494
514
{ "authordate" , SOURCE_OBJ , FIELD_TIME },
495
515
{ "committer" , SOURCE_OBJ },
496
516
{ "committername" , SOURCE_OBJ },
497
- { "committeremail" , SOURCE_OBJ },
517
+ { "committeremail" , SOURCE_OBJ , FIELD_STR , person_email_atom_parser },
498
518
{ "committerdate" , SOURCE_OBJ , FIELD_TIME },
499
519
{ "tagger" , SOURCE_OBJ },
500
520
{ "taggername" , SOURCE_OBJ },
501
- { "taggeremail" , SOURCE_OBJ },
521
+ { "taggeremail" , SOURCE_OBJ , FIELD_STR , person_email_atom_parser },
502
522
{ "taggerdate" , SOURCE_OBJ , FIELD_TIME },
503
523
{ "creator" , SOURCE_OBJ },
504
524
{ "creatordate" , SOURCE_OBJ , FIELD_TIME },
@@ -903,21 +923,27 @@ int verify_ref_format(struct ref_format *format)
903
923
return 0 ;
904
924
}
905
925
906
- static int grab_objectname (const char * name , const struct object_id * oid ,
907
- struct atom_value * v , struct used_atom * atom )
926
+ static const char * do_grab_oid (const char * field , const struct object_id * oid ,
927
+ struct used_atom * atom )
908
928
{
909
- if (starts_with (name , "objectname" )) {
910
- if (atom -> u .objectname .option == O_SHORT ) {
911
- v -> s = xstrdup (find_unique_abbrev (oid , DEFAULT_ABBREV ));
912
- return 1 ;
913
- } else if (atom -> u .objectname .option == O_FULL ) {
914
- v -> s = xstrdup (oid_to_hex (oid ));
915
- return 1 ;
916
- } else if (atom -> u .objectname .option == O_LENGTH ) {
917
- v -> s = xstrdup (find_unique_abbrev (oid , atom -> u .objectname .length ));
918
- return 1 ;
919
- } else
920
- BUG ("unknown %%(objectname) option" );
929
+ switch (atom -> u .oid .option ) {
930
+ case O_FULL :
931
+ return oid_to_hex (oid );
932
+ case O_LENGTH :
933
+ return find_unique_abbrev (oid , atom -> u .oid .length );
934
+ case O_SHORT :
935
+ return find_unique_abbrev (oid , DEFAULT_ABBREV );
936
+ default :
937
+ BUG ("unknown %%(%s) option" , field );
938
+ }
939
+ }
940
+
941
+ static int grab_oid (const char * name , const char * field , const struct object_id * oid ,
942
+ struct atom_value * v , struct used_atom * atom )
943
+ {
944
+ if (starts_with (name , field )) {
945
+ v -> s = xstrdup (do_grab_oid (field , oid , atom ));
946
+ return 1 ;
921
947
}
922
948
return 0 ;
923
949
}
@@ -945,7 +971,7 @@ static void grab_common_values(struct atom_value *val, int deref, struct expand_
945
971
} else if (!strcmp (name , "deltabase" ))
946
972
v -> s = xstrdup (oid_to_hex (& oi -> delta_base_oid ));
947
973
else if (deref )
948
- grab_objectname (name , & oi -> oid , v , & used_atom [i ]);
974
+ grab_oid (name , "objectname" , & oi -> oid , v , & used_atom [i ]);
949
975
}
950
976
}
951
977
@@ -984,21 +1010,20 @@ static void grab_commit_values(struct atom_value *val, int deref, struct object
984
1010
continue ;
985
1011
if (deref )
986
1012
name ++ ;
987
- if (!strcmp (name , "tree" )) {
988
- v -> s = xstrdup (oid_to_hex (get_commit_tree_oid (commit )));
989
- }
990
- else if (!strcmp (name , "numparent" )) {
1013
+ if (grab_oid (name , "tree" , get_commit_tree_oid (commit ), v , & used_atom [i ]))
1014
+ continue ;
1015
+ if (!strcmp (name , "numparent" )) {
991
1016
v -> value = commit_list_count (commit -> parents );
992
1017
v -> s = xstrfmt ("%lu" , (unsigned long )v -> value );
993
1018
}
994
- else if (! strcmp (name , "parent" )) {
1019
+ else if (starts_with (name , "parent" )) {
995
1020
struct commit_list * parents ;
996
1021
struct strbuf s = STRBUF_INIT ;
997
1022
for (parents = commit -> parents ; parents ; parents = parents -> next ) {
998
- struct commit * parent = parents -> item ;
1023
+ struct object_id * oid = & parents -> item -> object . oid ;
999
1024
if (parents != commit -> parents )
1000
1025
strbuf_addch (& s , ' ' );
1001
- strbuf_addstr (& s , oid_to_hex ( & parent -> object . oid ));
1026
+ strbuf_addstr (& s , do_grab_oid ( " parent" , oid , & used_atom [ i ] ));
1002
1027
}
1003
1028
v -> s = strbuf_detach (& s , NULL );
1004
1029
}
@@ -1039,16 +1064,35 @@ static const char *copy_name(const char *buf)
1039
1064
return xstrdup ("" );
1040
1065
}
1041
1066
1042
- static const char * copy_email (const char * buf )
1067
+ static const char * copy_email (const char * buf , struct used_atom * atom )
1043
1068
{
1044
1069
const char * email = strchr (buf , '<' );
1045
1070
const char * eoemail ;
1046
1071
if (!email )
1047
1072
return xstrdup ("" );
1048
- eoemail = strchr (email , '>' );
1073
+ switch (atom -> u .email_option .option ) {
1074
+ case EO_RAW :
1075
+ eoemail = strchr (email , '>' );
1076
+ if (eoemail )
1077
+ eoemail ++ ;
1078
+ break ;
1079
+ case EO_TRIM :
1080
+ email ++ ;
1081
+ eoemail = strchr (email , '>' );
1082
+ break ;
1083
+ case EO_LOCALPART :
1084
+ email ++ ;
1085
+ eoemail = strchr (email , '@' );
1086
+ if (!eoemail )
1087
+ eoemail = strchr (email , '>' );
1088
+ break ;
1089
+ default :
1090
+ BUG ("unknown email option" );
1091
+ }
1092
+
1049
1093
if (!eoemail )
1050
1094
return xstrdup ("" );
1051
- return xmemdupz (email , eoemail + 1 - email );
1095
+ return xmemdupz (email , eoemail - email );
1052
1096
}
1053
1097
1054
1098
static char * copy_subject (const char * buf , unsigned long len )
@@ -1118,7 +1162,7 @@ static void grab_person(const char *who, struct atom_value *val, int deref, void
1118
1162
continue ;
1119
1163
if (name [wholen ] != 0 &&
1120
1164
strcmp (name + wholen , "name" ) &&
1121
- strcmp (name + wholen , "email" ) &&
1165
+ ! starts_with (name + wholen , "email" ) &&
1122
1166
!starts_with (name + wholen , "date" ))
1123
1167
continue ;
1124
1168
if (!wholine )
@@ -1129,8 +1173,8 @@ static void grab_person(const char *who, struct atom_value *val, int deref, void
1129
1173
v -> s = copy_line (wholine );
1130
1174
else if (!strcmp (name + wholen , "name" ))
1131
1175
v -> s = copy_name (wholine );
1132
- else if (! strcmp (name + wholen , "email" ))
1133
- v -> s = copy_email (wholine );
1176
+ else if (starts_with (name + wholen , "email" ))
1177
+ v -> s = copy_email (wholine , & used_atom [ i ] );
1134
1178
else if (starts_with (name + wholen , "date" ))
1135
1179
grab_date (wholine , v , name );
1136
1180
}
@@ -1243,8 +1287,8 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, void *buf)
1243
1287
continue ;
1244
1288
if (deref )
1245
1289
name ++ ;
1246
- if (strcmp (name , "subject " ) &&
1247
- strcmp (name , "body " ) &&
1290
+ if (strcmp (name , "body " ) &&
1291
+ ! starts_with (name , "subject " ) &&
1248
1292
!starts_with (name , "trailers" ) &&
1249
1293
!starts_with (name , "contents" ))
1250
1294
continue ;
@@ -1256,7 +1300,11 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, void *buf)
1256
1300
1257
1301
if (atom -> u .contents .option == C_SUB )
1258
1302
v -> s = copy_subject (subpos , sublen );
1259
- else if (atom -> u .contents .option == C_BODY_DEP )
1303
+ else if (atom -> u .contents .option == C_SUB_SANITIZE ) {
1304
+ struct strbuf sb = STRBUF_INIT ;
1305
+ format_sanitized_subject (& sb , subpos , sublen );
1306
+ v -> s = strbuf_detach (& sb , NULL );
1307
+ } else if (atom -> u .contents .option == C_BODY_DEP )
1260
1308
v -> s = xmemdupz (bodypos , bodylen );
1261
1309
else if (atom -> u .contents .option == C_LENGTH )
1262
1310
v -> s = xstrfmt ("%" PRIuMAX , (uintmax_t )strlen (subpos ));
@@ -1706,7 +1754,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
1706
1754
v -> s = xstrdup (buf + 1 );
1707
1755
}
1708
1756
continue ;
1709
- } else if (!deref && grab_objectname (name , & ref -> objectname , v , atom )) {
1757
+ } else if (!deref && grab_oid (name , "objectname" , & ref -> objectname , v , atom )) {
1710
1758
continue ;
1711
1759
} else if (!strcmp (name , "HEAD" )) {
1712
1760
if (atom -> u .head && !strcmp (ref -> refname , atom -> u .head ))
0 commit comments