diff --git a/Documentation/config/format.adoc b/Documentation/config/format.adoc index ab0710e86a3e2ca7d0724e174213cada4a611cb4..df9e88d7e1e941de3fb1ac50daef0f6189037305 100644 --- a/Documentation/config/format.adoc +++ b/Documentation/config/format.adoc @@ -37,6 +37,10 @@ format.cc:: by mail. See the --to and --cc options in linkgit:git-format-patch[1]. +format.ccCmd:: + Program to generate list of additional CC recipients for all patches. + See the --cc-cmd option in linkgit:git-format-patch[1]. + format.subjectPrefix:: The default for format-patch is to output files with the '[PATCH]' subject prefix. Use this variable to change that prefix. diff --git a/Documentation/git-format-patch.adoc b/Documentation/git-format-patch.adoc index a8b53db9a6635b69cdd86241cc1f25936f224ef6..1ba5359cd36e9891ce4b9d4b651455de86bc8300 100644 --- a/Documentation/git-format-patch.adoc +++ b/Documentation/git-format-patch.adoc @@ -22,7 +22,7 @@ SYNOPSIS [--cover-from-description=] [--rfc[=]] [--subject-prefix=] [(--reroll-count|-v) ] - [--to=] [--cc=] + [--to=] [--cc=] [--cc-cmd=] [--[no-]cover-letter] [--quiet] [--[no-]encode-email-headers] [--no-notes | --notes[=]] @@ -280,6 +280,11 @@ e.g., `--rfc='-(WIP)'` results in "PATCH (WIP)". The negated form `--no-cc` discards all `Cc:` headers added so far (from config or command line). +--cc-cmd=:: + Specify a program to execute which generates a list of recipients to CC + on all patches. Output of this program must be a single email address + per line. This option overrides `format.ccCmd` configuration. + --from:: --from=:: Use `ident` in the `From:` header of each commit email. If the diff --git a/builtin/log.c b/builtin/log.c index 24a57c20a410e4921ca055035258a3fa224813db..cb88dda065a0665611613c1c059f20d96b38d624 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -40,6 +40,7 @@ #include "mailmap.h" #include "progress.h" #include "commit-slab.h" +#include "run-command.h" #include "commit-reach.h" #include "range-diff.h" @@ -1020,6 +1021,7 @@ struct format_config { struct string_list extra_hdr; struct string_list extra_to; struct string_list extra_cc; + char *cc_cmd; int keep_subject; int subject_prefix; struct strbuf sprefix; @@ -1053,6 +1055,7 @@ static void format_config_release(struct format_config *cfg) string_list_clear(&cfg->extra_cc, 0); strbuf_release(&cfg->sprefix); free(cfg->fmt_patch_suffix); + free(cfg->cc_cmd); } static enum cover_from_description parse_cover_from_description(const char *arg) @@ -1118,6 +1121,12 @@ static int git_format_config(const char *var, const char *value, string_list_append(&cfg->extra_cc, value); return 0; } + if (!strcmp(var, "format.cccmd")) { + if (!value) + return config_error_nonbool(var); + cfg->cc_cmd = xstrdup(value); + return 0; + } if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff") || !strcmp(var, "color.ui") || !strcmp(var, "diff.submodule")) { return 0; @@ -2014,6 +2023,27 @@ static void infer_range_diff_ranges(struct strbuf *r1, } } +static void run_cc_cmd(const char *prog, struct string_list *cc_list) +{ + struct child_process cmd = CHILD_PROCESS_INIT; + struct strbuf line = STRBUF_INIT; + FILE *fh; + + strvec_push(&cmd.args, prog); + cmd.out = -1; + + if (start_command(&cmd)) + return; + + fh = xfdopen(cmd.out, "r"); + while (strbuf_getline(&line, fh) != EOF) + string_list_append(cc_list, line.buf); + + fclose(fh); + finish_command(&cmd); + strbuf_release(&line); +} + int cmd_format_patch(int argc, const char **argv, const char *prefix, @@ -2064,6 +2094,7 @@ int cmd_format_patch(int argc, .revs = &rev, }; const char *fmt_patch_suffix = NULL; + const char *cc_cmd = NULL; const struct option builtin_format_patch_options[] = { OPT_CALLBACK_F('n', "numbered", &cfg, NULL, @@ -2118,6 +2149,8 @@ int cmd_format_patch(int argc, N_("add email header"), header_callback), OPT_STRING_LIST(0, "to", &cfg.extra_to, N_("email"), N_("add To: header")), OPT_STRING_LIST(0, "cc", &cfg.extra_cc, N_("email"), N_("add Cc: header")), + OPT_STRING(0, "cc-cmd", &cc_cmd, N_("program"), + N_("program to generate additional Cc addresses for all patches")), OPT_CALLBACK_F(0, "from", &cfg.from, N_("ident"), N_("set From address to (or committer ident if absent)"), PARSE_OPT_OPTARG, from_callback), @@ -2238,6 +2271,9 @@ int cmd_format_patch(int argc, strbuf_addch(&buf, '\n'); } + if (cc_cmd || cfg.cc_cmd) + run_cc_cmd(cc_cmd ? cc_cmd : cfg.cc_cmd, &cfg.extra_cc); + if (cfg.extra_cc.nr) strbuf_addstr(&buf, "Cc: "); for (i = 0; i < cfg.extra_cc.nr; i++) { diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index 2782b1fc183e8f1247e9b3f75a95f32569fdfc88..1cd67cc9d9616f299faeec33c3be3a9c05ea92d3 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -2547,4 +2547,30 @@ test_expect_success 'format-patch --default-prefix overrides format.noprefix' ' grep "^--- a/blorp" actual ' +test_expect_success 'additional cc from --cc-cmd' ' + test_when_finished "rm -f foo.sh" && + + write_script foo.sh <<-\EOF && + printf "%s\n" foo@bar.baz + EOF + + git format-patch --no-cc --cc-cmd="$PWD/foo.sh" --stdout -2 >actual && + + grep -c "^Cc: foo@bar.baz" actual >count && + test "$(cat count)" -eq 2 +' + +test_expect_success 'additional cc from format.ccCmd config' ' + test_when_finished "rm -f foo.sh" && + + write_script foo.sh <<-\EOF && + printf "%s\n" foo@bar.baz + EOF + + git -c format.ccCmd="$PWD/foo.sh" format-patch --no-cc --stdout -2 >actual && + + grep -c "^Cc: foo@bar.baz" actual >count && + test "$(cat count)" -eq 2 +' + test_done