Merge branch 'js/send-email'
* js/send-email: send-email: add --confirm option and configuration setting send-email: don't create temporary compose file until it is needed send-email: --suppress-cc improvements send-email: handle multiple Cc addresses when reading mbox message send-email: allow send-email to run outside a repo
This commit is contained in:
		@ -177,14 +177,25 @@ Automating
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
--suppress-cc::
 | 
					--suppress-cc::
 | 
				
			||||||
	Specify an additional category of recipients to suppress the
 | 
						Specify an additional category of recipients to suppress the
 | 
				
			||||||
	auto-cc of.  'self' will avoid including the sender, 'author' will
 | 
						auto-cc of:
 | 
				
			||||||
	avoid including the patch author, 'cc' will avoid including anyone
 | 
					+
 | 
				
			||||||
	mentioned in Cc lines in the patch, 'sob' will avoid including
 | 
					--
 | 
				
			||||||
	anyone mentioned in Signed-off-by lines, and 'cccmd' will avoid
 | 
					- 'author' will avoid including the patch author
 | 
				
			||||||
	running the --cc-cmd.  'all' will suppress all auto cc values.
 | 
					- 'self' will avoid including the sender
 | 
				
			||||||
	Default is the value of 'sendemail.suppresscc' configuration value;
 | 
					- 'cc' will avoid including anyone mentioned in Cc lines in the patch header
 | 
				
			||||||
	if that is unspecified, default to 'self' if --suppress-from is
 | 
					  except for self (use 'self' for that).
 | 
				
			||||||
	specified, as well as 'sob' if --no-signed-off-cc is specified.
 | 
					- 'ccbody' will avoid including anyone mentioned in Cc lines in the
 | 
				
			||||||
 | 
					  patch body (commit message) except for self (use 'self' for that).
 | 
				
			||||||
 | 
					- 'sob' will avoid including anyone mentioned in Signed-off-by lines except
 | 
				
			||||||
 | 
					   for self (use 'self' for that).
 | 
				
			||||||
 | 
					- 'cccmd' will avoid running the --cc-cmd.
 | 
				
			||||||
 | 
					- 'body' is equivalent to 'sob' + 'ccbody'
 | 
				
			||||||
 | 
					- 'all' will suppress all auto cc values.
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					Default is the value of 'sendemail.suppresscc' configuration value; if
 | 
				
			||||||
 | 
					that is unspecified, default to 'self' if --suppress-from is
 | 
				
			||||||
 | 
					specified, as well as 'body' if --no-signed-off-cc is specified.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
--[no-]suppress-from::
 | 
					--[no-]suppress-from::
 | 
				
			||||||
	If this is set, do not add the From: address to the cc: list.
 | 
						If this is set, do not add the From: address to the cc: list.
 | 
				
			||||||
@ -201,6 +212,22 @@ Automating
 | 
				
			|||||||
Administering
 | 
					Administering
 | 
				
			||||||
~~~~~~~~~~~~~
 | 
					~~~~~~~~~~~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--confirm::
 | 
				
			||||||
 | 
						Confirm just before sending:
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					- 'always' will always confirm before sending
 | 
				
			||||||
 | 
					- 'never' will never confirm before sending
 | 
				
			||||||
 | 
					- 'cc' will confirm before sending when send-email has automatically
 | 
				
			||||||
 | 
					  added addresses from the patch to the Cc list
 | 
				
			||||||
 | 
					- 'compose' will confirm before sending the first message when using --compose.
 | 
				
			||||||
 | 
					- 'auto' is equivalent to 'cc' + 'compose'
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					Default is the value of 'sendemail.confirm' configuration value; if that
 | 
				
			||||||
 | 
					is unspecified, default to 'auto' unless any of the suppress options
 | 
				
			||||||
 | 
					have been specified, in which case default to 'compose'.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
--dry-run::
 | 
					--dry-run::
 | 
				
			||||||
	Do everything except actually send the emails.
 | 
						Do everything except actually send the emails.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -244,6 +271,11 @@ sendemail.multiedit::
 | 
				
			|||||||
	summary when '--compose' is used). If false, files will be edited one
 | 
						summary when '--compose' is used). If false, files will be edited one
 | 
				
			||||||
	after the other, spawning a new editor each time.
 | 
						after the other, spawning a new editor each time.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sendemail.confirm::
 | 
				
			||||||
 | 
						Sets the default for whether to confirm before sending. Must be
 | 
				
			||||||
 | 
						one of 'always', 'never', 'cc', 'compose', or 'auto'. See '--confirm'
 | 
				
			||||||
 | 
						in the previous section for the meaning of these values.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Author
 | 
					Author
 | 
				
			||||||
------
 | 
					------
 | 
				
			||||||
 | 
				
			|||||||
@ -23,7 +23,7 @@ use Getopt::Long;
 | 
				
			|||||||
use Text::ParseWords;
 | 
					use Text::ParseWords;
 | 
				
			||||||
use Data::Dumper;
 | 
					use Data::Dumper;
 | 
				
			||||||
use Term::ANSIColor;
 | 
					use Term::ANSIColor;
 | 
				
			||||||
use File::Temp qw/ tempdir /;
 | 
					use File::Temp qw/ tempdir tempfile /;
 | 
				
			||||||
use Error qw(:try);
 | 
					use Error qw(:try);
 | 
				
			||||||
use Git;
 | 
					use Git;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -68,14 +68,15 @@ git send-email [options] <file | directory | rev-list options >
 | 
				
			|||||||
  Automating:
 | 
					  Automating:
 | 
				
			||||||
    --identity              <str>  * Use the sendemail.<id> options.
 | 
					    --identity              <str>  * Use the sendemail.<id> options.
 | 
				
			||||||
    --cc-cmd                <str>  * Email Cc: via `<str> \$patch_path`
 | 
					    --cc-cmd                <str>  * Email Cc: via `<str> \$patch_path`
 | 
				
			||||||
    --suppress-cc           <str>  * author, self, sob, cccmd, all.
 | 
					    --suppress-cc           <str>  * author, self, sob, cc, cccmd, body, bodycc, all.
 | 
				
			||||||
    --[no-]signed-off-by-cc        * Send to Cc: and Signed-off-by:
 | 
					    --[no-]signed-off-by-cc        * Send to Signed-off-by: addresses. Default on.
 | 
				
			||||||
                                     addresses. Default on.
 | 
					 | 
				
			||||||
    --[no-]suppress-from           * Send to self. Default off.
 | 
					    --[no-]suppress-from           * Send to self. Default off.
 | 
				
			||||||
    --[no-]chain-reply-to          * Chain In-Reply-To: fields. Default on.
 | 
					    --[no-]chain-reply-to          * Chain In-Reply-To: fields. Default on.
 | 
				
			||||||
    --[no-]thread                  * Use In-Reply-To: field. Default on.
 | 
					    --[no-]thread                  * Use In-Reply-To: field. Default on.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Administering:
 | 
					  Administering:
 | 
				
			||||||
 | 
					    --confirm               <str>  * Confirm recipients before sending;
 | 
				
			||||||
 | 
					                                     auto, cc, compose, always, or never.
 | 
				
			||||||
    --quiet                        * Output one line of info per email.
 | 
					    --quiet                        * Output one line of info per email.
 | 
				
			||||||
    --dry-run                      * Don't actually send the emails.
 | 
					    --dry-run                      * Don't actually send the emails.
 | 
				
			||||||
    --[no-]validate                * Perform patch sanity checks. Default on.
 | 
					    --[no-]validate                * Perform patch sanity checks. Default on.
 | 
				
			||||||
@ -126,6 +127,7 @@ sub format_2822_time {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
my $have_email_valid = eval { require Email::Valid; 1 };
 | 
					my $have_email_valid = eval { require Email::Valid; 1 };
 | 
				
			||||||
 | 
					my $have_mail_address = eval { require Mail::Address; 1 };
 | 
				
			||||||
my $smtp;
 | 
					my $smtp;
 | 
				
			||||||
my $auth;
 | 
					my $auth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -156,7 +158,7 @@ if ($@) {
 | 
				
			|||||||
# Behavior modification variables
 | 
					# Behavior modification variables
 | 
				
			||||||
my ($quiet, $dry_run) = (0, 0);
 | 
					my ($quiet, $dry_run) = (0, 0);
 | 
				
			||||||
my $format_patch;
 | 
					my $format_patch;
 | 
				
			||||||
my $compose_filename = $repo->repo_path() . "/.gitsendemail.msg.$$";
 | 
					my $compose_filename;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Handle interactive edition of files.
 | 
					# Handle interactive edition of files.
 | 
				
			||||||
my $multiedit;
 | 
					my $multiedit;
 | 
				
			||||||
@ -181,7 +183,7 @@ sub do_edit {
 | 
				
			|||||||
my ($thread, $chain_reply_to, $suppress_from, $signed_off_by_cc, $cc_cmd);
 | 
					my ($thread, $chain_reply_to, $suppress_from, $signed_off_by_cc, $cc_cmd);
 | 
				
			||||||
my ($smtp_server, $smtp_server_port, $smtp_authuser, $smtp_encryption);
 | 
					my ($smtp_server, $smtp_server_port, $smtp_authuser, $smtp_encryption);
 | 
				
			||||||
my ($identity, $aliasfiletype, @alias_files, @smtp_host_parts);
 | 
					my ($identity, $aliasfiletype, @alias_files, @smtp_host_parts);
 | 
				
			||||||
my ($validate);
 | 
					my ($validate, $confirm);
 | 
				
			||||||
my (@suppress_cc);
 | 
					my (@suppress_cc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
my %config_bool_settings = (
 | 
					my %config_bool_settings = (
 | 
				
			||||||
@ -207,6 +209,7 @@ my %config_settings = (
 | 
				
			|||||||
    "suppresscc" => \@suppress_cc,
 | 
					    "suppresscc" => \@suppress_cc,
 | 
				
			||||||
    "envelopesender" => \$envelope_sender,
 | 
					    "envelopesender" => \$envelope_sender,
 | 
				
			||||||
    "multiedit" => \$multiedit,
 | 
					    "multiedit" => \$multiedit,
 | 
				
			||||||
 | 
					    "confirm"   => \$confirm,
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Handle Uncouth Termination
 | 
					# Handle Uncouth Termination
 | 
				
			||||||
@ -219,11 +222,13 @@ sub signal_handler {
 | 
				
			|||||||
	system "stty echo";
 | 
						system "stty echo";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# tmp files from --compose
 | 
						# tmp files from --compose
 | 
				
			||||||
	if (-e $compose_filename) {
 | 
						if (defined $compose_filename) {
 | 
				
			||||||
		print "'$compose_filename' contains an intermediate version of the email you were composing.\n";
 | 
							if (-e $compose_filename) {
 | 
				
			||||||
	}
 | 
								print "'$compose_filename' contains an intermediate version of the email you were composing.\n";
 | 
				
			||||||
	if (-e ($compose_filename . ".final")) {
 | 
							}
 | 
				
			||||||
		print "'$compose_filename.final' contains the composed email.\n"
 | 
							if (-e ($compose_filename . ".final")) {
 | 
				
			||||||
 | 
								print "'$compose_filename.final' contains the composed email.\n"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	exit;
 | 
						exit;
 | 
				
			||||||
@ -256,6 +261,7 @@ my $rc = GetOptions("sender|from=s" => \$sender,
 | 
				
			|||||||
		    "suppress-from!" => \$suppress_from,
 | 
							    "suppress-from!" => \$suppress_from,
 | 
				
			||||||
		    "suppress-cc=s" => \@suppress_cc,
 | 
							    "suppress-cc=s" => \@suppress_cc,
 | 
				
			||||||
		    "signed-off-cc|signed-off-by-cc!" => \$signed_off_by_cc,
 | 
							    "signed-off-cc|signed-off-by-cc!" => \$signed_off_by_cc,
 | 
				
			||||||
 | 
							    "confirm=s" => \$confirm,
 | 
				
			||||||
		    "dry-run" => \$dry_run,
 | 
							    "dry-run" => \$dry_run,
 | 
				
			||||||
		    "envelope-sender=s" => \$envelope_sender,
 | 
							    "envelope-sender=s" => \$envelope_sender,
 | 
				
			||||||
		    "thread!" => \$thread,
 | 
							    "thread!" => \$thread,
 | 
				
			||||||
@ -267,6 +273,9 @@ unless ($rc) {
 | 
				
			|||||||
    usage();
 | 
					    usage();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					die "Cannot run git format-patch from outside a repository\n"
 | 
				
			||||||
 | 
						if $format_patch and not $repo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Now, let's fill any that aren't set in with defaults:
 | 
					# Now, let's fill any that aren't set in with defaults:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub read_config {
 | 
					sub read_config {
 | 
				
			||||||
@ -318,13 +327,13 @@ my(%suppress_cc);
 | 
				
			|||||||
if (@suppress_cc) {
 | 
					if (@suppress_cc) {
 | 
				
			||||||
	foreach my $entry (@suppress_cc) {
 | 
						foreach my $entry (@suppress_cc) {
 | 
				
			||||||
		die "Unknown --suppress-cc field: '$entry'\n"
 | 
							die "Unknown --suppress-cc field: '$entry'\n"
 | 
				
			||||||
			unless $entry =~ /^(all|cccmd|cc|author|self|sob)$/;
 | 
								unless $entry =~ /^(all|cccmd|cc|author|self|sob|body|bodycc)$/;
 | 
				
			||||||
		$suppress_cc{$entry} = 1;
 | 
							$suppress_cc{$entry} = 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if ($suppress_cc{'all'}) {
 | 
					if ($suppress_cc{'all'}) {
 | 
				
			||||||
	foreach my $entry (qw (ccmd cc author self sob)) {
 | 
						foreach my $entry (qw (ccmd cc author self sob body bodycc)) {
 | 
				
			||||||
		$suppress_cc{$entry} = 1;
 | 
							$suppress_cc{$entry} = 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	delete $suppress_cc{'all'};
 | 
						delete $suppress_cc{'all'};
 | 
				
			||||||
@ -334,6 +343,21 @@ if ($suppress_cc{'all'}) {
 | 
				
			|||||||
$suppress_cc{'self'} = $suppress_from if defined $suppress_from;
 | 
					$suppress_cc{'self'} = $suppress_from if defined $suppress_from;
 | 
				
			||||||
$suppress_cc{'sob'} = !$signed_off_by_cc if defined $signed_off_by_cc;
 | 
					$suppress_cc{'sob'} = !$signed_off_by_cc if defined $signed_off_by_cc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if ($suppress_cc{'body'}) {
 | 
				
			||||||
 | 
						foreach my $entry (qw (sob bodycc)) {
 | 
				
			||||||
 | 
							$suppress_cc{$entry} = 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						delete $suppress_cc{'body'};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Set confirm's default value
 | 
				
			||||||
 | 
					my $confirm_unconfigured = !defined $confirm;
 | 
				
			||||||
 | 
					if ($confirm_unconfigured) {
 | 
				
			||||||
 | 
						$confirm = scalar %suppress_cc ? 'compose' : 'auto';
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					die "Unknown --confirm setting: '$confirm'\n"
 | 
				
			||||||
 | 
						unless $confirm =~ /^(?:auto|cc|compose|always|never)/;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Debugging, print out the suppressions.
 | 
					# Debugging, print out the suppressions.
 | 
				
			||||||
if (0) {
 | 
					if (0) {
 | 
				
			||||||
	print "suppressions:\n";
 | 
						print "suppressions:\n";
 | 
				
			||||||
@ -360,6 +384,14 @@ foreach my $entry (@bcclist) {
 | 
				
			|||||||
	die "Comma in --bcclist entry: $entry'\n" unless $entry !~ m/,/;
 | 
						die "Comma in --bcclist entry: $entry'\n" unless $entry !~ m/,/;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub parse_address_line {
 | 
				
			||||||
 | 
						if ($have_mail_address) {
 | 
				
			||||||
 | 
							return map { $_->format } Mail::Address->parse($_[0]);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							return split_addrs($_[0]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub split_addrs {
 | 
					sub split_addrs {
 | 
				
			||||||
	return quotewords('\s*,\s*', 1, @_);
 | 
						return quotewords('\s*,\s*', 1, @_);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -404,6 +436,7 @@ if (@alias_files and $aliasfiletype and defined $parse_alias{$aliasfiletype}) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# returns 1 if the conflict must be solved using it as a format-patch argument
 | 
					# returns 1 if the conflict must be solved using it as a format-patch argument
 | 
				
			||||||
sub check_file_rev_conflict($) {
 | 
					sub check_file_rev_conflict($) {
 | 
				
			||||||
 | 
						return unless $repo;
 | 
				
			||||||
	my $f = shift;
 | 
						my $f = shift;
 | 
				
			||||||
	try {
 | 
						try {
 | 
				
			||||||
		$repo->command('rev-parse', '--verify', '--quiet', $f);
 | 
							$repo->command('rev-parse', '--verify', '--quiet', $f);
 | 
				
			||||||
@ -445,6 +478,8 @@ while (defined(my $f = shift @ARGV)) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (@rev_list_opts) {
 | 
					if (@rev_list_opts) {
 | 
				
			||||||
 | 
						die "Cannot run git format-patch from outside a repository\n"
 | 
				
			||||||
 | 
							unless $repo;
 | 
				
			||||||
	push @files, $repo->command('format-patch', '-o', tempdir(CLEANUP => 1), @rev_list_opts);
 | 
						push @files, $repo->command('format-patch', '-o', tempdir(CLEANUP => 1), @rev_list_opts);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -481,6 +516,9 @@ sub get_patch_subject($) {
 | 
				
			|||||||
if ($compose) {
 | 
					if ($compose) {
 | 
				
			||||||
	# Note that this does not need to be secure, but we will make a small
 | 
						# Note that this does not need to be secure, but we will make a small
 | 
				
			||||||
	# effort to have it be unique
 | 
						# effort to have it be unique
 | 
				
			||||||
 | 
						$compose_filename = ($repo ?
 | 
				
			||||||
 | 
							tempfile(".gitsendemail.msg.XXXXXX", DIR => $repo->repo_path()) :
 | 
				
			||||||
 | 
							tempfile(".gitsendemail.msg.XXXXXX", DIR => "."))[1];
 | 
				
			||||||
	open(C,">",$compose_filename)
 | 
						open(C,">",$compose_filename)
 | 
				
			||||||
		or die "Failed to open for writing $compose_filename: $!";
 | 
							or die "Failed to open for writing $compose_filename: $!";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -593,7 +631,7 @@ if (!@to) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	my $to = $_;
 | 
						my $to = $_;
 | 
				
			||||||
	push @to, split_addrs($to);
 | 
						push @to, parse_address_line($to);
 | 
				
			||||||
	$prompting++;
 | 
						$prompting++;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -637,25 +675,13 @@ if (!defined $smtp_server) {
 | 
				
			|||||||
	$smtp_server ||= 'localhost'; # could be 127.0.0.1, too... *shrug*
 | 
						$smtp_server ||= 'localhost'; # could be 127.0.0.1, too... *shrug*
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if ($compose) {
 | 
					if ($compose && $compose > 0) {
 | 
				
			||||||
	while (1) {
 | 
						@files = ($compose_filename . ".final", @files);
 | 
				
			||||||
		$_ = $term->readline("Send this email? (y|n) ");
 | 
					 | 
				
			||||||
		last if defined $_;
 | 
					 | 
				
			||||||
		print "\n";
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (uc substr($_,0,1) ne 'Y') {
 | 
					 | 
				
			||||||
		cleanup_compose_files();
 | 
					 | 
				
			||||||
		exit(0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ($compose > 0) {
 | 
					 | 
				
			||||||
		@files = ($compose_filename . ".final", @files);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Variables we set as part of the loop over files
 | 
					# Variables we set as part of the loop over files
 | 
				
			||||||
our ($message_id, %mail, $subject, $reply_to, $references, $message);
 | 
					our ($message_id, %mail, $subject, $reply_to, $references, $message,
 | 
				
			||||||
 | 
						$needs_confirm, $message_num);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub extract_valid_address {
 | 
					sub extract_valid_address {
 | 
				
			||||||
	my $address = shift;
 | 
						my $address = shift;
 | 
				
			||||||
@ -811,6 +837,37 @@ X-Mailer: git-send-email $gitversion
 | 
				
			|||||||
	unshift (@sendmail_parameters,
 | 
						unshift (@sendmail_parameters,
 | 
				
			||||||
			'-f', $raw_from) if(defined $envelope_sender);
 | 
								'-f', $raw_from) if(defined $envelope_sender);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ($needs_confirm && !$dry_run) {
 | 
				
			||||||
 | 
							print "\n$header\n";
 | 
				
			||||||
 | 
							if ($needs_confirm eq "inform") {
 | 
				
			||||||
 | 
								$confirm_unconfigured = 0; # squelch this message for the rest of this run
 | 
				
			||||||
 | 
								print "    The Cc list above has been expanded by additional\n";
 | 
				
			||||||
 | 
								print "    addresses found in the patch commit message. By default\n";
 | 
				
			||||||
 | 
								print "    send-email prompts before sending whenever this occurs.\n";
 | 
				
			||||||
 | 
								print "    This behavior is controlled by the sendemail.confirm\n";
 | 
				
			||||||
 | 
								print "    configuration setting.\n";
 | 
				
			||||||
 | 
								print "\n";
 | 
				
			||||||
 | 
								print "    For additional information, run 'git send-email --help'.\n";
 | 
				
			||||||
 | 
								print "    To retain the current behavior, but squelch this message,\n";
 | 
				
			||||||
 | 
								print "    run 'git config --global sendemail.confirm auto'.\n\n";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							while (1) {
 | 
				
			||||||
 | 
								chomp ($_ = $term->readline(
 | 
				
			||||||
 | 
									"Send this email? ([y]es|[n]o|[q]uit|[a]ll): "
 | 
				
			||||||
 | 
								));
 | 
				
			||||||
 | 
								last if /^(?:yes|y|no|n|quit|q|all|a)/i;
 | 
				
			||||||
 | 
								print "\n";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (/^n/i) {
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							} elsif (/^q/i) {
 | 
				
			||||||
 | 
								cleanup_compose_files();
 | 
				
			||||||
 | 
								exit(0);
 | 
				
			||||||
 | 
							} elsif (/^a/i) {
 | 
				
			||||||
 | 
								$confirm = 'never';
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ($dry_run) {
 | 
						if ($dry_run) {
 | 
				
			||||||
		# We don't want to send the email.
 | 
							# We don't want to send the email.
 | 
				
			||||||
	} elsif ($smtp_server =~ m#^/#) {
 | 
						} elsif ($smtp_server =~ m#^/#) {
 | 
				
			||||||
@ -909,6 +966,7 @@ X-Mailer: git-send-email $gitversion
 | 
				
			|||||||
$reply_to = $initial_reply_to;
 | 
					$reply_to = $initial_reply_to;
 | 
				
			||||||
$references = $initial_reply_to || '';
 | 
					$references = $initial_reply_to || '';
 | 
				
			||||||
$subject = $initial_subject;
 | 
					$subject = $initial_subject;
 | 
				
			||||||
 | 
					$message_num = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
foreach my $t (@files) {
 | 
					foreach my $t (@files) {
 | 
				
			||||||
	open(F,"<",$t) or die "can't open file $t";
 | 
						open(F,"<",$t) or die "can't open file $t";
 | 
				
			||||||
@ -917,91 +975,106 @@ foreach my $t (@files) {
 | 
				
			|||||||
	my $author_encoding;
 | 
						my $author_encoding;
 | 
				
			||||||
	my $has_content_type;
 | 
						my $has_content_type;
 | 
				
			||||||
	my $body_encoding;
 | 
						my $body_encoding;
 | 
				
			||||||
	@cc = @initial_cc;
 | 
						@cc = ();
 | 
				
			||||||
	@xh = ();
 | 
						@xh = ();
 | 
				
			||||||
	my $input_format = undef;
 | 
						my $input_format = undef;
 | 
				
			||||||
	my $header_done = 0;
 | 
						my @header = ();
 | 
				
			||||||
	$message = "";
 | 
						$message = "";
 | 
				
			||||||
 | 
						$message_num++;
 | 
				
			||||||
 | 
						# First unfold multiline header fields
 | 
				
			||||||
	while(<F>) {
 | 
						while(<F>) {
 | 
				
			||||||
		if (!$header_done) {
 | 
							last if /^\s*$/;
 | 
				
			||||||
			if (/^From /) {
 | 
							if (/^\s+\S/ and @header) {
 | 
				
			||||||
				$input_format = 'mbox';
 | 
								chomp($header[$#header]);
 | 
				
			||||||
				next;
 | 
								s/^\s+/ /;
 | 
				
			||||||
			}
 | 
								$header[$#header] .= $_;
 | 
				
			||||||
			chomp;
 | 
						    } else {
 | 
				
			||||||
			if (!defined $input_format && /^[-A-Za-z]+:\s/) {
 | 
								push(@header, $_);
 | 
				
			||||||
				$input_format = 'mbox';
 | 
							}
 | 
				
			||||||
			}
 | 
						}
 | 
				
			||||||
 | 
						# Now parse the header
 | 
				
			||||||
 | 
						foreach(@header) {
 | 
				
			||||||
 | 
							if (/^From /) {
 | 
				
			||||||
 | 
								$input_format = 'mbox';
 | 
				
			||||||
 | 
								next;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							chomp;
 | 
				
			||||||
 | 
							if (!defined $input_format && /^[-A-Za-z]+:\s/) {
 | 
				
			||||||
 | 
								$input_format = 'mbox';
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (defined $input_format && $input_format eq 'mbox') {
 | 
							if (defined $input_format && $input_format eq 'mbox') {
 | 
				
			||||||
				if (/^Subject:\s+(.*)$/) {
 | 
								if (/^Subject:\s+(.*)$/) {
 | 
				
			||||||
					$subject = $1;
 | 
									$subject = $1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
				} elsif (/^(Cc|From):\s+(.*)$/) {
 | 
								elsif (/^From:\s+(.*)$/) {
 | 
				
			||||||
					if (unquote_rfc2047($2) eq $sender) {
 | 
									($author, $author_encoding) = unquote_rfc2047($1);
 | 
				
			||||||
 | 
									next if $suppress_cc{'author'};
 | 
				
			||||||
 | 
									next if $suppress_cc{'self'} and $author eq $sender;
 | 
				
			||||||
 | 
									printf("(mbox) Adding cc: %s from line '%s'\n",
 | 
				
			||||||
 | 
										$1, $_) unless $quiet;
 | 
				
			||||||
 | 
									push @cc, $1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								elsif (/^Cc:\s+(.*)$/) {
 | 
				
			||||||
 | 
									foreach my $addr (parse_address_line($1)) {
 | 
				
			||||||
 | 
										if (unquote_rfc2047($addr) eq $sender) {
 | 
				
			||||||
						next if ($suppress_cc{'self'});
 | 
											next if ($suppress_cc{'self'});
 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					elsif ($1 eq 'From') {
 | 
					 | 
				
			||||||
						($author, $author_encoding)
 | 
					 | 
				
			||||||
						  = unquote_rfc2047($2);
 | 
					 | 
				
			||||||
						next if ($suppress_cc{'author'});
 | 
					 | 
				
			||||||
					} else {
 | 
										} else {
 | 
				
			||||||
						next if ($suppress_cc{'cc'});
 | 
											next if ($suppress_cc{'cc'});
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					printf("(mbox) Adding cc: %s from line '%s'\n",
 | 
										printf("(mbox) Adding cc: %s from line '%s'\n",
 | 
				
			||||||
						$2, $_) unless $quiet;
 | 
											$addr, $_) unless $quiet;
 | 
				
			||||||
					push @cc, $2;
 | 
										push @cc, $addr;
 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				elsif (/^Content-type:/i) {
 | 
					 | 
				
			||||||
					$has_content_type = 1;
 | 
					 | 
				
			||||||
					if (/charset="?([^ "]+)/) {
 | 
					 | 
				
			||||||
						$body_encoding = $1;
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					push @xh, $_;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				elsif (/^Message-Id: (.*)/i) {
 | 
					 | 
				
			||||||
					$message_id = $1;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				elsif (!/^Date:\s/ && /^[-A-Za-z]+:\s+\S/) {
 | 
					 | 
				
			||||||
					push @xh, $_;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				# In the traditional
 | 
					 | 
				
			||||||
				# "send lots of email" format,
 | 
					 | 
				
			||||||
				# line 1 = cc
 | 
					 | 
				
			||||||
				# line 2 = subject
 | 
					 | 
				
			||||||
				# So let's support that, too.
 | 
					 | 
				
			||||||
				$input_format = 'lots';
 | 
					 | 
				
			||||||
				if (@cc == 0 && !$suppress_cc{'cc'}) {
 | 
					 | 
				
			||||||
					printf("(non-mbox) Adding cc: %s from line '%s'\n",
 | 
					 | 
				
			||||||
						$_, $_) unless $quiet;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					push @cc, $_;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				} elsif (!defined $subject) {
 | 
					 | 
				
			||||||
					$subject = $_;
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								elsif (/^Content-type:/i) {
 | 
				
			||||||
			# A whitespace line will terminate the headers
 | 
									$has_content_type = 1;
 | 
				
			||||||
			if (m/^\s*$/) {
 | 
									if (/charset="?([^ "]+)/) {
 | 
				
			||||||
				$header_done = 1;
 | 
										$body_encoding = $1;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									push @xh, $_;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								elsif (/^Message-Id: (.*)/i) {
 | 
				
			||||||
 | 
									$message_id = $1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								elsif (!/^Date:\s/ && /^[-A-Za-z]+:\s+\S/) {
 | 
				
			||||||
 | 
									push @xh, $_;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			$message .=  $_;
 | 
								# In the traditional
 | 
				
			||||||
			if (/^(Signed-off-by|Cc): (.*)$/i) {
 | 
								# "send lots of email" format,
 | 
				
			||||||
				next if ($suppress_cc{'sob'});
 | 
								# line 1 = cc
 | 
				
			||||||
				chomp;
 | 
								# line 2 = subject
 | 
				
			||||||
				my $c = $2;
 | 
								# So let's support that, too.
 | 
				
			||||||
				chomp $c;
 | 
								$input_format = 'lots';
 | 
				
			||||||
				next if ($c eq $sender and $suppress_cc{'self'});
 | 
								if (@cc == 0 && !$suppress_cc{'cc'}) {
 | 
				
			||||||
				push @cc, $c;
 | 
									printf("(non-mbox) Adding cc: %s from line '%s'\n",
 | 
				
			||||||
				printf("(sob) Adding cc: %s from line '%s'\n",
 | 
										$_, $_) unless $quiet;
 | 
				
			||||||
					$c, $_) unless $quiet;
 | 
									push @cc, $_;
 | 
				
			||||||
 | 
								} elsif (!defined $subject) {
 | 
				
			||||||
 | 
									$subject = $_;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						# Now parse the message body
 | 
				
			||||||
 | 
						while(<F>) {
 | 
				
			||||||
 | 
							$message .=  $_;
 | 
				
			||||||
 | 
							if (/^(Signed-off-by|Cc): (.*)$/i) {
 | 
				
			||||||
 | 
								chomp;
 | 
				
			||||||
 | 
								my ($what, $c) = ($1, $2);
 | 
				
			||||||
 | 
								chomp $c;
 | 
				
			||||||
 | 
								if ($c eq $sender) {
 | 
				
			||||||
 | 
									next if ($suppress_cc{'self'});
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									next if $suppress_cc{'sob'} and $what =~ /Signed-off-by/i;
 | 
				
			||||||
 | 
									next if $suppress_cc{'bodycc'} and $what =~ /Cc/i;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								push @cc, $c;
 | 
				
			||||||
 | 
								printf("(body) Adding cc: %s from line '%s'\n",
 | 
				
			||||||
 | 
									$c, $_) unless $quiet;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	close F;
 | 
						close F;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (defined $cc_cmd && !$suppress_cc{'cccmd'}) {
 | 
						if (defined $cc_cmd && !$suppress_cc{'cccmd'}) {
 | 
				
			||||||
@ -1020,7 +1093,7 @@ foreach my $t (@files) {
 | 
				
			|||||||
			or die "(cc-cmd) failed to close pipe to '$cc_cmd'";
 | 
								or die "(cc-cmd) failed to close pipe to '$cc_cmd'";
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (defined $author) {
 | 
						if (defined $author and $author ne $sender) {
 | 
				
			||||||
		$message = "From: $author\n\n$message";
 | 
							$message = "From: $author\n\n$message";
 | 
				
			||||||
		if (defined $author_encoding) {
 | 
							if (defined $author_encoding) {
 | 
				
			||||||
			if ($has_content_type) {
 | 
								if ($has_content_type) {
 | 
				
			||||||
@ -1040,6 +1113,14 @@ foreach my $t (@files) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						$needs_confirm = (
 | 
				
			||||||
 | 
							$confirm eq "always" or
 | 
				
			||||||
 | 
							($confirm =~ /^(?:auto|cc)$/ && @cc) or
 | 
				
			||||||
 | 
							($confirm =~ /^(?:auto|compose)$/ && $compose && $message_num == 1));
 | 
				
			||||||
 | 
						$needs_confirm = "inform" if ($needs_confirm && $confirm_unconfigured && @cc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@cc = (@initial_cc, @cc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	send_message();
 | 
						send_message();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# set up for the next message
 | 
						# set up for the next message
 | 
				
			||||||
@ -1054,13 +1135,10 @@ foreach my $t (@files) {
 | 
				
			|||||||
	$message_id = undef;
 | 
						$message_id = undef;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if ($compose) {
 | 
					cleanup_compose_files();
 | 
				
			||||||
	cleanup_compose_files();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub cleanup_compose_files() {
 | 
					sub cleanup_compose_files() {
 | 
				
			||||||
	unlink($compose_filename, $compose_filename . ".final");
 | 
						unlink($compose_filename, $compose_filename . ".final") if $compose;
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$smtp->quit if $smtp;
 | 
					$smtp->quit if $smtp;
 | 
				
			||||||
 | 
				
			|||||||
@ -32,16 +32,59 @@ clean_fake_sendmail() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test_expect_success 'Extract patches' '
 | 
					test_expect_success 'Extract patches' '
 | 
				
			||||||
    patches=`git format-patch -n HEAD^1`
 | 
					    patches=`git format-patch -s --cc="One <one@example.com>" --cc=two@example.com -n HEAD^1`
 | 
				
			||||||
'
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Test no confirm early to ensure remaining tests will not hang
 | 
				
			||||||
 | 
					test_no_confirm () {
 | 
				
			||||||
 | 
						rm -f no_confirm_okay
 | 
				
			||||||
 | 
						echo n | \
 | 
				
			||||||
 | 
							GIT_SEND_EMAIL_NOTTY=1 \
 | 
				
			||||||
 | 
							git send-email \
 | 
				
			||||||
 | 
							--from="Example <from@example.com>" \
 | 
				
			||||||
 | 
							--to=nobody@example.com \
 | 
				
			||||||
 | 
							--smtp-server="$(pwd)/fake.sendmail" \
 | 
				
			||||||
 | 
							$@ \
 | 
				
			||||||
 | 
							$patches > stdout &&
 | 
				
			||||||
 | 
							test_must_fail grep "Send this email" stdout &&
 | 
				
			||||||
 | 
							> no_confirm_okay
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Exit immediately to prevent hang if a no-confirm test fails
 | 
				
			||||||
 | 
					check_no_confirm () {
 | 
				
			||||||
 | 
						test -f no_confirm_okay || {
 | 
				
			||||||
 | 
							say 'No confirm test failed; skipping remaining tests to prevent hanging'
 | 
				
			||||||
 | 
							test_done
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_expect_success 'No confirm with --suppress-cc' '
 | 
				
			||||||
 | 
						test_no_confirm --suppress-cc=sob
 | 
				
			||||||
 | 
					'
 | 
				
			||||||
 | 
					check_no_confirm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_expect_success 'No confirm with --confirm=never' '
 | 
				
			||||||
 | 
						test_no_confirm --confirm=never
 | 
				
			||||||
 | 
					'
 | 
				
			||||||
 | 
					check_no_confirm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# leave sendemail.confirm set to never after this so that none of the
 | 
				
			||||||
 | 
					# remaining tests prompt unintentionally.
 | 
				
			||||||
 | 
					test_expect_success 'No confirm with sendemail.confirm=never' '
 | 
				
			||||||
 | 
						git config sendemail.confirm never &&
 | 
				
			||||||
 | 
						test_no_confirm --compose --subject=foo
 | 
				
			||||||
 | 
					'
 | 
				
			||||||
 | 
					check_no_confirm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test_expect_success 'Send patches' '
 | 
					test_expect_success 'Send patches' '
 | 
				
			||||||
     git send-email --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors
 | 
					     git send-email --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors
 | 
				
			||||||
'
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cat >expected <<\EOF
 | 
					cat >expected <<\EOF
 | 
				
			||||||
!nobody@example.com!
 | 
					!nobody@example.com!
 | 
				
			||||||
!author@example.com!
 | 
					!author@example.com!
 | 
				
			||||||
 | 
					!one@example.com!
 | 
				
			||||||
 | 
					!two@example.com!
 | 
				
			||||||
EOF
 | 
					EOF
 | 
				
			||||||
test_expect_success \
 | 
					test_expect_success \
 | 
				
			||||||
    'Verify commandline' \
 | 
					    'Verify commandline' \
 | 
				
			||||||
@ -50,13 +93,15 @@ test_expect_success \
 | 
				
			|||||||
cat >expected-show-all-headers <<\EOF
 | 
					cat >expected-show-all-headers <<\EOF
 | 
				
			||||||
0001-Second.patch
 | 
					0001-Second.patch
 | 
				
			||||||
(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
 | 
					(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
 | 
				
			||||||
 | 
					(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
 | 
				
			||||||
 | 
					(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
 | 
				
			||||||
Dry-OK. Log says:
 | 
					Dry-OK. Log says:
 | 
				
			||||||
Server: relay.example.com
 | 
					Server: relay.example.com
 | 
				
			||||||
MAIL FROM:<from@example.com>
 | 
					MAIL FROM:<from@example.com>
 | 
				
			||||||
RCPT TO:<to@example.com>,<cc@example.com>,<author@example.com>,<bcc@example.com>
 | 
					RCPT TO:<to@example.com>,<cc@example.com>,<author@example.com>,<one@example.com>,<two@example.com>,<bcc@example.com>
 | 
				
			||||||
From: Example <from@example.com>
 | 
					From: Example <from@example.com>
 | 
				
			||||||
To: to@example.com
 | 
					To: to@example.com
 | 
				
			||||||
Cc: cc@example.com, A <author@example.com>
 | 
					Cc: cc@example.com, A <author@example.com>, One <one@example.com>, two@example.com
 | 
				
			||||||
Subject: [PATCH 1/1] Second.
 | 
					Subject: [PATCH 1/1] Second.
 | 
				
			||||||
Date: DATE-STRING
 | 
					Date: DATE-STRING
 | 
				
			||||||
Message-Id: MESSAGE-ID-STRING
 | 
					Message-Id: MESSAGE-ID-STRING
 | 
				
			||||||
@ -70,6 +115,7 @@ EOF
 | 
				
			|||||||
test_expect_success 'Show all headers' '
 | 
					test_expect_success 'Show all headers' '
 | 
				
			||||||
	git send-email \
 | 
						git send-email \
 | 
				
			||||||
		--dry-run \
 | 
							--dry-run \
 | 
				
			||||||
 | 
							--suppress-cc=sob \
 | 
				
			||||||
		--from="Example <from@example.com>" \
 | 
							--from="Example <from@example.com>" \
 | 
				
			||||||
		--to=to@example.com \
 | 
							--to=to@example.com \
 | 
				
			||||||
		--cc=cc@example.com \
 | 
							--cc=cc@example.com \
 | 
				
			||||||
@ -104,6 +150,28 @@ test_expect_success 'no patch was sent' '
 | 
				
			|||||||
	! test -e commandline1
 | 
						! test -e commandline1
 | 
				
			||||||
'
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_expect_success 'Author From: in message body' '
 | 
				
			||||||
 | 
						clean_fake_sendmail &&
 | 
				
			||||||
 | 
						git send-email \
 | 
				
			||||||
 | 
							--from="Example <nobody@example.com>" \
 | 
				
			||||||
 | 
							--to=nobody@example.com \
 | 
				
			||||||
 | 
							--smtp-server="$(pwd)/fake.sendmail" \
 | 
				
			||||||
 | 
							$patches &&
 | 
				
			||||||
 | 
						sed "1,/^$/d" < msgtxt1 > msgbody1
 | 
				
			||||||
 | 
						grep "From: A <author@example.com>" msgbody1
 | 
				
			||||||
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_expect_success 'Author From: not in message body' '
 | 
				
			||||||
 | 
						clean_fake_sendmail &&
 | 
				
			||||||
 | 
						git send-email \
 | 
				
			||||||
 | 
							--from="A <author@example.com>" \
 | 
				
			||||||
 | 
							--to=nobody@example.com \
 | 
				
			||||||
 | 
							--smtp-server="$(pwd)/fake.sendmail" \
 | 
				
			||||||
 | 
							$patches &&
 | 
				
			||||||
 | 
						sed "1,/^$/d" < msgtxt1 > msgbody1
 | 
				
			||||||
 | 
						! grep "From: A <author@example.com>" msgbody1
 | 
				
			||||||
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test_expect_success 'allow long lines with --no-validate' '
 | 
					test_expect_success 'allow long lines with --no-validate' '
 | 
				
			||||||
	git send-email \
 | 
						git send-email \
 | 
				
			||||||
		--from="Example <nobody@example.com>" \
 | 
							--from="Example <nobody@example.com>" \
 | 
				
			||||||
@ -148,15 +216,13 @@ test_set_editor "$(pwd)/fake-editor"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
test_expect_success '--compose works' '
 | 
					test_expect_success '--compose works' '
 | 
				
			||||||
	clean_fake_sendmail &&
 | 
						clean_fake_sendmail &&
 | 
				
			||||||
	echo y | \
 | 
						git send-email \
 | 
				
			||||||
		GIT_SEND_EMAIL_NOTTY=1 \
 | 
						--compose --subject foo \
 | 
				
			||||||
		git send-email \
 | 
						--from="Example <nobody@example.com>" \
 | 
				
			||||||
		--compose --subject foo \
 | 
						--to=nobody@example.com \
 | 
				
			||||||
		--from="Example <nobody@example.com>" \
 | 
						--smtp-server="$(pwd)/fake.sendmail" \
 | 
				
			||||||
		--to=nobody@example.com \
 | 
						$patches \
 | 
				
			||||||
		--smtp-server="$(pwd)/fake.sendmail" \
 | 
						2>errors
 | 
				
			||||||
		$patches \
 | 
					 | 
				
			||||||
		2>errors
 | 
					 | 
				
			||||||
'
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test_expect_success 'first message is compose text' '
 | 
					test_expect_success 'first message is compose text' '
 | 
				
			||||||
@ -167,16 +233,18 @@ test_expect_success 'second message is patch' '
 | 
				
			|||||||
	grep "Subject:.*Second" msgtxt2
 | 
						grep "Subject:.*Second" msgtxt2
 | 
				
			||||||
'
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cat >expected-show-all-headers <<\EOF
 | 
					cat >expected-suppress-sob <<\EOF
 | 
				
			||||||
0001-Second.patch
 | 
					0001-Second.patch
 | 
				
			||||||
(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
 | 
					(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
 | 
				
			||||||
 | 
					(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
 | 
				
			||||||
 | 
					(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
 | 
				
			||||||
Dry-OK. Log says:
 | 
					Dry-OK. Log says:
 | 
				
			||||||
Server: relay.example.com
 | 
					Server: relay.example.com
 | 
				
			||||||
MAIL FROM:<from@example.com>
 | 
					MAIL FROM:<from@example.com>
 | 
				
			||||||
RCPT TO:<to@example.com>,<cc@example.com>,<author@example.com>
 | 
					RCPT TO:<to@example.com>,<cc@example.com>,<author@example.com>,<one@example.com>,<two@example.com>
 | 
				
			||||||
From: Example <from@example.com>
 | 
					From: Example <from@example.com>
 | 
				
			||||||
To: to@example.com
 | 
					To: to@example.com
 | 
				
			||||||
Cc: cc@example.com, A <author@example.com>
 | 
					Cc: cc@example.com, A <author@example.com>, One <one@example.com>, two@example.com
 | 
				
			||||||
Subject: [PATCH 1/1] Second.
 | 
					Subject: [PATCH 1/1] Second.
 | 
				
			||||||
Date: DATE-STRING
 | 
					Date: DATE-STRING
 | 
				
			||||||
Message-Id: MESSAGE-ID-STRING
 | 
					Message-Id: MESSAGE-ID-STRING
 | 
				
			||||||
@ -185,10 +253,10 @@ X-Mailer: X-MAILER-STRING
 | 
				
			|||||||
Result: OK
 | 
					Result: OK
 | 
				
			||||||
EOF
 | 
					EOF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test_expect_success 'sendemail.cc set' '
 | 
					test_suppression () {
 | 
				
			||||||
	git config sendemail.cc cc@example.com &&
 | 
					 | 
				
			||||||
	git send-email \
 | 
						git send-email \
 | 
				
			||||||
		--dry-run \
 | 
							--dry-run \
 | 
				
			||||||
 | 
							--suppress-cc=$1 \
 | 
				
			||||||
		--from="Example <from@example.com>" \
 | 
							--from="Example <from@example.com>" \
 | 
				
			||||||
		--to=to@example.com \
 | 
							--to=to@example.com \
 | 
				
			||||||
		--smtp-server relay.example.com \
 | 
							--smtp-server relay.example.com \
 | 
				
			||||||
@ -196,20 +264,27 @@ test_expect_success 'sendemail.cc set' '
 | 
				
			|||||||
	sed	-e "s/^\(Date:\).*/\1 DATE-STRING/" \
 | 
						sed	-e "s/^\(Date:\).*/\1 DATE-STRING/" \
 | 
				
			||||||
		-e "s/^\(Message-Id:\).*/\1 MESSAGE-ID-STRING/" \
 | 
							-e "s/^\(Message-Id:\).*/\1 MESSAGE-ID-STRING/" \
 | 
				
			||||||
		-e "s/^\(X-Mailer:\).*/\1 X-MAILER-STRING/" \
 | 
							-e "s/^\(X-Mailer:\).*/\1 X-MAILER-STRING/" \
 | 
				
			||||||
		>actual-show-all-headers &&
 | 
							>actual-suppress-$1 &&
 | 
				
			||||||
	test_cmp expected-show-all-headers actual-show-all-headers
 | 
						test_cmp expected-suppress-$1 actual-suppress-$1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_expect_success 'sendemail.cc set' '
 | 
				
			||||||
 | 
						git config sendemail.cc cc@example.com &&
 | 
				
			||||||
 | 
						test_suppression sob
 | 
				
			||||||
'
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cat >expected-show-all-headers <<\EOF
 | 
					cat >expected-suppress-sob <<\EOF
 | 
				
			||||||
0001-Second.patch
 | 
					0001-Second.patch
 | 
				
			||||||
(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
 | 
					(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
 | 
				
			||||||
 | 
					(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
 | 
				
			||||||
 | 
					(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
 | 
				
			||||||
Dry-OK. Log says:
 | 
					Dry-OK. Log says:
 | 
				
			||||||
Server: relay.example.com
 | 
					Server: relay.example.com
 | 
				
			||||||
MAIL FROM:<from@example.com>
 | 
					MAIL FROM:<from@example.com>
 | 
				
			||||||
RCPT TO:<to@example.com>,<author@example.com>
 | 
					RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com>
 | 
				
			||||||
From: Example <from@example.com>
 | 
					From: Example <from@example.com>
 | 
				
			||||||
To: to@example.com
 | 
					To: to@example.com
 | 
				
			||||||
Cc: A <author@example.com>
 | 
					Cc: A <author@example.com>, One <one@example.com>, two@example.com
 | 
				
			||||||
Subject: [PATCH 1/1] Second.
 | 
					Subject: [PATCH 1/1] Second.
 | 
				
			||||||
Date: DATE-STRING
 | 
					Date: DATE-STRING
 | 
				
			||||||
Message-Id: MESSAGE-ID-STRING
 | 
					Message-Id: MESSAGE-ID-STRING
 | 
				
			||||||
@ -220,17 +295,166 @@ EOF
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
test_expect_success 'sendemail.cc unset' '
 | 
					test_expect_success 'sendemail.cc unset' '
 | 
				
			||||||
	git config --unset sendemail.cc &&
 | 
						git config --unset sendemail.cc &&
 | 
				
			||||||
	git send-email \
 | 
						test_suppression sob
 | 
				
			||||||
		--dry-run \
 | 
					'
 | 
				
			||||||
		--from="Example <from@example.com>" \
 | 
					
 | 
				
			||||||
		--to=to@example.com \
 | 
					cat >expected-suppress-all <<\EOF
 | 
				
			||||||
		--smtp-server relay.example.com \
 | 
					0001-Second.patch
 | 
				
			||||||
		$patches |
 | 
					Dry-OK. Log says:
 | 
				
			||||||
	sed	-e "s/^\(Date:\).*/\1 DATE-STRING/" \
 | 
					Server: relay.example.com
 | 
				
			||||||
		-e "s/^\(Message-Id:\).*/\1 MESSAGE-ID-STRING/" \
 | 
					MAIL FROM:<from@example.com>
 | 
				
			||||||
		-e "s/^\(X-Mailer:\).*/\1 X-MAILER-STRING/" \
 | 
					RCPT TO:<to@example.com>
 | 
				
			||||||
		>actual-show-all-headers &&
 | 
					From: Example <from@example.com>
 | 
				
			||||||
	test_cmp expected-show-all-headers actual-show-all-headers
 | 
					To: to@example.com
 | 
				
			||||||
 | 
					Subject: [PATCH 1/1] Second.
 | 
				
			||||||
 | 
					Date: DATE-STRING
 | 
				
			||||||
 | 
					Message-Id: MESSAGE-ID-STRING
 | 
				
			||||||
 | 
					X-Mailer: X-MAILER-STRING
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result: OK
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_expect_success '--suppress-cc=all' '
 | 
				
			||||||
 | 
						test_suppression all
 | 
				
			||||||
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cat >expected-suppress-body <<\EOF
 | 
				
			||||||
 | 
					0001-Second.patch
 | 
				
			||||||
 | 
					(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
 | 
				
			||||||
 | 
					(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
 | 
				
			||||||
 | 
					(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
 | 
				
			||||||
 | 
					Dry-OK. Log says:
 | 
				
			||||||
 | 
					Server: relay.example.com
 | 
				
			||||||
 | 
					MAIL FROM:<from@example.com>
 | 
				
			||||||
 | 
					RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com>
 | 
				
			||||||
 | 
					From: Example <from@example.com>
 | 
				
			||||||
 | 
					To: to@example.com
 | 
				
			||||||
 | 
					Cc: A <author@example.com>, One <one@example.com>, two@example.com
 | 
				
			||||||
 | 
					Subject: [PATCH 1/1] Second.
 | 
				
			||||||
 | 
					Date: DATE-STRING
 | 
				
			||||||
 | 
					Message-Id: MESSAGE-ID-STRING
 | 
				
			||||||
 | 
					X-Mailer: X-MAILER-STRING
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result: OK
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_expect_success '--suppress-cc=body' '
 | 
				
			||||||
 | 
						test_suppression body
 | 
				
			||||||
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cat >expected-suppress-sob <<\EOF
 | 
				
			||||||
 | 
					0001-Second.patch
 | 
				
			||||||
 | 
					(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
 | 
				
			||||||
 | 
					(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
 | 
				
			||||||
 | 
					(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
 | 
				
			||||||
 | 
					Dry-OK. Log says:
 | 
				
			||||||
 | 
					Server: relay.example.com
 | 
				
			||||||
 | 
					MAIL FROM:<from@example.com>
 | 
				
			||||||
 | 
					RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com>
 | 
				
			||||||
 | 
					From: Example <from@example.com>
 | 
				
			||||||
 | 
					To: to@example.com
 | 
				
			||||||
 | 
					Cc: A <author@example.com>, One <one@example.com>, two@example.com
 | 
				
			||||||
 | 
					Subject: [PATCH 1/1] Second.
 | 
				
			||||||
 | 
					Date: DATE-STRING
 | 
				
			||||||
 | 
					Message-Id: MESSAGE-ID-STRING
 | 
				
			||||||
 | 
					X-Mailer: X-MAILER-STRING
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result: OK
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_expect_success '--suppress-cc=sob' '
 | 
				
			||||||
 | 
						test_suppression sob
 | 
				
			||||||
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cat >expected-suppress-bodycc <<\EOF
 | 
				
			||||||
 | 
					0001-Second.patch
 | 
				
			||||||
 | 
					(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
 | 
				
			||||||
 | 
					(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
 | 
				
			||||||
 | 
					(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
 | 
				
			||||||
 | 
					(body) Adding cc: C O Mitter <committer@example.com> from line 'Signed-off-by: C O Mitter <committer@example.com>'
 | 
				
			||||||
 | 
					Dry-OK. Log says:
 | 
				
			||||||
 | 
					Server: relay.example.com
 | 
				
			||||||
 | 
					MAIL FROM:<from@example.com>
 | 
				
			||||||
 | 
					RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com>,<committer@example.com>
 | 
				
			||||||
 | 
					From: Example <from@example.com>
 | 
				
			||||||
 | 
					To: to@example.com
 | 
				
			||||||
 | 
					Cc: A <author@example.com>, One <one@example.com>, two@example.com, C O Mitter <committer@example.com>
 | 
				
			||||||
 | 
					Subject: [PATCH 1/1] Second.
 | 
				
			||||||
 | 
					Date: DATE-STRING
 | 
				
			||||||
 | 
					Message-Id: MESSAGE-ID-STRING
 | 
				
			||||||
 | 
					X-Mailer: X-MAILER-STRING
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result: OK
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_expect_success '--suppress-cc=bodycc' '
 | 
				
			||||||
 | 
						test_suppression bodycc
 | 
				
			||||||
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cat >expected-suppress-cc <<\EOF
 | 
				
			||||||
 | 
					0001-Second.patch
 | 
				
			||||||
 | 
					(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
 | 
				
			||||||
 | 
					(body) Adding cc: C O Mitter <committer@example.com> from line 'Signed-off-by: C O Mitter <committer@example.com>'
 | 
				
			||||||
 | 
					Dry-OK. Log says:
 | 
				
			||||||
 | 
					Server: relay.example.com
 | 
				
			||||||
 | 
					MAIL FROM:<from@example.com>
 | 
				
			||||||
 | 
					RCPT TO:<to@example.com>,<author@example.com>,<committer@example.com>
 | 
				
			||||||
 | 
					From: Example <from@example.com>
 | 
				
			||||||
 | 
					To: to@example.com
 | 
				
			||||||
 | 
					Cc: A <author@example.com>, C O Mitter <committer@example.com>
 | 
				
			||||||
 | 
					Subject: [PATCH 1/1] Second.
 | 
				
			||||||
 | 
					Date: DATE-STRING
 | 
				
			||||||
 | 
					Message-Id: MESSAGE-ID-STRING
 | 
				
			||||||
 | 
					X-Mailer: X-MAILER-STRING
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result: OK
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_expect_success '--suppress-cc=cc' '
 | 
				
			||||||
 | 
						test_suppression cc
 | 
				
			||||||
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_confirm () {
 | 
				
			||||||
 | 
						echo y | \
 | 
				
			||||||
 | 
							GIT_SEND_EMAIL_NOTTY=1 \
 | 
				
			||||||
 | 
							git send-email \
 | 
				
			||||||
 | 
							--from="Example <nobody@example.com>" \
 | 
				
			||||||
 | 
							--to=nobody@example.com \
 | 
				
			||||||
 | 
							--smtp-server="$(pwd)/fake.sendmail" \
 | 
				
			||||||
 | 
							$@ \
 | 
				
			||||||
 | 
							$patches | grep "Send this email"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_expect_success '--confirm=always' '
 | 
				
			||||||
 | 
						test_confirm --confirm=always --suppress-cc=all
 | 
				
			||||||
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_expect_success '--confirm=auto' '
 | 
				
			||||||
 | 
						test_confirm --confirm=auto
 | 
				
			||||||
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_expect_success '--confirm=cc' '
 | 
				
			||||||
 | 
						test_confirm --confirm=cc
 | 
				
			||||||
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_expect_success '--confirm=compose' '
 | 
				
			||||||
 | 
						test_confirm --confirm=compose --compose
 | 
				
			||||||
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_expect_success 'confirm by default (due to cc)' '
 | 
				
			||||||
 | 
						CONFIRM=$(git config --get sendemail.confirm) &&
 | 
				
			||||||
 | 
						git config --unset sendemail.confirm &&
 | 
				
			||||||
 | 
						test_confirm &&
 | 
				
			||||||
 | 
						git config sendemail.confirm $CONFIRM
 | 
				
			||||||
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_expect_success 'confirm by default (due to --compose)' '
 | 
				
			||||||
 | 
						CONFIRM=$(git config --get sendemail.confirm) &&
 | 
				
			||||||
 | 
						git config --unset sendemail.confirm &&
 | 
				
			||||||
 | 
						test_confirm --suppress-cc=all --compose
 | 
				
			||||||
 | 
						ret="$?"
 | 
				
			||||||
 | 
						git config sendemail.confirm ${CONFIRM:-never}
 | 
				
			||||||
 | 
						test $ret = "0"
 | 
				
			||||||
'
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test_expect_success '--compose adds MIME for utf8 body' '
 | 
					test_expect_success '--compose adds MIME for utf8 body' '
 | 
				
			||||||
@ -239,9 +463,7 @@ test_expect_success '--compose adds MIME for utf8 body' '
 | 
				
			|||||||
	 echo "echo utf8 body: àéìöú >>\"\$1\""
 | 
						 echo "echo utf8 body: àéìöú >>\"\$1\""
 | 
				
			||||||
	) >fake-editor-utf8 &&
 | 
						) >fake-editor-utf8 &&
 | 
				
			||||||
	chmod +x fake-editor-utf8 &&
 | 
						chmod +x fake-editor-utf8 &&
 | 
				
			||||||
	echo y | \
 | 
					 | 
				
			||||||
	  GIT_EDITOR="\"$(pwd)/fake-editor-utf8\"" \
 | 
						  GIT_EDITOR="\"$(pwd)/fake-editor-utf8\"" \
 | 
				
			||||||
	  GIT_SEND_EMAIL_NOTTY=1 \
 | 
					 | 
				
			||||||
	  git send-email \
 | 
						  git send-email \
 | 
				
			||||||
	  --compose --subject foo \
 | 
						  --compose --subject foo \
 | 
				
			||||||
	  --from="Example <nobody@example.com>" \
 | 
						  --from="Example <nobody@example.com>" \
 | 
				
			||||||
@ -263,9 +485,7 @@ test_expect_success '--compose respects user mime type' '
 | 
				
			|||||||
	 echo " echo utf8 body: àéìöú) >\"\$1\""
 | 
						 echo " echo utf8 body: àéìöú) >\"\$1\""
 | 
				
			||||||
	) >fake-editor-utf8-mime &&
 | 
						) >fake-editor-utf8-mime &&
 | 
				
			||||||
	chmod +x fake-editor-utf8-mime &&
 | 
						chmod +x fake-editor-utf8-mime &&
 | 
				
			||||||
	echo y | \
 | 
					 | 
				
			||||||
	  GIT_EDITOR="\"$(pwd)/fake-editor-utf8-mime\"" \
 | 
						  GIT_EDITOR="\"$(pwd)/fake-editor-utf8-mime\"" \
 | 
				
			||||||
	  GIT_SEND_EMAIL_NOTTY=1 \
 | 
					 | 
				
			||||||
	  git send-email \
 | 
						  git send-email \
 | 
				
			||||||
	  --compose --subject foo \
 | 
						  --compose --subject foo \
 | 
				
			||||||
	  --from="Example <nobody@example.com>" \
 | 
						  --from="Example <nobody@example.com>" \
 | 
				
			||||||
@ -279,9 +499,7 @@ test_expect_success '--compose respects user mime type' '
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
test_expect_success '--compose adds MIME for utf8 subject' '
 | 
					test_expect_success '--compose adds MIME for utf8 subject' '
 | 
				
			||||||
	clean_fake_sendmail &&
 | 
						clean_fake_sendmail &&
 | 
				
			||||||
	echo y | \
 | 
					 | 
				
			||||||
	  GIT_EDITOR="\"$(pwd)/fake-editor\"" \
 | 
						  GIT_EDITOR="\"$(pwd)/fake-editor\"" \
 | 
				
			||||||
	  GIT_SEND_EMAIL_NOTTY=1 \
 | 
					 | 
				
			||||||
	  git send-email \
 | 
						  git send-email \
 | 
				
			||||||
	  --compose --subject utf8-sübjëct \
 | 
						  --compose --subject utf8-sübjëct \
 | 
				
			||||||
	  --from="Example <nobody@example.com>" \
 | 
						  --from="Example <nobody@example.com>" \
 | 
				
			||||||
@ -303,7 +521,7 @@ test_expect_success 'detects ambiguous reference/file conflict' '
 | 
				
			|||||||
test_expect_success 'feed two files' '
 | 
					test_expect_success 'feed two files' '
 | 
				
			||||||
	rm -fr outdir &&
 | 
						rm -fr outdir &&
 | 
				
			||||||
	git format-patch -2 -o outdir &&
 | 
						git format-patch -2 -o outdir &&
 | 
				
			||||||
	GIT_SEND_EMAIL_NOTTY=1 git send-email \
 | 
						git send-email \
 | 
				
			||||||
	--dry-run \
 | 
						--dry-run \
 | 
				
			||||||
	--from="Example <nobody@example.com>" \
 | 
						--from="Example <nobody@example.com>" \
 | 
				
			||||||
	--to=nobody@example.com \
 | 
						--to=nobody@example.com \
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user