From 87f1b2d45ca7987cc6cc1a74eb66a77fa11fab94 Mon Sep 17 00:00:00 2001 From: Eric Sunshine Date: Sun, 22 Jul 2018 05:57:10 -0400 Subject: range-diff: respect diff_option.file rather than assuming 'stdout' The actual diffs output by range-diff respect diff_option.file, which range-diff passes down the call-chain, thus are destination-agnostic. However, output_pair_header() is hard-coded to emit to 'stdout'. Fix this by making output_pair_header() respect diff_option.file, as well. Signed-off-by: Eric Sunshine Signed-off-by: Junio C Hamano diff --git a/range-diff.c b/range-diff.c index b6b9aba..defe31f 100644 --- a/range-diff.c +++ b/range-diff.c @@ -323,7 +323,7 @@ static void output_pair_header(struct diff_options *diffopt, } strbuf_addf(buf, "%s\n", color_reset); - fwrite(buf->buf, buf->len, 1, stdout); + fwrite(buf->buf, buf->len, 1, diffopt->file); } static struct userdiff_driver no_func_name = { -- cgit v0.10.2-6-g49f6 From 25668659bfd74a71de6dd27eac437a17ad72a315 Mon Sep 17 00:00:00 2001 From: Eric Sunshine Date: Sun, 22 Jul 2018 05:57:11 -0400 Subject: range-diff: publish default creation factor The range-diff back-end allows its heuristic to be tweaked via the "creation factor". git-range-diff, the only client of the back-end, defaults the factor to 60% (hard-coded in builtin/range-diff.c), but allows the user to override it with the --creation-factor option. Publish the default range factor to allow new callers of the range-diff back-end to default to the same value without duplicating the hard-coded constant, and to avoid worrying about various callers becoming out-of-sync if the default ever needs to change. Signed-off-by: Eric Sunshine Signed-off-by: Junio C Hamano diff --git a/builtin/range-diff.c b/builtin/range-diff.c index f52d45d..006e766 100644 --- a/builtin/range-diff.c +++ b/builtin/range-diff.c @@ -18,7 +18,7 @@ static struct strbuf *output_prefix_cb(struct diff_options *opt, void *data) int cmd_range_diff(int argc, const char **argv, const char *prefix) { - int creation_factor = 60; + int creation_factor = RANGE_DIFF_CREATION_FACTOR_DEFAULT; struct diff_options diffopt = { NULL }; int simple_color = -1; struct option options[] = { diff --git a/range-diff.h b/range-diff.h index 2407d46..f26de5d 100644 --- a/range-diff.h +++ b/range-diff.h @@ -3,6 +3,8 @@ #include "diff.h" +#define RANGE_DIFF_CREATION_FACTOR_DEFAULT 60 + int show_range_diff(const char *range1, const char *range2, int creation_factor, struct diff_options *diffopt); -- cgit v0.10.2-6-g49f6 From 73a834e9e27906a76940f1ced5c132bce205d3f8 Mon Sep 17 00:00:00 2001 From: Eric Sunshine Date: Sun, 22 Jul 2018 05:57:12 -0400 Subject: range-diff: relieve callers of low-level configuration burden There are a number of very low-level configuration details which need to be managed precisely to generate a proper range-diff. In particular, 'diff_options' output format, header suppression, indentation, and dual-color mode must all be set appropriately to ensure proper behavior. Handle these details locally in the libified range-diff back-end rather than forcing each caller to have specialized knowledge of these implementation details, and to avoid duplication as new callers are added. While at it, localize these tweaks to be active only while generating the range-diff, so they don't clobber the caller-provided 'diff_options', which might be used beyond range-diff generation. Signed-off-by: Eric Sunshine Signed-off-by: Junio C Hamano diff --git a/builtin/range-diff.c b/builtin/range-diff.c index 006e766..cc06e86 100644 --- a/builtin/range-diff.c +++ b/builtin/range-diff.c @@ -11,11 +11,6 @@ N_("git range-diff [] "), NULL }; -static struct strbuf *output_prefix_cb(struct diff_options *opt, void *data) -{ - return data; -} - int cmd_range_diff(int argc, const char **argv, const char *prefix) { int creation_factor = RANGE_DIFF_CREATION_FACTOR_DEFAULT; @@ -29,17 +24,11 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix) OPT_END() }; int i, j, res = 0; - struct strbuf four_spaces = STRBUF_INIT; struct strbuf range1 = STRBUF_INIT, range2 = STRBUF_INIT; git_config(git_diff_ui_config, NULL); diff_setup(&diffopt); - diffopt.output_format = DIFF_FORMAT_PATCH; - diffopt.flags.suppress_diff_headers = 1; - diffopt.output_prefix = output_prefix_cb; - strbuf_addstr(&four_spaces, " "); - diffopt.output_prefix_data = &four_spaces; argc = parse_options(argc, argv, NULL, options, builtin_range_diff_usage, PARSE_OPT_KEEP_UNKNOWN | @@ -63,12 +52,9 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix) options + ARRAY_SIZE(options) - 1, /* OPT_END */ builtin_range_diff_usage, 0); - if (simple_color < 1) { - if (!simple_color) - /* force color when --dual-color was used */ - diffopt.use_color = 1; - diffopt.flags.dual_color_diffed_diffs = 1; - } + /* force color when --dual-color was used */ + if (!simple_color) + diffopt.use_color = 1; if (argc == 2) { if (!strstr(argv[0], "..")) @@ -106,11 +92,10 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix) } res = show_range_diff(range1.buf, range2.buf, creation_factor, - &diffopt); + simple_color < 1, &diffopt); strbuf_release(&range1); strbuf_release(&range2); - strbuf_release(&four_spaces); return res; } diff --git a/range-diff.c b/range-diff.c index defe31f..3dd2edd 100644 --- a/range-diff.c +++ b/range-diff.c @@ -409,8 +409,14 @@ static void output(struct string_list *a, struct string_list *b, strbuf_release(&dashes); } +static struct strbuf *output_prefix_cb(struct diff_options *opt, void *data) +{ + return data; +} + int show_range_diff(const char *range1, const char *range2, - int creation_factor, struct diff_options *diffopt) + int creation_factor, int dual_color, + struct diff_options *diffopt) { int res = 0; @@ -423,9 +429,23 @@ int show_range_diff(const char *range1, const char *range2, res = error(_("could not parse log for '%s'"), range2); if (!res) { + struct diff_options opts; + struct strbuf indent = STRBUF_INIT; + + memcpy(&opts, diffopt, sizeof(opts)); + opts.output_format = DIFF_FORMAT_PATCH; + opts.flags.suppress_diff_headers = 1; + opts.flags.dual_color_diffed_diffs = dual_color; + opts.output_prefix = output_prefix_cb; + strbuf_addstr(&indent, " "); + opts.output_prefix_data = &indent; + diff_setup_done(&opts); + find_exact_matches(&branch1, &branch2); get_correspondences(&branch1, &branch2, creation_factor); - output(&branch1, &branch2, diffopt); + output(&branch1, &branch2, &opts); + + strbuf_release(&indent); } string_list_clear(&branch1, 1); diff --git a/range-diff.h b/range-diff.h index f26de5d..190593f 100644 --- a/range-diff.h +++ b/range-diff.h @@ -6,6 +6,7 @@ #define RANGE_DIFF_CREATION_FACTOR_DEFAULT 60 int show_range_diff(const char *range1, const char *range2, - int creation_factor, struct diff_options *diffopt); + int creation_factor, int dual_color, + struct diff_options *diffopt); #endif -- cgit v0.10.2-6-g49f6 From 31e2617a5f8fe1c114e72f058d1c035bbf77cffe Mon Sep 17 00:00:00 2001 From: Eric Sunshine Date: Sun, 22 Jul 2018 05:57:13 -0400 Subject: format-patch: add --range-diff option to embed diff in cover letter When submitting a revised version of a patch series, it can be helpful (to reviewers) to include a summary of changes since the previous attempt in the form of a range-diff, however, doing so involves manually copy/pasting the diff into the cover letter. Add a --range-diff option to automate this process. The argument to --range-diff specifies the tip of the previous attempt against which to generate the range-diff. For example: git format-patch --cover-letter --range-diff=v1 -3 v2 (At this stage, the previous attempt and the patch series being formatted must share a common base, however, a subsequent enhancement will make it possible to specify an explicit revision range for the previous attempt.) Signed-off-by: Eric Sunshine Signed-off-by: Junio C Hamano diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index f8a0617..e7f404b 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -24,6 +24,7 @@ SYNOPSIS [--to=] [--cc=] [--[no-]cover-letter] [--quiet] [--notes[=]] [--interdiff=] + [--range-diff=] [--progress] [] [ | ] @@ -238,6 +239,15 @@ feeding the result to `git send-email`. the series being formatted (for example `git format-patch --cover-letter --interdiff=feature/v1 -3 feature/v2`). +--range-diff=:: + As a reviewer aid, insert a range-diff (see linkgit:git-range-diff[1]) + into the cover letter showing the differences between the previous + version of the patch series and the series currently being formatted. + `previous` is a single revision naming the tip of the previous + series which shares a common base with the series being formatted (for + example `git format-patch --cover-letter --range-diff=feature/v1 -3 + feature/v2`). + --notes[=]:: Append the notes (see linkgit:git-notes[1]) for the commit after the three-dash line. diff --git a/builtin/log.c b/builtin/log.c index fcc2f4d..4b65673 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -32,6 +32,7 @@ #include "commit-slab.h" #include "repository.h" #include "interdiff.h" +#include "range-diff.h" #define MAIL_DEFAULT_WRAP 72 @@ -1089,6 +1090,12 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, fprintf_ln(rev->diffopt.file, "%s", rev->idiff_title); show_interdiff(rev, 0); } + + if (rev->rdiff1) { + fprintf_ln(rev->diffopt.file, "%s", _("Range-diff:")); + show_range_diff(rev->rdiff1, rev->rdiff2, + rev->creation_factor, 1, &rev->diffopt); + } } static const char *clean_message_id(const char *msg_id) @@ -1438,6 +1445,17 @@ static const char *diff_title(struct strbuf *sb, int reroll_count, return sb->buf; } +static void infer_range_diff_ranges(struct strbuf *r1, + struct strbuf *r2, + const char *prev, + struct commit *head) +{ + const char *head_oid = oid_to_hex(&head->object.oid); + + strbuf_addf(r1, "%s..%s", head_oid, prev); + strbuf_addf(r2, "%s..%s", prev, head_oid); +} + int cmd_format_patch(int argc, const char **argv, const char *prefix) { struct commit *commit; @@ -1467,6 +1485,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) struct progress *progress = NULL; struct oid_array idiff_prev = OID_ARRAY_INIT; struct strbuf idiff_title = STRBUF_INIT; + const char *rdiff_prev = NULL; + struct strbuf rdiff1 = STRBUF_INIT; + struct strbuf rdiff2 = STRBUF_INIT; const struct option builtin_format_patch_options[] = { { OPTION_CALLBACK, 'n', "numbered", &numbered, NULL, @@ -1543,6 +1564,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) OPT_CALLBACK(0, "interdiff", &idiff_prev, N_("rev"), N_("show changes against in cover letter or single patch"), parse_opt_object_name), + OPT_STRING(0, "range-diff", &rdiff_prev, N_("refspec"), + N_("show changes against in cover letter")), OPT_END() }; @@ -1775,6 +1798,16 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) _("Interdiff against v%d:")); } + if (rdiff_prev) { + if (!cover_letter) + die(_("--range-diff requires --cover-letter")); + + infer_range_diff_ranges(&rdiff1, &rdiff2, rdiff_prev, list[0]); + rev.rdiff1 = rdiff1.buf; + rev.rdiff2 = rdiff2.buf; + rev.creation_factor = RANGE_DIFF_CREATION_FACTOR_DEFAULT; + } + if (!signature) { ; /* --no-signature inhibits all signatures */ } else if (signature && signature != git_version_string) { @@ -1898,6 +1931,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) done: oid_array_clear(&idiff_prev); strbuf_release(&idiff_title); + strbuf_release(&rdiff1); + strbuf_release(&rdiff2); return 0; } diff --git a/revision.h b/revision.h index b30ea3a..01fd7e2 100644 --- a/revision.h +++ b/revision.h @@ -218,6 +218,11 @@ struct rev_info { const struct object_id *idiff_oid2; const char *idiff_title; + /* range-diff */ + const char *rdiff1; + const char *rdiff2; + int creation_factor; + /* commit counts */ int count_left; int count_right; diff --git a/t/t3206-range-diff.sh b/t/t3206-range-diff.sh index 2237c7f..dd854b6 100755 --- a/t/t3206-range-diff.sh +++ b/t/t3206-range-diff.sh @@ -142,4 +142,16 @@ test_expect_success 'changed message' ' test_cmp expected actual ' +for prev in topic +do + test_expect_success "format-patch --range-diff=$prev" ' + git format-patch --stdout --cover-letter --range-diff=$prev \ + master..unmodified >actual && + grep "= 1: .* s/5/A" actual && + grep "= 2: .* s/4/A" actual && + grep "= 3: .* s/11/B" actual && + grep "= 4: .* s/12/B" actual + ' +done + test_done -- cgit v0.10.2-6-g49f6 From 2e6fd71a52f5bde1c4036b8b0c586ae446f620f8 Mon Sep 17 00:00:00 2001 From: Eric Sunshine Date: Sun, 22 Jul 2018 05:57:14 -0400 Subject: format-patch: extend --range-diff to accept revision range When submitting a revised a patch series, the --range-diff option embeds a range-diff in the cover letter showing changes since the previous version of the patch series. The argument to --range-diff is a simple revision naming the tip of the previous series, which works fine if the previous and current versions of the patch series share a common base. However, it fails if the revision ranges of the old and new versions of the series are disjoint. To address this shortcoming, extend --range-diff to also accept an explicit revision range for the previous series. For example: git format-patch --cover-letter --range-diff=v1~3..v1 -3 v2 Signed-off-by: Eric Sunshine Signed-off-by: Junio C Hamano diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index e7f404b..425145f 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -243,10 +243,12 @@ feeding the result to `git send-email`. As a reviewer aid, insert a range-diff (see linkgit:git-range-diff[1]) into the cover letter showing the differences between the previous version of the patch series and the series currently being formatted. - `previous` is a single revision naming the tip of the previous - series which shares a common base with the series being formatted (for + `previous` can be a single revision naming the tip of the previous + series if it shares a common base with the series being formatted (for example `git format-patch --cover-letter --range-diff=feature/v1 -3 - feature/v2`). + feature/v2`), or a revision range if the two versions of the series are + disjoint (for example `git format-patch --cover-letter + --range-diff=feature/v1~3..feature/v1 -3 feature/v2`). --notes[=]:: Append the notes (see linkgit:git-notes[1]) for the commit diff --git a/builtin/log.c b/builtin/log.c index 4b65673..fa54090 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1448,12 +1448,21 @@ static const char *diff_title(struct strbuf *sb, int reroll_count, static void infer_range_diff_ranges(struct strbuf *r1, struct strbuf *r2, const char *prev, + struct commit *origin, struct commit *head) { const char *head_oid = oid_to_hex(&head->object.oid); - strbuf_addf(r1, "%s..%s", head_oid, prev); - strbuf_addf(r2, "%s..%s", prev, head_oid); + if (!strstr(prev, "..")) { + strbuf_addf(r1, "%s..%s", head_oid, prev); + strbuf_addf(r2, "%s..%s", prev, head_oid); + } else if (!origin) { + die(_("failed to infer range-diff ranges")); + } else { + strbuf_addstr(r1, prev); + strbuf_addf(r2, "%s..%s", + oid_to_hex(&origin->object.oid), head_oid); + } } int cmd_format_patch(int argc, const char **argv, const char *prefix) @@ -1802,7 +1811,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (!cover_letter) die(_("--range-diff requires --cover-letter")); - infer_range_diff_ranges(&rdiff1, &rdiff2, rdiff_prev, list[0]); + infer_range_diff_ranges(&rdiff1, &rdiff2, rdiff_prev, + origin, list[0]); rev.rdiff1 = rdiff1.buf; rev.rdiff2 = rdiff2.buf; rev.creation_factor = RANGE_DIFF_CREATION_FACTOR_DEFAULT; diff --git a/t/t3206-range-diff.sh b/t/t3206-range-diff.sh index dd854b6..3d7a2d8 100755 --- a/t/t3206-range-diff.sh +++ b/t/t3206-range-diff.sh @@ -142,7 +142,7 @@ test_expect_success 'changed message' ' test_cmp expected actual ' -for prev in topic +for prev in topic master..topic do test_expect_success "format-patch --range-diff=$prev" ' git format-patch --stdout --cover-letter --range-diff=$prev \ -- cgit v0.10.2-6-g49f6 From 4ee99689410cf7275f21833779da89626eb6edd6 Mon Sep 17 00:00:00 2001 From: Eric Sunshine Date: Sun, 22 Jul 2018 05:57:15 -0400 Subject: format-patch: teach --range-diff to respect -v/--reroll-count The --range-diff option announces the embedded range-diff generically as "Range-diff:", however, we can do better when --reroll-count is specified by emitting "Range-diff against v{n}:" instead. Signed-off-by: Eric Sunshine Signed-off-by: Junio C Hamano diff --git a/builtin/log.c b/builtin/log.c index fa54090..0dc17fe 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1092,7 +1092,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, } if (rev->rdiff1) { - fprintf_ln(rev->diffopt.file, "%s", _("Range-diff:")); + fprintf_ln(rev->diffopt.file, "%s", rev->rdiff_title); show_range_diff(rev->rdiff1, rev->rdiff2, rev->creation_factor, 1, &rev->diffopt); } @@ -1497,6 +1497,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) const char *rdiff_prev = NULL; struct strbuf rdiff1 = STRBUF_INIT; struct strbuf rdiff2 = STRBUF_INIT; + struct strbuf rdiff_title = STRBUF_INIT; const struct option builtin_format_patch_options[] = { { OPTION_CALLBACK, 'n', "numbered", &numbered, NULL, @@ -1816,6 +1817,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.rdiff1 = rdiff1.buf; rev.rdiff2 = rdiff2.buf; rev.creation_factor = RANGE_DIFF_CREATION_FACTOR_DEFAULT; + rev.rdiff_title = diff_title(&rdiff_title, reroll_count, + _("Range-diff:"), + _("Range-diff against v%d:")); } if (!signature) { @@ -1943,6 +1947,7 @@ done: strbuf_release(&idiff_title); strbuf_release(&rdiff1); strbuf_release(&rdiff2); + strbuf_release(&rdiff_title); return 0; } diff --git a/revision.h b/revision.h index 01fd7e2..7106b89 100644 --- a/revision.h +++ b/revision.h @@ -222,6 +222,7 @@ struct rev_info { const char *rdiff1; const char *rdiff2; int creation_factor; + const char *rdiff_title; /* commit counts */ int count_left; -- cgit v0.10.2-6-g49f6 From 8631bf1cdd7296684deebab2708761bfc8085fc2 Mon Sep 17 00:00:00 2001 From: Eric Sunshine Date: Sun, 22 Jul 2018 05:57:16 -0400 Subject: format-patch: add --creation-factor tweak for --range-diff When generating a range-diff, matching up commits between two version of a patch series involves heuristics, thus may give unexpected results. git-range-diff allows tweaking the heuristic via --creation-factor. Follow suit by accepting --creation-factor in combination with --range-diff when generating a range-diff for a cover-letter. Signed-off-by: Eric Sunshine Signed-off-by: Junio C Hamano diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 425145f..9b2e172 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -24,7 +24,7 @@ SYNOPSIS [--to=] [--cc=] [--[no-]cover-letter] [--quiet] [--notes[=]] [--interdiff=] - [--range-diff=] + [--range-diff= [--creation-factor=]] [--progress] [] [ | ] @@ -250,6 +250,12 @@ feeding the result to `git send-email`. disjoint (for example `git format-patch --cover-letter --range-diff=feature/v1~3..feature/v1 -3 feature/v2`). +--creation-factor=:: + Used with `--range-diff`, tweak the heuristic which matches up commits + between the previous and current series of patches by adjusting the + creation/deletion cost fudge factor. See linkgit:git-range-diff[1]) + for details. + --notes[=]:: Append the notes (see linkgit:git-notes[1]) for the commit after the three-dash line. diff --git a/builtin/log.c b/builtin/log.c index 0dc17fe..05965a57 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1498,6 +1498,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) struct strbuf rdiff1 = STRBUF_INIT; struct strbuf rdiff2 = STRBUF_INIT; struct strbuf rdiff_title = STRBUF_INIT; + int creation_factor = -1; const struct option builtin_format_patch_options[] = { { OPTION_CALLBACK, 'n', "numbered", &numbered, NULL, @@ -1576,6 +1577,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) parse_opt_object_name), OPT_STRING(0, "range-diff", &rdiff_prev, N_("refspec"), N_("show changes against in cover letter")), + OPT_INTEGER(0, "creation-factor", &creation_factor, + N_("percentage by which creation is weighted")), OPT_END() }; @@ -1808,6 +1811,11 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) _("Interdiff against v%d:")); } + if (creation_factor < 0) + creation_factor = RANGE_DIFF_CREATION_FACTOR_DEFAULT; + else if (!rdiff_prev) + die(_("--creation-factor requires --range-diff")); + if (rdiff_prev) { if (!cover_letter) die(_("--range-diff requires --cover-letter")); @@ -1816,7 +1824,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) origin, list[0]); rev.rdiff1 = rdiff1.buf; rev.rdiff2 = rdiff2.buf; - rev.creation_factor = RANGE_DIFF_CREATION_FACTOR_DEFAULT; + rev.creation_factor = creation_factor; rev.rdiff_title = diff_title(&rdiff_title, reroll_count, _("Range-diff:"), _("Range-diff against v%d:")); -- cgit v0.10.2-6-g49f6 From 40ce41604daf200cdc85abded0133d40faafc2f8 Mon Sep 17 00:00:00 2001 From: Eric Sunshine Date: Sun, 22 Jul 2018 05:57:17 -0400 Subject: 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=" 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 Signed-off-by: Junio C Hamano diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 9b2e172..aba4c5f 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -241,7 +241,8 @@ feeding the result to `git send-email`. --range-diff=:: As a reviewer aid, insert a range-diff (see linkgit:git-range-diff[1]) - into the cover letter showing the differences between the previous + into the cover letter, or as commentary of the lone patch of a + 1-patch series, showing the differences between the previous version of the patch series and the series currently being formatted. `previous` can be a single revision naming the tip of the previous series if it shares a common base with the series being formatted (for diff --git a/builtin/log.c b/builtin/log.c index 05965a57..f69b67b 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1576,7 +1576,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) N_("show changes against in cover letter or single patch"), parse_opt_object_name), OPT_STRING(0, "range-diff", &rdiff_prev, N_("refspec"), - N_("show changes against in cover letter")), + N_("show changes against in cover letter or single patch")), OPT_INTEGER(0, "creation-factor", &creation_factor, N_("percentage by which creation is weighted")), OPT_END() @@ -1817,8 +1817,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) die(_("--creation-factor requires --range-diff")); if (rdiff_prev) { - if (!cover_letter) - die(_("--range-diff requires --cover-letter")); + if (!cover_letter && total != 1) + die(_("--range-diff requires --cover-letter or single patch")); infer_range_diff_ranges(&rdiff1, &rdiff2, rdiff_prev, origin, list[0]); @@ -1867,8 +1867,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) print_signature(rev.diffopt.file); total++; start_number--; - /* interdiff in cover-letter; omit from patches */ + /* interdiff/range-diff in cover-letter; omit from patches */ rev.idiff_oid1 = NULL; + rev.rdiff1 = NULL; } rev.add_signoff = do_signoff; diff --git a/log-tree.c b/log-tree.c index e21c3d9..cec983a 100644 --- a/log-tree.c +++ b/log-tree.c @@ -16,6 +16,7 @@ #include "line-log.h" #include "help.h" #include "interdiff.h" +#include "range-diff.h" static struct decoration name_decoration = { "object names" }; static int decoration_loaded; @@ -751,6 +752,20 @@ void show_log(struct rev_info *opt) memcpy(&diff_queued_diff, &dq, sizeof(diff_queued_diff)); } + + if (cmit_fmt_is_mail(ctx.fmt) && opt->rdiff1) { + struct diff_queue_struct dq; + + memcpy(&dq, &diff_queued_diff, sizeof(diff_queued_diff)); + DIFF_QUEUE_CLEAR(&diff_queued_diff); + + next_commentary_block(opt, NULL); + fprintf_ln(opt->diffopt.file, "%s", opt->rdiff_title); + show_range_diff(opt->rdiff1, opt->rdiff2, + opt->creation_factor, 1, &opt->diffopt); + + memcpy(&diff_queued_diff, &dq, sizeof(diff_queued_diff)); + } } int log_tree_diff_flush(struct rev_info *opt) -- cgit v0.10.2-6-g49f6