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 <gitster@pobox.com>

Junio C Hamano committed Sep 21, 2011 at 20:32 UTC 739453a3fb74ade725243ac972f02ba1aedabdf6
1 file changed +68 -3
builtin/log.c
+68 -3
@@ -19,6 +19,7 @@
19 #include "remote.h"
20 #include "string-list.h"
21 #include "parse-options.h"
22 +#include "branch.h"
23
24 /* Set a default date-time format for git log ("log.date" config variable) */
25 static const char *default_date_mode = NULL;
@@ -746,10 +747,24 @@ static void print_signature(void)
747 printf("-- \n%s\n\n", signature);
748 }
749
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 +
763 static void make_cover_letter(struct rev_info *rev, int use_stdout,
764 int numbered, int numbered_files,
765 struct commit *origin,
766 int nr, struct commit **list, struct commit *head,
767 + const char *branch_name,
768 int quiet)
769 {
770 const char *committer;
@@ -807,6 +822,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
822 pp_user_info(&pp, NULL, &sb, committer, encoding);
823 pp_title_line(&pp, &msg, &sb, encoding, need_8bit_cte);
824 pp_remainder(&pp, &msg, &sb, 0);
825 + add_branch_description(&sb, branch_name);
826 printf("%s\n", sb.buf);
827
828 strbuf_release(&sb);
@@ -1006,6 +1022,35 @@ static int cc_callback(const struct option *opt, const char *arg, int unset)
1022 return 0;
1023 }
1024
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 +
1054 int cmd_format_patch(int argc, const char **argv, const char *prefix)
1055 {
1056 struct commit *commit;
@@ -1027,6 +1072,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
1072 struct strbuf buf = STRBUF_INIT;
1073 int use_patch_format = 0;
1074 int quiet = 0;
1075 + char *branch_name = NULL;
1076 const struct option builtin_format_patch_options[] = {
1077 { OPTION_CALLBACK, 'n', "numbered", &numbered, NULL,
1078 "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)
1263 * origin" that prepares what the origin side still
1264 * does not have.
1265 */
1266 + unsigned char sha1[20];
1267 + const char *ref;
1268 +
1269 rev.pending.objects[0].item->flags |= UNINTERESTING;
1270 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 */
1276 }
1277 /*
1278 * 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)
1288 rev.show_root_diff = 1;
1289
1290 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 + */
1300 int i;
1301 for (i = 0; i < rev.pending.nr; i++) {
1302 struct object *o = rev.pending.objects[i].item;
1303 if (!(o->flags & UNINTERESTING))
1304 head = (struct commit *)o;
1305 }
1244 - /* We can't generate a cover letter without any patches */
1306 + /* There is nothing to show; it is not an error, though. */
1307 if (!head)
1308 return 0;
1309 + if (!branch_name)
1310 + branch_name = find_branch_name(&rev);
1311 }
1312
1313 if (ignore_if_in_upstream) {
@@ -1294,7 +1358,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
1358 if (thread)
1359 gen_message_id(&rev, "cover");
1360 make_cover_letter(&rev, use_stdout, numbered, numbered_files,
1297 - origin, nr, list, head, quiet);
1361 + origin, nr, list, head, branch_name, quiet);
1362 total++;
1363 start_number--;
1364 }
@@ -1366,6 +1430,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
1430 fclose(stdout);
1431 }
1432 free(list);
1433 + free(branch_name);
1434 string_list_clear(&extra_to, 0);
1435 string_list_clear(&extra_cc, 0);
1436 string_list_clear(&extra_hdr, 0);