Skip to content

Commit c24138b

Browse files
committed
Merge branch 'sd/format-patch-to'
* sd/format-patch-to: send-email: add --no-cc, --no-to, and --no-bcc format-patch: add --no-cc, --no-to, and --no-add-headers format-patch: use a string_list for headers Add 'git format-patch --to=' option and 'format.to' configuration variable.
2 parents 78d909a + f434c08 commit c24138b

File tree

5 files changed

+197
-46
lines changed

5 files changed

+197
-46
lines changed

Documentation/git-format-patch.txt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ SYNOPSIS
1818
[--in-reply-to=Message-Id] [--suffix=.<sfx>]
1919
[--ignore-if-in-upstream]
2020
[--subject-prefix=Subject-Prefix]
21-
[--cc=<email>]
21+
[--to=<email>] [--cc=<email>]
2222
[--cover-letter]
2323
[<common diff options>]
2424
[ <since> | <revision range> ]
@@ -162,6 +162,10 @@ will want to ensure that threading is disabled for `git send-email`.
162162
allows for useful naming of a patch series, and can be
163163
combined with the `--numbered` option.
164164

165+
--to=<email>::
166+
Add a `To:` header to the email headers. This is in addition
167+
to any configured headers, and may be used multiple times.
168+
165169
--cc=<email>::
166170
Add a `Cc:` header to the email headers. This is in addition
167171
to any configured headers, and may be used multiple times.
@@ -202,15 +206,16 @@ CONFIGURATION
202206
-------------
203207
You can specify extra mail header lines to be added to each message,
204208
defaults for the subject prefix and file suffix, number patches when
205-
outputting more than one patch, add "Cc:" headers, configure attachments,
206-
and sign off patches with configuration variables.
209+
outputting more than one patch, add "To" or "Cc:" headers, configure
210+
attachments, and sign off patches with configuration variables.
207211

208212
------------
209213
[format]
210214
headers = "Organization: git-foo\n"
211215
subjectprefix = CHANGE
212216
suffix = .txt
213217
numbered = auto
218+
to = <email>
214219
cc = <email>
215220
attach [ = mime-boundary-string ]
216221
signoff = true

builtin/log.c

Lines changed: 61 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -458,35 +458,28 @@ static int auto_number = 1;
458458

459459
static char *default_attach = NULL;
460460

461-
static char **extra_hdr;
462-
static int extra_hdr_nr;
463-
static int extra_hdr_alloc;
464-
465-
static char **extra_to;
466-
static int extra_to_nr;
467-
static int extra_to_alloc;
468-
469-
static char **extra_cc;
470-
static int extra_cc_nr;
471-
static int extra_cc_alloc;
461+
static struct string_list extra_hdr;
462+
static struct string_list extra_to;
463+
static struct string_list extra_cc;
472464

473465
static void add_header(const char *value)
474466
{
467+
struct string_list_item *item;
475468
int len = strlen(value);
476469
while (len && value[len - 1] == '\n')
477470
len--;
471+
478472
if (!strncasecmp(value, "to: ", 4)) {
479-
ALLOC_GROW(extra_to, extra_to_nr + 1, extra_to_alloc);
480-
extra_to[extra_to_nr++] = xstrndup(value + 4, len - 4);
481-
return;
482-
}
483-
if (!strncasecmp(value, "cc: ", 4)) {
484-
ALLOC_GROW(extra_cc, extra_cc_nr + 1, extra_cc_alloc);
485-
extra_cc[extra_cc_nr++] = xstrndup(value + 4, len - 4);
486-
return;
473+
item = string_list_append(value + 4, &extra_to);
474+
len -= 4;
475+
} else if (!strncasecmp(value, "cc: ", 4)) {
476+
item = string_list_append(value + 4, &extra_cc);
477+
len -= 4;
478+
} else {
479+
item = string_list_append(value, &extra_hdr);
487480
}
488-
ALLOC_GROW(extra_hdr, extra_hdr_nr + 1, extra_hdr_alloc);
489-
extra_hdr[extra_hdr_nr++] = xstrndup(value, len);
481+
482+
item->string[len] = '\0';
490483
}
491484

492485
#define THREAD_SHALLOW 1
@@ -504,11 +497,16 @@ static int git_format_config(const char *var, const char *value, void *cb)
504497
}
505498
if (!strcmp(var, "format.suffix"))
506499
return git_config_string(&fmt_patch_suffix, var, value);
500+
if (!strcmp(var, "format.to")) {
501+
if (!value)
502+
return config_error_nonbool(var);
503+
string_list_append(value, &extra_to);
504+
return 0;
505+
}
507506
if (!strcmp(var, "format.cc")) {
508507
if (!value)
509508
return config_error_nonbool(var);
510-
ALLOC_GROW(extra_cc, extra_cc_nr + 1, extra_cc_alloc);
511-
extra_cc[extra_cc_nr++] = xstrdup(value);
509+
string_list_append(value, &extra_cc);
512510
return 0;
513511
}
514512
if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) {
@@ -871,14 +869,31 @@ static int inline_callback(const struct option *opt, const char *arg, int unset)
871869

872870
static int header_callback(const struct option *opt, const char *arg, int unset)
873871
{
874-
add_header(arg);
872+
if (unset) {
873+
string_list_clear(&extra_hdr, 0);
874+
string_list_clear(&extra_to, 0);
875+
string_list_clear(&extra_cc, 0);
876+
} else {
877+
add_header(arg);
878+
}
879+
return 0;
880+
}
881+
882+
static int to_callback(const struct option *opt, const char *arg, int unset)
883+
{
884+
if (unset)
885+
string_list_clear(&extra_to, 0);
886+
else
887+
string_list_append(arg, &extra_to);
875888
return 0;
876889
}
877890

878891
static int cc_callback(const struct option *opt, const char *arg, int unset)
879892
{
880-
ALLOC_GROW(extra_cc, extra_cc_nr + 1, extra_cc_alloc);
881-
extra_cc[extra_cc_nr++] = xstrdup(arg);
893+
if (unset)
894+
string_list_clear(&extra_cc, 0);
895+
else
896+
string_list_append(arg, &extra_cc);
882897
return 0;
883898
}
884899

@@ -937,10 +952,11 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
937952
PARSE_OPT_NONEG | PARSE_OPT_NOARG },
938953
OPT_GROUP("Messaging"),
939954
{ OPTION_CALLBACK, 0, "add-header", NULL, "header",
940-
"add email header", PARSE_OPT_NONEG,
941-
header_callback },
955+
"add email header", 0, header_callback },
956+
{ OPTION_CALLBACK, 0, "to", NULL, "email", "add To: header",
957+
0, to_callback },
942958
{ OPTION_CALLBACK, 0, "cc", NULL, "email", "add Cc: header",
943-
PARSE_OPT_NONEG, cc_callback },
959+
0, cc_callback },
944960
OPT_STRING(0, "in-reply-to", &in_reply_to, "message-id",
945961
"make first mail a reply to <message-id>"),
946962
{ OPTION_CALLBACK, 0, "attach", &rev, "boundary",
@@ -956,6 +972,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
956972
OPT_END()
957973
};
958974

975+
extra_hdr.strdup_strings = 1;
976+
extra_to.strdup_strings = 1;
977+
extra_cc.strdup_strings = 1;
959978
git_config(git_format_config, NULL);
960979
init_revisions(&rev, prefix);
961980
rev.commit_format = CMIT_FMT_EMAIL;
@@ -992,29 +1011,29 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
9921011
add_signoff = xmemdupz(committer, endpos - committer + 1);
9931012
}
9941013

995-
for (i = 0; i < extra_hdr_nr; i++) {
996-
strbuf_addstr(&buf, extra_hdr[i]);
1014+
for (i = 0; i < extra_hdr.nr; i++) {
1015+
strbuf_addstr(&buf, extra_hdr.items[i].string);
9971016
strbuf_addch(&buf, '\n');
9981017
}
9991018

1000-
if (extra_to_nr)
1019+
if (extra_to.nr)
10011020
strbuf_addstr(&buf, "To: ");
1002-
for (i = 0; i < extra_to_nr; i++) {
1021+
for (i = 0; i < extra_to.nr; i++) {
10031022
if (i)
10041023
strbuf_addstr(&buf, " ");
1005-
strbuf_addstr(&buf, extra_to[i]);
1006-
if (i + 1 < extra_to_nr)
1024+
strbuf_addstr(&buf, extra_to.items[i].string);
1025+
if (i + 1 < extra_to.nr)
10071026
strbuf_addch(&buf, ',');
10081027
strbuf_addch(&buf, '\n');
10091028
}
10101029

1011-
if (extra_cc_nr)
1030+
if (extra_cc.nr)
10121031
strbuf_addstr(&buf, "Cc: ");
1013-
for (i = 0; i < extra_cc_nr; i++) {
1032+
for (i = 0; i < extra_cc.nr; i++) {
10141033
if (i)
10151034
strbuf_addstr(&buf, " ");
1016-
strbuf_addstr(&buf, extra_cc[i]);
1017-
if (i + 1 < extra_cc_nr)
1035+
strbuf_addstr(&buf, extra_cc.items[i].string);
1036+
if (i + 1 < extra_cc.nr)
10181037
strbuf_addch(&buf, ',');
10191038
strbuf_addch(&buf, '\n');
10201039
}
@@ -1223,6 +1242,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
12231242
fclose(stdout);
12241243
}
12251244
free(list);
1245+
string_list_clear(&extra_to, 0);
1246+
string_list_clear(&extra_cc, 0);
1247+
string_list_clear(&extra_hdr, 0);
12261248
if (ignore_if_in_upstream)
12271249
free_patch_ids(&ids);
12281250
return 0;

git-send-email.perl

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ sub usage {
4747
4848
Composing:
4949
--from <str> * Email From:
50-
--to <str> * Email To:
51-
--cc <str> * Email Cc:
52-
--bcc <str> * Email Bcc:
50+
--[no-]to <str> * Email To:
51+
--[no-]cc <str> * Email Cc:
52+
--[no-]bcc <str> * Email Bcc:
5353
--subject <str> * Email "Subject:"
5454
--in-reply-to <str> * Email "In-Reply-To:"
5555
--annotate * Review each patch that will be sent in an editor.
@@ -135,7 +135,7 @@ sub format_2822_time {
135135
sub cleanup_compose_files();
136136

137137
# Variables we fill in automatically, or via prompting:
138-
my (@to,@cc,@initial_cc,@bcclist,@xh,
138+
my (@to,$no_to,@cc,$no_cc,@initial_cc,@bcclist,$no_bcc,@xh,
139139
$initial_reply_to,$initial_subject,@files,
140140
$author,$sender,$smtp_authpass,$annotate,$compose,$time);
141141

@@ -261,8 +261,11 @@ sub signal_handler {
261261
"in-reply-to=s" => \$initial_reply_to,
262262
"subject=s" => \$initial_subject,
263263
"to=s" => \@to,
264+
"no-to" => \$no_to,
264265
"cc=s" => \@initial_cc,
266+
"no-cc" => \$no_cc,
265267
"bcc=s" => \@bcclist,
268+
"no-bcc" => \$no_bcc,
266269
"chain-reply-to!" => \$chain_reply_to,
267270
"smtp-server=s" => \$smtp_server,
268271
"smtp-server-port=s" => \$smtp_server_port,
@@ -305,6 +308,9 @@ sub read_config {
305308

306309
foreach my $setting (keys %config_settings) {
307310
my $target = $config_settings{$setting};
311+
next if $setting eq "to" and defined $no_to;
312+
next if $setting eq "cc" and defined $no_cc;
313+
next if $setting eq "bcc" and defined $no_bcc;
308314
if (ref($target) eq "ARRAY") {
309315
unless (@$target) {
310316
my @values = Git::config(@repo, "$prefix.$setting");

t/t4014-format-patch.sh

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,58 @@ test_expect_success 'configuration headers and command line headers' '
143143
grep "^ *S. E. Cipient <[email protected]>\$" patch7
144144
'
145145

146+
test_expect_success 'command line To: header' '
147+
148+
git config --unset-all format.headers &&
149+
git format-patch --to="R. E. Cipient <[email protected]>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
150+
grep "^To: R. E. Cipient <[email protected]>\$" patch8
151+
'
152+
153+
test_expect_success 'configuration To: header' '
154+
155+
git config format.to "R. E. Cipient <[email protected]>" &&
156+
git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
157+
grep "^To: R. E. Cipient <[email protected]>\$" patch9
158+
'
159+
160+
test_expect_success '--no-to overrides config.to' '
161+
162+
git config --replace-all format.to \
163+
"R. E. Cipient <[email protected]>" &&
164+
git format-patch --no-to --stdout master..side |
165+
sed -e "/^\$/q" >patch10 &&
166+
! grep "^To: R. E. Cipient <[email protected]>\$" patch10
167+
'
168+
169+
test_expect_success '--no-to and --to replaces config.to' '
170+
171+
git config --replace-all format.to \
172+
"Someone <[email protected]>" &&
173+
git format-patch --no-to --to="Someone Else <[email protected]>" \
174+
--stdout master..side |
175+
sed -e "/^\$/q" >patch11 &&
176+
! grep "^To: Someone <[email protected]>\$" patch11 &&
177+
grep "^To: Someone Else <[email protected]>\$" patch11
178+
'
179+
180+
test_expect_success '--no-cc overrides config.cc' '
181+
182+
git config --replace-all format.cc \
183+
"C. E. Cipient <[email protected]>" &&
184+
git format-patch --no-cc --stdout master..side |
185+
sed -e "/^\$/q" >patch12 &&
186+
! grep "^Cc: C. E. Cipient <[email protected]>\$" patch12
187+
'
188+
189+
test_expect_success '--no-add-headers overrides config.headers' '
190+
191+
git config --replace-all format.headers \
192+
"Header1: B. E. Cipient <[email protected]>" &&
193+
git format-patch --no-add-headers --stdout master..side |
194+
sed -e "/^\$/q" >patch13 &&
195+
! grep "^Header1: B. E. Cipient <[email protected]>\$" patch13
196+
'
197+
146198
test_expect_success 'multiple files' '
147199
148200
rm -rf patches/ &&

t/t9001-send-email.sh

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,4 +852,70 @@ test_expect_success 'no warning with sendemail.chainreplyto = true' '
852852
! grep "no-chain-reply-to" errors
853853
'
854854

855+
test_expect_success 'sendemail.to works' '
856+
git config --replace-all sendemail.to "Somebody <[email protected]>" &&
857+
git send-email \
858+
--dry-run \
859+
--from="Example <[email protected]>" \
860+
$patches $patches >stdout &&
861+
grep "To: Somebody <[email protected]>" stdout
862+
'
863+
864+
test_expect_success '--no-to overrides sendemail.to' '
865+
git send-email \
866+
--dry-run \
867+
--from="Example <[email protected]>" \
868+
--no-to \
869+
870+
$patches $patches >stdout &&
871+
grep "To: [email protected]" stdout &&
872+
! grep "To: Somebody <[email protected]>" stdout
873+
'
874+
875+
test_expect_success 'sendemail.cc works' '
876+
git config --replace-all sendemail.cc "Somebody <[email protected]>" &&
877+
git send-email \
878+
--dry-run \
879+
--from="Example <[email protected]>" \
880+
881+
$patches $patches >stdout &&
882+
grep "Cc: Somebody <[email protected]>" stdout
883+
'
884+
885+
test_expect_success '--no-cc overrides sendemail.cc' '
886+
git send-email \
887+
--dry-run \
888+
--from="Example <[email protected]>" \
889+
--no-cc \
890+
891+
892+
$patches $patches >stdout &&
893+
grep "Cc: [email protected]" stdout &&
894+
! grep "Cc: Somebody <[email protected]>" stdout
895+
'
896+
897+
test_expect_success 'sendemail.bcc works' '
898+
git config --replace-all sendemail.bcc "Other <[email protected]>" &&
899+
git send-email \
900+
--dry-run \
901+
--from="Example <[email protected]>" \
902+
903+
--smtp-server relay.example.com \
904+
$patches $patches >stdout &&
905+
grep "RCPT TO:<[email protected]>" stdout
906+
'
907+
908+
test_expect_success '--no-bcc overrides sendemail.bcc' '
909+
git send-email \
910+
--dry-run \
911+
--from="Example <[email protected]>" \
912+
--no-bcc \
913+
914+
915+
--smtp-server relay.example.com \
916+
$patches $patches >stdout &&
917+
grep "RCPT TO:<[email protected]>" stdout &&
918+
! grep "RCPT TO:<[email protected]>" stdout
919+
'
920+
855921
test_done

0 commit comments

Comments
 (0)