Teach git-format-patch a new option --comment-notes (with config format.commentNotes) which takes a notes ref argument. These notes are then added to the patch email between the --- separator and the diffstat/diff. This is somewhat tricky because the pretty-printing code has no control whatsoever over the --- and the diffstat, and there be dragons in the newline-producing code inside show_log(). Try not to disturb them, and patch around only outside show_log(). To ensure correctness of the resulting email, extend the existing rule (separator if not 'oneline' format and --patch-with-stat) to also include a separator if there are notes and a patch will be included. Signed-off-by: Thomas Rast <trast@xxxxxxxxxxxxxxx> --- So here's the promised patch. This is sort-of-RFC; it's not part of the series because I don't want the latter to block on this one if anyone suggests changes. I'll follow up with a broken version to prove the point about the dragons I made above, if anyone wants to try fixing it. Documentation/config.txt | 6 ++ Documentation/git-format-patch.txt | 10 ++++ builtin-log.c | 12 +++++ log-tree.c | 14 +++++- pretty.c | 2 +- t/t4014-format-patch.sh | 91 ++++++++++++++++++++++++++++++++++++ 6 files changed, 133 insertions(+), 2 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index dffe1f6..a9e27db 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -886,6 +886,12 @@ format.signoff:: the rights to submit this work under the same open source license. Please see the 'SubmittingPatches' document for further discussion. +format.commentNotes:: + The default notes reference that is used for the comment + section with --pretty=email and for 'git-format-patch'. (The + comment section is the area between the `\---` separator and + the patch, which also holds the diffstat.) + gc.aggressiveWindow:: The window size parameter used in the delta compression algorithm used by 'git gc --aggressive'. This defaults diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 9674f9d..afe7e41 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -198,6 +198,16 @@ you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`. range are always formatted as creation patches, independently of this flag. +--comment-notes=<ref>:: + Use the notes from <ref> to fill the comment section of the + email, i.e., the part between the `\---` separator and the + patch. See linkgit:git-notes[1]. ++ +Warning: the code currently does not guard against a line in the notes +that starts with `diff`, which will be treated as the start of the +patch by 'git-am'. + + CONFIGURATION ------------- You can specify extra mail header lines to be added to each message, diff --git a/builtin-log.c b/builtin-log.c index e7ea088..f85837d 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -19,6 +19,7 @@ #include "remote.h" #include "string-list.h" #include "parse-options.h" +#include "notes.h" /* Set a default date-time format for git log ("log.date" config variable) */ static const char *default_date_mode = NULL; @@ -495,6 +496,7 @@ static void add_header(const char *value) #define THREAD_DEEP 2 static int thread = 0; static int do_signoff = 0; +static const char *comment_notes = NULL; static int git_format_config(const char *var, const char *value, void *cb) { @@ -548,6 +550,9 @@ static int git_format_config(const char *var, const char *value, void *cb) do_signoff = git_config_bool(var, value); return 0; } + if (!strcmp(var, "format.commentnotes")) { + return git_config_string(&comment_notes, var, value); + } return git_log_config(var, value, cb); } @@ -955,6 +960,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) { OPTION_CALLBACK, 0, "thread", &thread, "style", "enable message threading, styles: shallow, deep", PARSE_OPT_OPTARG, thread_callback }, + OPT_STRING(0, "comment-notes", &comment_notes, + "ref", "use notes from <ref> for comment section"), OPT_END() }; @@ -1039,6 +1046,11 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (keep_subject && subject_prefix) die ("--subject-prefix and -k are mutually exclusive."); + if (comment_notes) { + init_notes(NULL, comment_notes, combine_notes_ignore, 0); + rev.show_notes = 1; + } + argc = setup_revisions(argc, argv, &rev, "HEAD"); if (argc > 1) die ("unrecognized argument: %s", argv[1]); diff --git a/log-tree.c b/log-tree.c index d3ae969..9830be8 100644 --- a/log-tree.c +++ b/log-tree.c @@ -7,6 +7,7 @@ #include "reflog-walk.h" #include "refs.h" #include "string-list.h" +#include "notes.h" struct decoration name_decoration = { "object names" }; @@ -457,6 +458,7 @@ int log_tree_diff_flush(struct rev_info *opt) } if (opt->loginfo && !opt->no_commit_id) { + const unsigned char *sha1 = opt->loginfo->commit->object.sha1; /* When showing a verbose header (i.e. log message), * and not in --pretty=oneline format, we would want * an extra newline between the end of log and the @@ -467,10 +469,20 @@ int log_tree_diff_flush(struct rev_info *opt) opt->verbose_header && opt->commit_format != CMIT_FMT_ONELINE) { int pch = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_PATCH; - if ((pch & opt->diffopt.output_format) == pch) + if ((pch & opt->diffopt.output_format) == pch + || (opt->commit_format == CMIT_FMT_EMAIL + && opt->show_notes)) printf("---"); putchar('\n'); } + if (opt->commit_format == CMIT_FMT_EMAIL && opt->show_notes) { + struct strbuf sb = STRBUF_INIT; + putchar('\n'); + format_note(NULL, sha1, &sb, NULL, 0); + fwrite(sb.buf, 1, sb.len, stdout); + strbuf_release(&sb); + putchar('\n'); + } } diff_flush(&opt->diffopt); return 1; diff --git a/pretty.c b/pretty.c index 6ba3da8..10d7812 100644 --- a/pretty.c +++ b/pretty.c @@ -1095,7 +1095,7 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit, if (fmt == CMIT_FMT_EMAIL && sb->len <= beginning_of_body) strbuf_addch(sb, '\n'); - if (context->show_notes) + if (context->show_notes && fmt != CMIT_FMT_EMAIL) format_display_notes(commit->object.sha1, sb, encoding, NOTES_SHOW_HEADER | NOTES_INDENT); diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index f2a2aaa..653e50a 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -557,4 +557,95 @@ test_expect_success 'format-patch -- <path>' ' ! grep "Use .--" error ' +cat >expect-no-comment <<EOF +Subject: [PATCH] foo +Cc: R. E. Cipient <rcipient@xxxxxxxxxxx> + +--- + file | 32 -------------------------------- + foo | 32 ++++++++++++++++++++++++++++++++ + 2 files changed, 32 insertions(+), 32 deletions(-) + delete mode 100644 file + create mode 100644 foo + +diff --git a/file b/file +EOF + +cat >expect-comment <<EOF +Subject: [PATCH] foo +Cc: R. E. Cipient <rcipient@xxxxxxxxxxx> + +--- + +a bit of testing here + + file | 32 -------------------------------- + foo | 32 ++++++++++++++++++++++++++++++++ + 2 files changed, 32 insertions(+), 32 deletions(-) + delete mode 100644 file + create mode 100644 foo + +diff --git a/file b/file +EOF + +test_expect_success 'comment section untouched by default' ' + git notes add -m"a bit of testing here" && + git format-patch -1 --stdout > output && + sed -e "1,/^Date/d" -e "/^diff --git/q" output > output+ && + test_cmp expect-no-comment output+ +' + +test_expect_success '--comment-notes' ' + git format-patch --comment-notes=refs/notes/commits -1 --stdout > output && + sed -e "1,/^Date/d" -e "/^diff --git/q" output > output+ && + test_cmp expect-comment output+ +' + +test_expect_success 'format.commentNotes' ' + git config format.commentNotes refs/notes/commits && + git format-patch -1 --stdout > output && + sed -e "1,/^Date/d" -e "/^diff --git/q" output > output+ && + test_cmp expect-comment output+ +' + +test_expect_success '--comment-notes overrides format.commentNotes' ' + git config format.commentNotes refs/notes/empty && + git format-patch --comment-notes=refs/notes/commits -1 --stdout > output && + sed -e "1,/^Date/d" -e "/^diff --git/q" output > output+ && + test_cmp expect-comment output+ +' + +cat >expect <<EOF +Subject: [PATCH] foo +Cc: R. E. Cipient <rcipient@xxxxxxxxxxx> + + +diff --git a/file b/file +EOF + +test_expect_success 'no separator with neither diffstat nor notes' ' + git config --unset format.commentNotes && + git format-patch -p -1 --stdout > output && + sed -e "1,/^Date/d" -e "/^diff --git/q" output > output+ && + test_cmp expect output+ +' + +cat >expect <<EOF +Subject: [PATCH] foo +Cc: R. E. Cipient <rcipient@xxxxxxxxxxx> + +--- + +a bit of testing here + +diff --git a/file b/file +EOF + +test_expect_success 'separator with notes but no diffstat' ' + git config format.commentNotes refs/notes/commits && + git format-patch -p -1 --stdout > output && + sed -e "1,/^Date/d" -e "/^diff --git/q" output > output+ && + test_cmp expect output+ +' + test_done -- 1.7.0.218.g73a398 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html