format-patch: allow --range-diff to apply to a lone-patch

When submitting a revised version of a patch or series, it can be helpful (to reviewers) to include a summary of changes since the previous attempt in the form of a range-diff, typically in the cover letter. However, it is occasionally useful, despite making for a noisy read, to insert a range-diff into the commentary section of the lone patch of a 1-patch series. Therefore, extend "git format-patch --range-diff=<refspec>" to insert a range-diff into the commentary section of a lone patch rather than requiring a cover letter. Implementation note: Generating a range-diff for insertion into the commentary section of a patch which itself is currently being generated requires invoking the diffing machinery recursively. However, the machinery does not (presently) support this since it uses global state. Consequently, we need to take care to stash away the state of the in-progress operation while generating the range-diff, and restore it after. Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Eric Sunshine committed Jul 22, 2018 at 05:57 UTC 40ce41604daf200cdc85abded0133d40faafc2f8
3 files changed +22 -5
Documentation/git-format-patch.txt
+2 -1
@@ -241,7 +241,8 @@ feeding the result to `git send-email`.
241
242 --range-diff=<previous>::
243 As a reviewer aid, insert a range-diff (see linkgit:git-range-diff[1])
244 - into the cover letter showing the differences between the previous
244 + into the cover letter, or as commentary of the lone patch of a
245 + 1-patch series, showing the differences between the previous
246 version of the patch series and the series currently being formatted.
247 `previous` can be a single revision naming the tip of the previous
248 series if it shares a common base with the series being formatted (for
builtin/log.c
+5 -4
@@ -1576,7 +1576,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
1576 N_("show changes against <rev> in cover letter or single patch"),
1577 parse_opt_object_name),
1578 OPT_STRING(0, "range-diff", &rdiff_prev, N_("refspec"),
1579 - N_("show changes against <refspec> in cover letter")),
1579 + N_("show changes against <refspec> in cover letter or single patch")),
1580 OPT_INTEGER(0, "creation-factor", &creation_factor,
1581 N_("percentage by which creation is weighted")),
1582 OPT_END()
@@ -1817,8 +1817,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
1817 die(_("--creation-factor requires --range-diff"));
1818
1819 if (rdiff_prev) {
1820 - if (!cover_letter)
1821 - die(_("--range-diff requires --cover-letter"));
1820 + if (!cover_letter && total != 1)
1821 + die(_("--range-diff requires --cover-letter or single patch"));
1822
1823 infer_range_diff_ranges(&rdiff1, &rdiff2, rdiff_prev,
1824 origin, list[0]);
@@ -1867,8 +1867,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
1867 print_signature(rev.diffopt.file);
1868 total++;
1869 start_number--;
1870 - /* interdiff in cover-letter; omit from patches */
1870 + /* interdiff/range-diff in cover-letter; omit from patches */
1871 rev.idiff_oid1 = NULL;
1872 + rev.rdiff1 = NULL;
1873 }
1874 rev.add_signoff = do_signoff;
1875
log-tree.c
+15
@@ -16,6 +16,7 @@
16 #include "line-log.h"
17 #include "help.h"
18 #include "interdiff.h"
19 +#include "range-diff.h"
20
21 static struct decoration name_decoration = { "object names" };
22 static int decoration_loaded;
@@ -751,6 +752,20 @@ void show_log(struct rev_info *opt)
752
753 memcpy(&diff_queued_diff, &dq, sizeof(diff_queued_diff));
754 }
755 +
756 + if (cmit_fmt_is_mail(ctx.fmt) && opt->rdiff1) {
757 + struct diff_queue_struct dq;
758 +
759 + memcpy(&dq, &diff_queued_diff, sizeof(diff_queued_diff));
760 + DIFF_QUEUE_CLEAR(&diff_queued_diff);
761 +
762 + next_commentary_block(opt, NULL);
763 + fprintf_ln(opt->diffopt.file, "%s", opt->rdiff_title);
764 + show_range_diff(opt->rdiff1, opt->rdiff2,
765 + opt->creation_factor, 1, &opt->diffopt);
766 +
767 + memcpy(&diff_queued_diff, &dq, sizeof(diff_queued_diff));
768 + }
769 }
770
771 int log_tree_diff_flush(struct rev_info *opt)