@@ -100,9 +100,9 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
100100 int quiet = 0 , source = 0 , mailmap = 0 ;
101101
102102 const struct option builtin_log_options [] = {
103- OPT_BOOLEAN (0 , "quiet" , & quiet , N_ ("suppress diff output" )),
104- OPT_BOOLEAN (0 , "source" , & source , N_ ("show source" )),
105- OPT_BOOLEAN (0 , "use-mailmap" , & mailmap , N_ ("Use mail map file" )),
103+ OPT_BOOL (0 , "quiet" , & quiet , N_ ("suppress diff output" )),
104+ OPT_BOOL (0 , "source" , & source , N_ ("show source" )),
105+ OPT_BOOL (0 , "use-mailmap" , & mailmap , N_ ("Use mail map file" )),
106106 { OPTION_CALLBACK , 0 , "decorate" , NULL , NULL , N_ ("decorate options" ),
107107 PARSE_OPT_OPTARG , decorate_callback },
108108 OPT_END ()
@@ -622,6 +622,14 @@ static void add_header(const char *value)
622622static int thread ;
623623static int do_signoff ;
624624static const char * signature = git_version_string ;
625+ static int config_cover_letter ;
626+
627+ enum {
628+ COVER_UNSET ,
629+ COVER_OFF ,
630+ COVER_ON ,
631+ COVER_AUTO
632+ };
625633
626634static int git_format_config (const char * var , const char * value , void * cb )
627635{
@@ -683,6 +691,14 @@ static int git_format_config(const char *var, const char *value, void *cb)
683691 }
684692 if (!strcmp (var , "format.signature" ))
685693 return git_config_string (& signature , var , value );
694+ if (!strcmp (var , "format.coverletter" )) {
695+ if (value && !strcasecmp (value , "auto" )) {
696+ config_cover_letter = COVER_AUTO ;
697+ return 0 ;
698+ }
699+ config_cover_letter = git_config_bool (var , value ) ? COVER_ON : COVER_OFF ;
700+ return 0 ;
701+ }
686702
687703 return git_log_config (var , value , cb );
688704}
@@ -794,9 +810,37 @@ static void add_branch_description(struct strbuf *buf, const char *branch_name)
794810 }
795811}
796812
813+ static char * find_branch_name (struct rev_info * rev )
814+ {
815+ int i , positive = -1 ;
816+ unsigned char branch_sha1 [20 ];
817+ const unsigned char * tip_sha1 ;
818+ const char * ref ;
819+ char * full_ref , * branch = NULL ;
820+
821+ for (i = 0 ; i < rev -> cmdline .nr ; i ++ ) {
822+ if (rev -> cmdline .rev [i ].flags & UNINTERESTING )
823+ continue ;
824+ if (positive < 0 )
825+ positive = i ;
826+ else
827+ return NULL ;
828+ }
829+ if (positive < 0 )
830+ return NULL ;
831+ ref = rev -> cmdline .rev [positive ].name ;
832+ tip_sha1 = rev -> cmdline .rev [positive ].item -> sha1 ;
833+ if (dwim_ref (ref , strlen (ref ), branch_sha1 , & full_ref ) &&
834+ !prefixcmp (full_ref , "refs/heads/" ) &&
835+ !hashcmp (tip_sha1 , branch_sha1 ))
836+ branch = xstrdup (full_ref + strlen ("refs/heads/" ));
837+ free (full_ref );
838+ return branch ;
839+ }
840+
797841static void make_cover_letter (struct rev_info * rev , int use_stdout ,
798842 struct commit * origin ,
799- int nr , struct commit * * list , struct commit * head ,
843+ int nr , struct commit * * list ,
800844 const char * branch_name ,
801845 int quiet )
802846{
@@ -810,6 +854,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
810854 struct diff_options opts ;
811855 int need_8bit_cte = 0 ;
812856 struct pretty_print_context pp = {0 };
857+ struct commit * head = list [0 ];
813858
814859 if (rev -> commit_format != CMIT_FMT_EMAIL )
815860 die (_ ("Cover letter needs email format" ));
@@ -827,6 +872,9 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
827872 if (has_non_ascii (list [i ]-> buffer ))
828873 need_8bit_cte = 1 ;
829874
875+ if (!branch_name )
876+ branch_name = find_branch_name (rev );
877+
830878 msg = body ;
831879 pp .fmt = CMIT_FMT_EMAIL ;
832880 pp .date_mode = DATE_RFC2822 ;
@@ -1033,45 +1081,6 @@ static int cc_callback(const struct option *opt, const char *arg, int unset)
10331081 return 0 ;
10341082}
10351083
1036- static char * find_branch_name (struct rev_info * rev )
1037- {
1038- int i , positive = -1 ;
1039- unsigned char branch_sha1 [20 ];
1040- const unsigned char * tip_sha1 ;
1041- const char * ref ;
1042- char * full_ref , * branch = NULL ;
1043-
1044- for (i = 0 ; i < rev -> cmdline .nr ; i ++ ) {
1045- if (rev -> cmdline .rev [i ].flags & UNINTERESTING )
1046- continue ;
1047- if (positive < 0 )
1048- positive = i ;
1049- else
1050- return NULL ;
1051- }
1052- if (0 <= positive ) {
1053- ref = rev -> cmdline .rev [positive ].name ;
1054- tip_sha1 = rev -> cmdline .rev [positive ].item -> sha1 ;
1055- } else if (!rev -> cmdline .nr && rev -> pending .nr == 1 &&
1056- !strcmp (rev -> pending .objects [0 ].name , "HEAD" )) {
1057- /*
1058- * No actual ref from command line, but "HEAD" from
1059- * rev->def was added in setup_revisions()
1060- * e.g. format-patch --cover-letter -12
1061- */
1062- ref = "HEAD" ;
1063- tip_sha1 = rev -> pending .objects [0 ].item -> sha1 ;
1064- } else {
1065- return NULL ;
1066- }
1067- if (dwim_ref (ref , strlen (ref ), branch_sha1 , & full_ref ) &&
1068- !prefixcmp (full_ref , "refs/heads/" ) &&
1069- !hashcmp (tip_sha1 , branch_sha1 ))
1070- branch = xstrdup (full_ref + strlen ("refs/heads/" ));
1071- free (full_ref );
1072- return branch ;
1073- }
1074-
10751084int cmd_format_patch (int argc , const char * * argv , const char * prefix )
10761085{
10771086 struct commit * commit ;
@@ -1083,10 +1092,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
10831092 int start_number = -1 ;
10841093 int just_numbers = 0 ;
10851094 int ignore_if_in_upstream = 0 ;
1086- int cover_letter = 0 ;
1095+ int cover_letter = -1 ;
10871096 int boundary_count = 0 ;
10881097 int no_binary_diff = 0 ;
1089- struct commit * origin = NULL , * head = NULL ;
1098+ struct commit * origin = NULL ;
10901099 const char * in_reply_to = NULL ;
10911100 struct patch_ids ids ;
10921101 struct strbuf buf = STRBUF_INIT ;
@@ -1101,12 +1110,12 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
11011110 { OPTION_CALLBACK , 'N' , "no-numbered" , & numbered , NULL ,
11021111 N_ ("use [PATCH] even with multiple patches" ),
11031112 PARSE_OPT_NOARG , no_numbered_callback },
1104- OPT_BOOLEAN ('s' , "signoff" , & do_signoff , N_ ("add Signed-off-by:" )),
1105- OPT_BOOLEAN (0 , "stdout" , & use_stdout ,
1113+ OPT_BOOL ('s' , "signoff" , & do_signoff , N_ ("add Signed-off-by:" )),
1114+ OPT_BOOL (0 , "stdout" , & use_stdout ,
11061115 N_ ("print patches to standard out" )),
1107- OPT_BOOLEAN (0 , "cover-letter" , & cover_letter ,
1116+ OPT_BOOL (0 , "cover-letter" , & cover_letter ,
11081117 N_ ("generate a cover letter" )),
1109- OPT_BOOLEAN (0 , "numbered-files" , & just_numbers ,
1118+ OPT_BOOL (0 , "numbered-files" , & just_numbers ,
11101119 N_ ("use simple number sequence for output file names" )),
11111120 OPT_STRING (0 , "suffix" , & fmt_patch_suffix , N_ ("sfx" ),
11121121 N_ ("use <sfx> instead of '.patch'" )),
@@ -1280,28 +1289,36 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
12801289 }
12811290
12821291 if (rev .pending .nr == 1 ) {
1292+ int check_head = 0 ;
1293+
12831294 if (rev .max_count < 0 && !rev .show_root_diff ) {
12841295 /*
12851296 * This is traditional behaviour of "git format-patch
12861297 * origin" that prepares what the origin side still
12871298 * does not have.
12881299 */
1289- unsigned char sha1 [20 ];
1290- const char * ref ;
1291-
12921300 rev .pending .objects [0 ].item -> flags |= UNINTERESTING ;
12931301 add_head_to_pending (& rev );
1294- ref = resolve_ref_unsafe ("HEAD" , sha1 , 1 , NULL );
1295- if (ref && !prefixcmp (ref , "refs/heads/" ))
1296- branch_name = xstrdup (ref + strlen ("refs/heads/" ));
1297- else
1298- branch_name = xstrdup ("" ); /* no branch */
1302+ check_head = 1 ;
12991303 }
13001304 /*
13011305 * Otherwise, it is "format-patch -22 HEAD", and/or
13021306 * "format-patch --root HEAD". The user wants
13031307 * get_revision() to do the usual traversal.
13041308 */
1309+
1310+ if (!strcmp (rev .pending .objects [0 ].name , "HEAD" ))
1311+ check_head = 1 ;
1312+
1313+ if (check_head ) {
1314+ unsigned char sha1 [20 ];
1315+ const char * ref ;
1316+ ref = resolve_ref_unsafe ("HEAD" , sha1 , 1 , NULL );
1317+ if (ref && !prefixcmp (ref , "refs/heads/" ))
1318+ branch_name = xstrdup (ref + strlen ("refs/heads/" ));
1319+ else
1320+ branch_name = xstrdup ("" ); /* no branch */
1321+ }
13051322 }
13061323
13071324 /*
@@ -1310,29 +1327,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
13101327 */
13111328 rev .show_root_diff = 1 ;
13121329
1313- if (cover_letter ) {
1314- /*
1315- * NEEDSWORK:randomly pick one positive commit to show
1316- * diffstat; this is often the tip and the command
1317- * happens to do the right thing in most cases, but a
1318- * complex command like "--cover-letter a b c ^bottom"
1319- * picks "c" and shows diffstat between bottom..c
1320- * which may not match what the series represents at
1321- * all and totally broken.
1322- */
1323- int i ;
1324- for (i = 0 ; i < rev .pending .nr ; i ++ ) {
1325- struct object * o = rev .pending .objects [i ].item ;
1326- if (!(o -> flags & UNINTERESTING ))
1327- head = (struct commit * )o ;
1328- }
1329- /* There is nothing to show; it is not an error, though. */
1330- if (!head )
1331- return 0 ;
1332- if (!branch_name )
1333- branch_name = find_branch_name (& rev );
1334- }
1335-
13361330 if (ignore_if_in_upstream ) {
13371331 /* Don't say anything if head and upstream are the same. */
13381332 if (rev .pending .nr == 2 ) {
@@ -1364,11 +1358,21 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
13641358 list = xrealloc (list , nr * sizeof (list [0 ]));
13651359 list [nr - 1 ] = commit ;
13661360 }
1361+ if (nr == 0 )
1362+ /* nothing to do */
1363+ return 0 ;
13671364 total = nr ;
13681365 if (!keep_subject && auto_number && total > 1 )
13691366 numbered = 1 ;
13701367 if (numbered )
13711368 rev .total = total + start_number - 1 ;
1369+ if (cover_letter == -1 ) {
1370+ if (config_cover_letter == COVER_AUTO )
1371+ cover_letter = (total > 1 );
1372+ else
1373+ cover_letter = (config_cover_letter == COVER_ON );
1374+ }
1375+
13721376 if (in_reply_to || thread || cover_letter )
13731377 rev .ref_message_ids = xcalloc (1 , sizeof (struct string_list ));
13741378 if (in_reply_to ) {
@@ -1381,7 +1385,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
13811385 if (thread )
13821386 gen_message_id (& rev , "cover" );
13831387 make_cover_letter (& rev , use_stdout ,
1384- origin , nr , list , head , branch_name , quiet );
1388+ origin , nr , list , branch_name , quiet );
13851389 total ++ ;
13861390 start_number -- ;
13871391 }
0 commit comments