@matheusbsbs / matheus-bagliano / commits / 2bda2cf4f9
Fork 0

Improve collection of information for format-patch --cover-letter

Use the "boundary" feature to find the origin (or find that there are multiple origins), and use the actual list of commits to pass to shortlog. This makes all cover letter include shortlogs, and all cover letters for series with a single boundary commit include diffstats (if there are multiple boundary commits it's unclear what would be meaningful as a diffstat). Note that the single boundary test is empirical, not theoretical; even a -2 limiting condition will give a diffstat if there's only one boundary commit in this particular case. Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>

Daniel Barkalow committed Feb 25, 2008 at 18:24 UTC 2bda2cf4f966ae50d08a32a3839f930c1daac907
1 file changed +28 -24
builtin-log.c
+28 -24
@@ -15,6 +15,7 @@
15 #include "patch-ids.h"
16 #include "refs.h"
17 #include "run-command.h"
18 +#include "shortlog.h"
19
20 static int default_show_root = 1;
21 static const char *fmt_patch_subject_prefix = "PATCH";
@@ -621,9 +622,10 @@ static void gen_message_id(struct rev_info *info, char *base)
622 info->message_id = strbuf_detach(&buf, NULL);
623 }
624
624 -static void make_cover_letter(struct rev_info *rev,
625 - int use_stdout, int numbered, int numbered_files,
626 - struct commit *origin, struct commit *head)
625 +static void make_cover_letter(struct rev_info *rev, int use_stdout,
626 + int numbered, int numbered_files,
627 + struct commit *origin,
628 + int nr, struct commit **list, struct commit *head)
629 {
630 const char *committer;
631 const char *origin_sha1, *head_sha1;
@@ -632,7 +634,9 @@ static void make_cover_letter(struct rev_info *rev,
634 const char *body = "*** SUBJECT HERE ***\n\n*** BLURB HERE ***\n";
635 const char *msg;
636 const char *extra_headers = rev->extra_headers;
637 + struct shortlog log;
638 struct strbuf sb;
639 + int i;
640 const char *encoding = "utf-8";
641
642 if (rev->commit_format != CMIT_FMT_EMAIL)
@@ -642,7 +646,6 @@ static void make_cover_letter(struct rev_info *rev,
646 NULL : "cover-letter", 0, rev->total))
647 return;
648
645 - origin_sha1 = sha1_to_hex(origin ? origin->object.sha1 : null_sha1);
649 head_sha1 = sha1_to_hex(head->object.sha1);
650
651 log_write_email_headers(rev, head_sha1, &subject_start, &extra_headers);
@@ -660,21 +663,19 @@ static void make_cover_letter(struct rev_info *rev,
663
664 strbuf_release(&sb);
665
666 + shortlog_init(&log);
667 + for (i = 0; i < nr; i++)
668 + shortlog_add_commit(&log, list[i]);
669 +
670 + shortlog_output(&log);
671 +
672 /*
664 - * We can only do diffstat with a unique reference point, and
665 - * log is a bit tricky, so just skip it.
673 + * We can only do diffstat with a unique reference point
674 */
675 if (!origin)
676 return;
677
670 - argv[0] = "shortlog";
671 - argv[1] = head_sha1;
672 - argv[2] = "--not";
673 - argv[3] = origin_sha1;
674 - argv[4] = "--";
675 - argv[5] = NULL;
676 - fflush(stdout);
677 - run_command_v_opt(argv, RUN_GIT_CMD);
678 + origin_sha1 = sha1_to_hex(origin->object.sha1);
679
680 argv[0] = "diff";
681 argv[1] = "--stat";
@@ -727,6 +728,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
728 int ignore_if_in_upstream = 0;
729 int thread = 0;
730 int cover_letter = 0;
731 + int boundary_count = 0;
732 struct commit *origin = NULL, *head = NULL;
733 const char *in_reply_to = NULL;
734 struct patch_ids ids;
@@ -917,19 +919,12 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
919 }
920 if (cover_letter) {
921 /* remember the range */
920 - int negative_count = 0;
922 int i;
923 for (i = 0; i < rev.pending.nr; i++) {
924 struct object *o = rev.pending.objects[i].item;
924 - if (o->flags & UNINTERESTING) {
925 - origin = (struct commit *)o;
926 - negative_count++;
927 - } else
925 + if (!(o->flags & UNINTERESTING))
926 head = (struct commit *)o;
927 }
930 - /* Multiple origins don't work for diffstat. */
931 - if (negative_count > 1)
932 - origin = NULL;
928 /* We can't generate a cover letter without any patches */
929 if (!head)
930 return 0;
@@ -941,8 +936,17 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
936 if (!use_stdout)
937 realstdout = xfdopen(xdup(1), "w");
938
944 - prepare_revision_walk(&rev);
939 + if (prepare_revision_walk(&rev))
940 + die("revision walk setup failed");
941 + rev.boundary = 1;
942 while ((commit = get_revision(&rev)) != NULL) {
943 + if (commit->object.flags & BOUNDARY) {
944 + fprintf(stderr, "Boundary %s\n", sha1_to_hex(commit->object.sha1));
945 + boundary_count++;
946 + origin = (boundary_count == 1) ? commit : NULL;
947 + continue;
948 + }
949 +
950 /* ignore merges */
951 if (commit->parents && commit->parents->next)
952 continue;
@@ -966,7 +970,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
970 if (thread)
971 gen_message_id(&rev, "cover");
972 make_cover_letter(&rev, use_stdout, numbered, numbered_files,
969 - origin, head);
973 + origin, nr, list, head);
974 total++;
975 start_number--;
976 }