From fa5b7ea670f4c5ee377e7fce799300829eabb291 Mon Sep 17 00:00:00 2001 From: Eric Sunshine Date: Sun, 22 Jul 2018 05:57:04 -0400 Subject: [PATCH 1/6] format-patch: allow additional generated content in make_cover_letter() make_cover_letter() returns early when it lacks sufficient state to emit a diffstat, which makes it difficult to extend the function to reliably emit additional generated content. Work around this shortcoming by factoring diffstat-printing logic out to its own function and calling it as needed without otherwise inhibiting normal control flow. Signed-off-by: Eric Sunshine Signed-off-by: Junio C Hamano --- builtin/log.c | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/builtin/log.c b/builtin/log.c index 805f89d7e1..873aabcf40 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -997,6 +997,26 @@ static char *find_branch_name(struct rev_info *rev) return branch; } +static void show_diffstat(struct rev_info *rev, + struct commit *origin, struct commit *head) +{ + struct diff_options opts; + + memcpy(&opts, &rev->diffopt, sizeof(opts)); + opts.output_format = DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT; + opts.stat_width = MAIL_DEFAULT_WRAP; + + diff_setup_done(&opts); + + diff_tree_oid(get_commit_tree_oid(origin), + get_commit_tree_oid(head), + "", &opts); + diffcore_std(&opts); + diff_flush(&opts); + + fprintf(rev->diffopt.file, "\n"); +} + static void make_cover_letter(struct rev_info *rev, int use_stdout, struct commit *origin, int nr, struct commit **list, @@ -1010,7 +1030,6 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, struct strbuf sb = STRBUF_INIT; int i; const char *encoding = "UTF-8"; - struct diff_options opts; int need_8bit_cte = 0; struct pretty_print_context pp = {0}; struct commit *head = list[0]; @@ -1060,25 +1079,9 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, shortlog_output(&log); - /* - * We can only do diffstat with a unique reference point - */ - if (!origin) - return; - - memcpy(&opts, &rev->diffopt, sizeof(opts)); - opts.output_format = DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT; - opts.stat_width = MAIL_DEFAULT_WRAP; - - diff_setup_done(&opts); - - diff_tree_oid(get_commit_tree_oid(origin), - get_commit_tree_oid(head), - "", &opts); - diffcore_std(&opts); - diff_flush(&opts); - - fprintf(rev->diffopt.file, "\n"); + /* We can only do diffstat with a unique reference point */ + if (origin) + show_diffstat(rev, origin, head); } static const char *clean_message_id(const char *msg_id) From 126facf8219177bc265be725a8579c86ebdf99a5 Mon Sep 17 00:00:00 2001 From: Eric Sunshine Date: Sun, 22 Jul 2018 05:57:05 -0400 Subject: [PATCH 2/6] format-patch: add --interdiff 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 an interdiff, however, doing so involves manually copy/pasting the diff into the cover letter. Add an --interdiff option to automate this process. The argument to --interdiff specifies the tip of the previous attempt against which to generate the interdiff. For example: git format-patch --cover-letter --interdiff=v1 -3 v2 The previous attempt and the patch series being formatted must share a common base. Signed-off-by: Eric Sunshine Signed-off-by: Junio C Hamano --- Documentation/git-format-patch.txt | 9 +++++++++ Makefile | 1 + builtin/log.c | 24 ++++++++++++++++++++++-- interdiff.c | 17 +++++++++++++++++ interdiff.h | 8 ++++++++ revision.h | 4 ++++ t/t4014-format-patch.sh | 17 +++++++++++++++++ 7 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 interdiff.c create mode 100644 interdiff.h diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index b41e1329a7..a1b1bafee7 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -23,6 +23,7 @@ SYNOPSIS [(--reroll-count|-v) ] [--to=] [--cc=] [--[no-]cover-letter] [--quiet] [--notes[=]] + [--interdiff=] [--progress] [] [ | ] @@ -228,6 +229,14 @@ feeding the result to `git send-email`. containing the branch description, shortlog and the overall diffstat. You can fill in a description in the file before sending it out. +--interdiff=:: + As a reviewer aid, insert an interdiff 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 --interdiff=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/Makefile b/Makefile index 08e5c54549..b2685190e1 100644 --- a/Makefile +++ b/Makefile @@ -871,6 +871,7 @@ LIB_OBJS += hashmap.o LIB_OBJS += help.o LIB_OBJS += hex.o LIB_OBJS += ident.o +LIB_OBJS += interdiff.o LIB_OBJS += kwset.o LIB_OBJS += levenshtein.o LIB_OBJS += line-log.o diff --git a/builtin/log.c b/builtin/log.c index 873aabcf40..1020b78477 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -30,6 +30,7 @@ #include "gpg-interface.h" #include "progress.h" #include "commit-slab.h" +#include "interdiff.h" #define MAIL_DEFAULT_WRAP 72 @@ -1082,6 +1083,11 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, /* We can only do diffstat with a unique reference point */ if (origin) show_diffstat(rev, origin, head); + + if (rev->idiff_oid1) { + fprintf_ln(rev->diffopt.file, "%s", _("Interdiff:")); + show_interdiff(rev); + } } static const char *clean_message_id(const char *msg_id) @@ -1448,6 +1454,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) struct base_tree_info bases; int show_progress = 0; struct progress *progress = NULL; + struct oid_array idiff_prev = OID_ARRAY_INIT; const struct option builtin_format_patch_options[] = { { OPTION_CALLBACK, 'n', "numbered", &numbered, NULL, @@ -1521,6 +1528,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) OPT__QUIET(&quiet, N_("don't print the patch filenames")), OPT_BOOL(0, "progress", &show_progress, N_("show progress while generating patches")), + OPT_CALLBACK(0, "interdiff", &idiff_prev, N_("rev"), + N_("show changes against in cover letter"), + parse_opt_object_name), OPT_END() }; @@ -1706,7 +1716,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (rev.pending.nr == 2) { struct object_array_entry *o = rev.pending.objects; if (oidcmp(&o[0].item->oid, &o[1].item->oid) == 0) - return 0; + goto done; } get_patch_ids(&rev, &ids); } @@ -1730,7 +1740,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) } if (nr == 0) /* nothing to do */ - return 0; + goto done; total = nr; if (cover_letter == -1) { if (config_cover_letter == COVER_AUTO) @@ -1743,6 +1753,13 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (numbered) rev.total = total + start_number - 1; + if (idiff_prev.nr) { + if (!cover_letter) + die(_("--interdiff requires --cover-letter")); + rev.idiff_oid1 = &idiff_prev.oid[idiff_prev.nr - 1]; + rev.idiff_oid2 = get_commit_tree_oid(list[0]); + } + if (!signature) { ; /* --no-signature inhibits all signatures */ } else if (signature && signature != git_version_string) { @@ -1860,6 +1877,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) string_list_clear(&extra_hdr, 0); if (ignore_if_in_upstream) free_patch_ids(&ids); + +done: + oid_array_clear(&idiff_prev); return 0; } diff --git a/interdiff.c b/interdiff.c new file mode 100644 index 0000000000..d0fac10c7c --- /dev/null +++ b/interdiff.c @@ -0,0 +1,17 @@ +#include "cache.h" +#include "commit.h" +#include "revision.h" +#include "interdiff.h" + +void show_interdiff(struct rev_info *rev) +{ + struct diff_options opts; + + memcpy(&opts, &rev->diffopt, sizeof(opts)); + opts.output_format = DIFF_FORMAT_PATCH; + diff_setup_done(&opts); + + diff_tree_oid(rev->idiff_oid1, rev->idiff_oid2, "", &opts); + diffcore_std(&opts); + diff_flush(&opts); +} diff --git a/interdiff.h b/interdiff.h new file mode 100644 index 0000000000..793c0144fe --- /dev/null +++ b/interdiff.h @@ -0,0 +1,8 @@ +#ifndef INTERDIFF_H +#define INTERDIFF_H + +struct rev_info; + +void show_interdiff(struct rev_info *); + +#endif diff --git a/revision.h b/revision.h index bf2239f876..61931fbac5 100644 --- a/revision.h +++ b/revision.h @@ -212,6 +212,10 @@ struct rev_info { /* notes-specific options: which refs to show */ struct display_notes_opt notes_opt; + /* interdiff */ + const struct object_id *idiff_oid1; + const struct object_id *idiff_oid2; + /* commit counts */ int count_left; int count_right; diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index 53880da7bb..57b46322aa 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -1717,4 +1717,21 @@ test_expect_success 'format-patch --pretty=mboxrd' ' test_cmp expect actual ' +test_expect_success 'interdiff: setup' ' + git checkout -b boop master && + test_commit fnorp blorp && + test_commit fleep blorp +' + +test_expect_success 'interdiff: cover-letter' ' + sed "y/q/ /" >expect <<-\EOF && + +fleep + --q + EOF + git format-patch --cover-letter --interdiff=boop~2 -1 boop && + test_i18ngrep "^Interdiff:$" 0000-cover-letter.patch && + sed "1,/^@@ /d; /^-- $/q" <0000-cover-letter.patch >actual && + test_cmp expect actual +' + test_done From 5ac290f9c00edb8963585c322fae9fb06a98167d Mon Sep 17 00:00:00 2001 From: Eric Sunshine Date: Sun, 22 Jul 2018 05:57:06 -0400 Subject: [PATCH 3/6] format-patch: teach --interdiff to respect -v/--reroll-count The --interdiff option introduces the embedded interdiff generically as "Interdiff:", however, we can do better when --reroll-count is specified by emitting "Interdiff against v{n}:" instead. Signed-off-by: Eric Sunshine Signed-off-by: Junio C Hamano --- builtin/log.c | 17 ++++++++++++++++- revision.h | 1 + t/t4014-format-patch.sh | 5 +++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/builtin/log.c b/builtin/log.c index 1020b78477..99ddfe8bb0 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1085,7 +1085,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, show_diffstat(rev, origin, head); if (rev->idiff_oid1) { - fprintf_ln(rev->diffopt.file, "%s", _("Interdiff:")); + fprintf_ln(rev->diffopt.file, "%s", rev->idiff_title); show_interdiff(rev); } } @@ -1427,6 +1427,16 @@ static void print_bases(struct base_tree_info *bases, FILE *file) oidclr(&bases->base_commit); } +static const char *diff_title(struct strbuf *sb, int reroll_count, + const char *generic, const char *rerolled) +{ + if (reroll_count <= 0) + strbuf_addstr(sb, generic); + else /* RFC may be v0, so allow -v1 to diff against v0 */ + strbuf_addf(sb, rerolled, reroll_count - 1); + return sb->buf; +} + int cmd_format_patch(int argc, const char **argv, const char *prefix) { struct commit *commit; @@ -1455,6 +1465,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) int show_progress = 0; struct progress *progress = NULL; struct oid_array idiff_prev = OID_ARRAY_INIT; + struct strbuf idiff_title = STRBUF_INIT; const struct option builtin_format_patch_options[] = { { OPTION_CALLBACK, 'n', "numbered", &numbered, NULL, @@ -1758,6 +1769,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) die(_("--interdiff requires --cover-letter")); rev.idiff_oid1 = &idiff_prev.oid[idiff_prev.nr - 1]; rev.idiff_oid2 = get_commit_tree_oid(list[0]); + rev.idiff_title = diff_title(&idiff_title, reroll_count, + _("Interdiff:"), + _("Interdiff against v%d:")); } if (!signature) { @@ -1880,6 +1894,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) done: oid_array_clear(&idiff_prev); + strbuf_release(&idiff_title); return 0; } diff --git a/revision.h b/revision.h index 61931fbac5..ffeadc261a 100644 --- a/revision.h +++ b/revision.h @@ -215,6 +215,7 @@ struct rev_info { /* interdiff */ const struct object_id *idiff_oid1; const struct object_id *idiff_oid2; + const char *idiff_title; /* commit counts */ int count_left; diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index 57b46322aa..5950890d30 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -1734,4 +1734,9 @@ test_expect_success 'interdiff: cover-letter' ' test_cmp expect actual ' +test_expect_success 'interdiff: reroll-count' ' + git format-patch --cover-letter --interdiff=boop~2 -v2 -1 boop && + test_i18ngrep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch +' + test_done From 3b026417eaa1f32f53b85d1b131194ae1cbbf068 Mon Sep 17 00:00:00 2001 From: Eric Sunshine Date: Sun, 22 Jul 2018 05:57:07 -0400 Subject: [PATCH 4/6] interdiff: teach show_interdiff() to indent interdiff A future change will allow "git format-patch --interdiff= -1" to insert an interdiff into the commentary section of the lone patch of a 1-patch series. However, to prevent the inserted interdiff from confusing git-am, as well as human readers, it needs to be indented. Therefore, teach show_interdiff() how to indent. Signed-off-by: Eric Sunshine Signed-off-by: Junio C Hamano --- builtin/log.c | 2 +- interdiff.c | 13 ++++++++++++- interdiff.h | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/builtin/log.c b/builtin/log.c index 99ddfe8bb0..8078a43d14 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1086,7 +1086,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, if (rev->idiff_oid1) { fprintf_ln(rev->diffopt.file, "%s", rev->idiff_title); - show_interdiff(rev); + show_interdiff(rev, 0); } } diff --git a/interdiff.c b/interdiff.c index d0fac10c7c..c81d680a6c 100644 --- a/interdiff.c +++ b/interdiff.c @@ -3,15 +3,26 @@ #include "revision.h" #include "interdiff.h" -void show_interdiff(struct rev_info *rev) +static struct strbuf *idiff_prefix_cb(struct diff_options *opt, void *data) +{ + return data; +} + +void show_interdiff(struct rev_info *rev, int indent) { struct diff_options opts; + struct strbuf prefix = STRBUF_INIT; memcpy(&opts, &rev->diffopt, sizeof(opts)); opts.output_format = DIFF_FORMAT_PATCH; + opts.output_prefix = idiff_prefix_cb; + strbuf_addchars(&prefix, ' ', indent); + opts.output_prefix_data = &prefix; diff_setup_done(&opts); diff_tree_oid(rev->idiff_oid1, rev->idiff_oid2, "", &opts); diffcore_std(&opts); diff_flush(&opts); + + strbuf_release(&prefix); } diff --git a/interdiff.h b/interdiff.h index 793c0144fe..01c730a5c9 100644 --- a/interdiff.h +++ b/interdiff.h @@ -3,6 +3,6 @@ struct rev_info; -void show_interdiff(struct rev_info *); +void show_interdiff(struct rev_info *, int indent); #endif From 3fcc7a23a0b76bdac07b605a6afd6084ac543821 Mon Sep 17 00:00:00 2001 From: Eric Sunshine Date: Sun, 22 Jul 2018 05:57:08 -0400 Subject: [PATCH 5/6] log-tree: show_log: make commentary block delimiting reusable In patches generated by git-format-patch, the area below the "---" line following the commit message and before the actual 'diff' can be used for commentary which the patch author wants to convey to readers of the patch itself but not include in the commit message proper. By default, the commentary area is empty, however, the --notes option causes it to be populated with notes associated with the commit. In the future, other options may be added which also insert content into the commentary section. To accommodate this, factor out the logic which delimits commentary blocks from the commit message so that it can be re-used for upcoming optional inserted content. Signed-off-by: Eric Sunshine Signed-off-by: Junio C Hamano --- log-tree.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/log-tree.c b/log-tree.c index 4a3907fea0..9d38f1cf79 100644 --- a/log-tree.c +++ b/log-tree.c @@ -541,6 +541,16 @@ static int show_mergetag(struct rev_info *opt, struct commit *commit) return for_each_mergetag(show_one_mergetag, commit, opt); } +static void next_commentary_block(struct rev_info *opt, struct strbuf *sb) +{ + const char *x = opt->shown_dashes ? "\n" : "---\n"; + if (sb) + strbuf_addstr(sb, x); + else + fputs(x, opt->diffopt.file); + opt->shown_dashes = 1; +} + void show_log(struct rev_info *opt) { struct strbuf msgbuf = STRBUF_INIT; @@ -698,10 +708,8 @@ void show_log(struct rev_info *opt) if ((ctx.fmt != CMIT_FMT_USERFORMAT) && ctx.notes_message && *ctx.notes_message) { - if (cmit_fmt_is_mail(ctx.fmt)) { - strbuf_addstr(&msgbuf, "---\n"); - opt->shown_dashes = 1; - } + if (cmit_fmt_is_mail(ctx.fmt)) + next_commentary_block(opt, &msgbuf); strbuf_addstr(&msgbuf, ctx.notes_message); } @@ -765,9 +773,10 @@ int log_tree_diff_flush(struct rev_info *opt) /* * We may have shown three-dashes line early - * between notes and the log message, in which - * case we only want a blank line after the - * notes without (an extra) three-dashes line. + * between generated commentary (notes, etc.) + * and the log message, in which case we only + * want a blank line after the commentary + * without (an extra) three-dashes line. * Otherwise, we show the three-dashes line if * we are showing the patch with diffstat, but * in that case, there is no extra blank line From ee6cbf712edcbd1dc14993ab2452fbe882dc524a Mon Sep 17 00:00:00 2001 From: Eric Sunshine Date: Sun, 22 Jul 2018 05:57:09 -0400 Subject: [PATCH 6/6] format-patch: allow --interdiff 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 an interdiff, typically in the cover letter. However, it is occasionally useful, despite making for a noisy read, to insert an interdiff into the commentary section of the lone patch of a 1-patch series. Therefore, extend "git format-patch --interdiff=" to insert an interdiff into the commentary section of a lone patch rather than requiring a cover letter. The interdiff is indented to avoid confusing git-am and human readers into considering it part of the patch proper. Implementation note: Generating an interdiff 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 interdiff, and restore it after. Signed-off-by: Eric Sunshine Signed-off-by: Junio C Hamano --- Documentation/git-format-patch.txt | 3 ++- builtin/log.c | 8 +++++--- log-tree.c | 14 ++++++++++++++ t/t4014-format-patch.sh | 12 ++++++++++++ 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index a1b1bafee7..f8a061794d 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -230,7 +230,8 @@ feeding the result to `git send-email`. fill in a description in the file before sending it out. --interdiff=:: - As a reviewer aid, insert an interdiff into the cover letter showing + As a reviewer aid, insert an interdiff 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` is a single revision naming the tip of the previous series which shares a common base with diff --git a/builtin/log.c b/builtin/log.c index 8078a43d14..e990027c28 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1540,7 +1540,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) OPT_BOOL(0, "progress", &show_progress, N_("show progress while generating patches")), OPT_CALLBACK(0, "interdiff", &idiff_prev, N_("rev"), - N_("show changes against in cover letter"), + N_("show changes against in cover letter or single patch"), parse_opt_object_name), OPT_END() }; @@ -1765,8 +1765,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.total = total + start_number - 1; if (idiff_prev.nr) { - if (!cover_letter) - die(_("--interdiff requires --cover-letter")); + if (!cover_letter && total != 1) + die(_("--interdiff requires --cover-letter or single patch")); rev.idiff_oid1 = &idiff_prev.oid[idiff_prev.nr - 1]; rev.idiff_oid2 = get_commit_tree_oid(list[0]); rev.idiff_title = diff_title(&idiff_title, reroll_count, @@ -1811,6 +1811,8 @@ 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 */ + rev.idiff_oid1 = NULL; } rev.add_signoff = do_signoff; diff --git a/log-tree.c b/log-tree.c index 9d38f1cf79..56513fa83d 100644 --- a/log-tree.c +++ b/log-tree.c @@ -14,6 +14,7 @@ #include "sequencer.h" #include "line-log.h" #include "help.h" +#include "interdiff.h" static struct decoration name_decoration = { "object names" }; static int decoration_loaded; @@ -736,6 +737,19 @@ void show_log(struct rev_info *opt) strbuf_release(&msgbuf); free(ctx.notes_message); + + if (cmit_fmt_is_mail(ctx.fmt) && opt->idiff_oid1) { + 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->idiff_title); + show_interdiff(opt, 2); + + memcpy(&diff_queued_diff, &dq, sizeof(diff_queued_diff)); + } } int log_tree_diff_flush(struct rev_info *opt) diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index 5950890d30..909c743c13 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -1730,6 +1730,7 @@ test_expect_success 'interdiff: cover-letter' ' EOF git format-patch --cover-letter --interdiff=boop~2 -1 boop && test_i18ngrep "^Interdiff:$" 0000-cover-letter.patch && + test_i18ngrep ! "^Interdiff:$" 0001-fleep.patch && sed "1,/^@@ /d; /^-- $/q" <0000-cover-letter.patch >actual && test_cmp expect actual ' @@ -1739,4 +1740,15 @@ test_expect_success 'interdiff: reroll-count' ' test_i18ngrep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch ' +test_expect_success 'interdiff: solo-patch' ' + cat >expect <<-\EOF && + +fleep + + EOF + git format-patch --interdiff=boop~2 -1 boop && + test_i18ngrep "^Interdiff:$" 0001-fleep.patch && + sed "1,/^ @@ /d; /^$/q" <0001-fleep.patch >actual && + test_cmp expect actual +' + test_done