Skip to content

Commit 739453a

Browse files
committed
format-patch: use branch description in cover letter
Use the description for the branch when preparing the cover letter when available. While at it, mark a loosely written codepath that would do a random and useless thing given an unusual input (e.g. "^master HEAD HEAD^"), which we may want to fix someday. Signed-off-by: Junio C Hamano <[email protected]>
1 parent 6f9a332 commit 739453a

File tree

1 file changed

+68
-3
lines changed

1 file changed

+68
-3
lines changed

builtin/log.c

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "remote.h"
2020
#include "string-list.h"
2121
#include "parse-options.h"
22+
#include "branch.h"
2223

2324
/* Set a default date-time format for git log ("log.date" config variable) */
2425
static const char *default_date_mode = NULL;
@@ -746,10 +747,24 @@ static void print_signature(void)
746747
printf("-- \n%s\n\n", signature);
747748
}
748749

750+
static void add_branch_description(struct strbuf *buf, const char *branch_name)
751+
{
752+
struct strbuf desc = STRBUF_INIT;
753+
if (!branch_name || !*branch_name)
754+
return;
755+
read_branch_desc(&desc, branch_name);
756+
if (desc.len) {
757+
strbuf_addch(buf, '\n');
758+
strbuf_add(buf, desc.buf, desc.len);
759+
strbuf_addch(buf, '\n');
760+
}
761+
}
762+
749763
static void make_cover_letter(struct rev_info *rev, int use_stdout,
750764
int numbered, int numbered_files,
751765
struct commit *origin,
752766
int nr, struct commit **list, struct commit *head,
767+
const char *branch_name,
753768
int quiet)
754769
{
755770
const char *committer;
@@ -807,6 +822,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
807822
pp_user_info(&pp, NULL, &sb, committer, encoding);
808823
pp_title_line(&pp, &msg, &sb, encoding, need_8bit_cte);
809824
pp_remainder(&pp, &msg, &sb, 0);
825+
add_branch_description(&sb, branch_name);
810826
printf("%s\n", sb.buf);
811827

812828
strbuf_release(&sb);
@@ -1006,6 +1022,35 @@ static int cc_callback(const struct option *opt, const char *arg, int unset)
10061022
return 0;
10071023
}
10081024

1025+
static char *find_branch_name(struct rev_info *rev)
1026+
{
1027+
int i, positive = -1;
1028+
unsigned char branch_sha1[20];
1029+
struct strbuf buf = STRBUF_INIT;
1030+
const char *branch;
1031+
1032+
for (i = 0; i < rev->cmdline.nr; i++) {
1033+
if (rev->cmdline.rev[i].flags & UNINTERESTING)
1034+
continue;
1035+
if (positive < 0)
1036+
positive = i;
1037+
else
1038+
return NULL;
1039+
}
1040+
if (positive < 0)
1041+
return NULL;
1042+
strbuf_addf(&buf, "refs/heads/%s", rev->cmdline.rev[positive].name);
1043+
branch = resolve_ref(buf.buf, branch_sha1, 1, 0);
1044+
if (!branch ||
1045+
prefixcmp(branch, "refs/heads/") ||
1046+
hashcmp(rev->cmdline.rev[positive].item->sha1, branch_sha1))
1047+
branch = NULL;
1048+
strbuf_release(&buf);
1049+
if (branch)
1050+
return xstrdup(rev->cmdline.rev[positive].name);
1051+
return NULL;
1052+
}
1053+
10091054
int cmd_format_patch(int argc, const char **argv, const char *prefix)
10101055
{
10111056
struct commit *commit;
@@ -1027,6 +1072,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
10271072
struct strbuf buf = STRBUF_INIT;
10281073
int use_patch_format = 0;
10291074
int quiet = 0;
1075+
char *branch_name = NULL;
10301076
const struct option builtin_format_patch_options[] = {
10311077
{ OPTION_CALLBACK, 'n', "numbered", &numbered, NULL,
10321078
"use [PATCH n/m] even with a single patch",
@@ -1217,8 +1263,16 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
12171263
* origin" that prepares what the origin side still
12181264
* does not have.
12191265
*/
1266+
unsigned char sha1[20];
1267+
const char *ref;
1268+
12201269
rev.pending.objects[0].item->flags |= UNINTERESTING;
12211270
add_head_to_pending(&rev);
1271+
ref = resolve_ref("HEAD", sha1, 1, NULL);
1272+
if (ref && !prefixcmp(ref, "refs/heads/"))
1273+
branch_name = xstrdup(ref + strlen("refs/heads/"));
1274+
else
1275+
branch_name = xstrdup(""); /* no branch */
12221276
}
12231277
/*
12241278
* Otherwise, it is "format-patch -22 HEAD", and/or
@@ -1234,16 +1288,26 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
12341288
rev.show_root_diff = 1;
12351289

12361290
if (cover_letter) {
1237-
/* remember the range */
1291+
/*
1292+
* NEEDSWORK:randomly pick one positive commit to show
1293+
* diffstat; this is often the tip and the command
1294+
* happens to do the right thing in most cases, but a
1295+
* complex command like "--cover-letter a b c ^bottom"
1296+
* picks "c" and shows diffstat between bottom..c
1297+
* which may not match what the series represents at
1298+
* all and totally broken.
1299+
*/
12381300
int i;
12391301
for (i = 0; i < rev.pending.nr; i++) {
12401302
struct object *o = rev.pending.objects[i].item;
12411303
if (!(o->flags & UNINTERESTING))
12421304
head = (struct commit *)o;
12431305
}
1244-
/* We can't generate a cover letter without any patches */
1306+
/* There is nothing to show; it is not an error, though. */
12451307
if (!head)
12461308
return 0;
1309+
if (!branch_name)
1310+
branch_name = find_branch_name(&rev);
12471311
}
12481312

12491313
if (ignore_if_in_upstream) {
@@ -1294,7 +1358,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
12941358
if (thread)
12951359
gen_message_id(&rev, "cover");
12961360
make_cover_letter(&rev, use_stdout, numbered, numbered_files,
1297-
origin, nr, list, head, quiet);
1361+
origin, nr, list, head, branch_name, quiet);
12981362
total++;
12991363
start_number--;
13001364
}
@@ -1366,6 +1430,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
13661430
fclose(stdout);
13671431
}
13681432
free(list);
1433+
free(branch_name);
13691434
string_list_clear(&extra_to, 0);
13701435
string_list_clear(&extra_cc, 0);
13711436
string_list_clear(&extra_hdr, 0);

0 commit comments

Comments
 (0)