@@ -886,6 +886,7 @@ struct format_config {
886886 char * signature ;
887887 char * signature_file ;
888888 enum cover_setting config_cover_letter ;
889+ char * fmt_cover_letter_commit_list ;
889890 char * config_output_directory ;
890891 enum cover_from_description cover_from_description_mode ;
891892 int show_notes ;
@@ -930,6 +931,7 @@ static void format_config_release(struct format_config *cfg)
930931 string_list_clear (& cfg -> extra_cc , 0 );
931932 strbuf_release (& cfg -> sprefix );
932933 free (cfg -> fmt_patch_suffix );
934+ free (cfg -> fmt_cover_letter_commit_list );
933935}
934936
935937static enum cover_from_description parse_cover_from_description (const char * arg )
@@ -1052,6 +1054,19 @@ static int git_format_config(const char *var, const char *value,
10521054 cfg -> config_cover_letter = git_config_bool (var , value ) ? COVER_ON : COVER_OFF ;
10531055 return 0 ;
10541056 }
1057+ if (!strcmp (var , "format.commitlistformat" )) {
1058+ struct strbuf tmp = STRBUF_INIT ;
1059+ strbuf_init (& tmp , 0 );
1060+ if (value )
1061+ strbuf_addstr (& tmp , value );
1062+ else
1063+ strbuf_addstr (& tmp , "log:[%(count)/%(total)] %s" );
1064+
1065+ FREE_AND_NULL (cfg -> fmt_cover_letter_commit_list );
1066+ git_config_string (& cfg -> fmt_cover_letter_commit_list , var , tmp .buf );
1067+ strbuf_release (& tmp );
1068+ return 0 ;
1069+ }
10551070 if (!strcmp (var , "format.outputdirectory" )) {
10561071 FREE_AND_NULL (cfg -> config_output_directory );
10571072 return git_config_string (& cfg -> config_output_directory , var , value );
@@ -1335,13 +1350,55 @@ static void get_notes_args(struct strvec *arg, struct rev_info *rev)
13351350 }
13361351}
13371352
1353+ static void generate_shortlog_cover_letter (struct shortlog * log ,
1354+ struct rev_info * rev ,
1355+ struct commit * * list ,
1356+ int nr )
1357+ {
1358+ shortlog_init (log );
1359+ log -> wrap_lines = 1 ;
1360+ log -> wrap = MAIL_DEFAULT_WRAP ;
1361+ log -> in1 = 2 ;
1362+ log -> in2 = 4 ;
1363+ log -> file = rev -> diffopt .file ;
1364+ log -> groups = SHORTLOG_GROUP_AUTHOR ;
1365+ shortlog_finish_setup (log );
1366+ for (int i = 0 ; i < nr ; i ++ )
1367+ shortlog_add_commit (log , list [i ]);
1368+
1369+ shortlog_output (log );
1370+ }
1371+
1372+ static void generate_commit_list_cover (FILE * cover_file , const char * format ,
1373+ struct commit * * list , int n )
1374+ {
1375+ struct strbuf commit_line = STRBUF_INIT ;
1376+ struct pretty_print_context ctx = {0 };
1377+ struct rev_info rev = REV_INFO_INIT ;
1378+
1379+ strbuf_init (& commit_line , 0 );
1380+ rev .total = n ;
1381+ ctx .rev = & rev ;
1382+ for (int i = n - 1 ; i >= 0 ; i -- ) {
1383+ rev .nr = n - i ;
1384+ repo_format_commit_message (the_repository , list [i ], format ,
1385+ & commit_line , & ctx );
1386+ fprintf (cover_file , "%s\n" , commit_line .buf );
1387+ strbuf_reset (& commit_line );
1388+ }
1389+ fprintf (cover_file , "\n" );
1390+
1391+ strbuf_release (& commit_line );
1392+ }
1393+
13381394static void make_cover_letter (struct rev_info * rev , int use_separate_file ,
13391395 struct commit * origin ,
13401396 int nr , struct commit * * list ,
13411397 const char * description_file ,
13421398 const char * branch_name ,
13431399 int quiet ,
1344- const struct format_config * cfg )
1400+ const struct format_config * cfg ,
1401+ const char * format )
13451402{
13461403 const char * from ;
13471404 struct shortlog log ;
@@ -1388,18 +1445,12 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file,
13881445 free (pp .after_subject );
13891446 strbuf_release (& sb );
13901447
1391- shortlog_init (& log );
1392- log .wrap_lines = 1 ;
1393- log .wrap = MAIL_DEFAULT_WRAP ;
1394- log .in1 = 2 ;
1395- log .in2 = 4 ;
1396- log .file = rev -> diffopt .file ;
1397- log .groups = SHORTLOG_GROUP_AUTHOR ;
1398- shortlog_finish_setup (& log );
1399- for (i = 0 ; i < nr ; i ++ )
1400- shortlog_add_commit (& log , list [i ]);
1401-
1402- shortlog_output (& log );
1448+ if (skip_prefix (format , "log:" , & format ))
1449+ generate_commit_list_cover (rev -> diffopt .file , format , list , nr );
1450+ else if (!strcmp (format , "shortlog" ))
1451+ generate_shortlog_cover_letter (& log , rev , list , nr );
1452+ else
1453+ die (_ ("'%s' is not a valid format string" ), format );
14031454
14041455 /* We can only do diffstat with a unique reference point */
14051456 if (origin )
@@ -1917,6 +1968,7 @@ int cmd_format_patch(int argc,
19171968 int just_numbers = 0 ;
19181969 int ignore_if_in_upstream = 0 ;
19191970 int cover_letter = -1 ;
1971+ const char * cover_letter_fmt = NULL ;
19201972 int boundary_count = 0 ;
19211973 int no_binary_diff = 0 ;
19221974 int zero_commit = 0 ;
@@ -1963,6 +2015,8 @@ int cmd_format_patch(int argc,
19632015 N_ ("print patches to standard out" )),
19642016 OPT_BOOL (0 , "cover-letter" , & cover_letter ,
19652017 N_ ("generate a cover letter" )),
2018+ OPT_STRING (0 , "cover-letter-format" , & cover_letter_fmt , N_ ("format-spec" ),
2019+ N_ ("format spec used for the commit list in the cover letter" )),
19662020 OPT_BOOL (0 , "numbered-files" , & just_numbers ,
19672021 N_ ("use simple number sequence for output file names" )),
19682022 OPT_STRING (0 , "suffix" , & fmt_patch_suffix , N_ ("sfx" ),
@@ -2300,6 +2354,13 @@ int cmd_format_patch(int argc,
23002354 /* nothing to do */
23012355 goto done ;
23022356 total = list .nr ;
2357+
2358+ if (!cover_letter_fmt ) {
2359+ cover_letter_fmt = cfg .fmt_cover_letter_commit_list ;
2360+ if (!cover_letter_fmt )
2361+ cover_letter_fmt = "shortlog" ;
2362+ }
2363+
23032364 if (cover_letter == -1 ) {
23042365 if (cfg .config_cover_letter == COVER_AUTO )
23052366 cover_letter = (total > 1 );
@@ -2386,12 +2447,14 @@ int cmd_format_patch(int argc,
23862447 }
23872448 rev .numbered_files = just_numbers ;
23882449 rev .patch_suffix = fmt_patch_suffix ;
2450+
23892451 if (cover_letter ) {
23902452 if (cfg .thread )
23912453 gen_message_id (& rev , "cover" );
23922454 make_cover_letter (& rev , !!output_directory ,
23932455 origin , list .nr , list .items ,
2394- description_file , branch_name , quiet , & cfg );
2456+ description_file , branch_name , quiet , & cfg ,
2457+ cover_letter_fmt );
23952458 print_bases (& bases , rev .diffopt .file );
23962459 print_signature (signature , rev .diffopt .file );
23972460 total ++ ;
0 commit comments