Skip to content

Commit 2bda2cf

Browse files
iabervongitster
authored andcommitted
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 <[email protected]>
1 parent 552bcac commit 2bda2cf

File tree

1 file changed

+28
-24
lines changed

1 file changed

+28
-24
lines changed

builtin-log.c

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "patch-ids.h"
1616
#include "refs.h"
1717
#include "run-command.h"
18+
#include "shortlog.h"
1819

1920
static int default_show_root = 1;
2021
static const char *fmt_patch_subject_prefix = "PATCH";
@@ -621,9 +622,10 @@ static void gen_message_id(struct rev_info *info, char *base)
621622
info->message_id = strbuf_detach(&buf, NULL);
622623
}
623624

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)
627629
{
628630
const char *committer;
629631
const char *origin_sha1, *head_sha1;
@@ -632,7 +634,9 @@ static void make_cover_letter(struct rev_info *rev,
632634
const char *body = "*** SUBJECT HERE ***\n\n*** BLURB HERE ***\n";
633635
const char *msg;
634636
const char *extra_headers = rev->extra_headers;
637+
struct shortlog log;
635638
struct strbuf sb;
639+
int i;
636640
const char *encoding = "utf-8";
637641

638642
if (rev->commit_format != CMIT_FMT_EMAIL)
@@ -642,7 +646,6 @@ static void make_cover_letter(struct rev_info *rev,
642646
NULL : "cover-letter", 0, rev->total))
643647
return;
644648

645-
origin_sha1 = sha1_to_hex(origin ? origin->object.sha1 : null_sha1);
646649
head_sha1 = sha1_to_hex(head->object.sha1);
647650

648651
log_write_email_headers(rev, head_sha1, &subject_start, &extra_headers);
@@ -660,21 +663,19 @@ static void make_cover_letter(struct rev_info *rev,
660663

661664
strbuf_release(&sb);
662665

666+
shortlog_init(&log);
667+
for (i = 0; i < nr; i++)
668+
shortlog_add_commit(&log, list[i]);
669+
670+
shortlog_output(&log);
671+
663672
/*
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
666674
*/
667675
if (!origin)
668676
return;
669677

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);
678679

679680
argv[0] = "diff";
680681
argv[1] = "--stat";
@@ -727,6 +728,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
727728
int ignore_if_in_upstream = 0;
728729
int thread = 0;
729730
int cover_letter = 0;
731+
int boundary_count = 0;
730732
struct commit *origin = NULL, *head = NULL;
731733
const char *in_reply_to = NULL;
732734
struct patch_ids ids;
@@ -917,19 +919,12 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
917919
}
918920
if (cover_letter) {
919921
/* remember the range */
920-
int negative_count = 0;
921922
int i;
922923
for (i = 0; i < rev.pending.nr; i++) {
923924
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))
928926
head = (struct commit *)o;
929927
}
930-
/* Multiple origins don't work for diffstat. */
931-
if (negative_count > 1)
932-
origin = NULL;
933928
/* We can't generate a cover letter without any patches */
934929
if (!head)
935930
return 0;
@@ -941,8 +936,17 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
941936
if (!use_stdout)
942937
realstdout = xfdopen(xdup(1), "w");
943938

944-
prepare_revision_walk(&rev);
939+
if (prepare_revision_walk(&rev))
940+
die("revision walk setup failed");
941+
rev.boundary = 1;
945942
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+
946950
/* ignore merges */
947951
if (commit->parents && commit->parents->next)
948952
continue;
@@ -966,7 +970,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
966970
if (thread)
967971
gen_message_id(&rev, "cover");
968972
make_cover_letter(&rev, use_stdout, numbered, numbered_files,
969-
origin, head);
973+
origin, nr, list, head);
970974
total++;
971975
start_number--;
972976
}

0 commit comments

Comments
 (0)