From: Junio C Hamano Date: Sat, 17 Nov 2007 05:30:06 +0000 (-0800) Subject: Merge branch 'maint' X-Git-Tag: v1.5.4-rc0~196 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/f1a82fe9a3de780fb2f1fe054d692294544f01e7?hp=-c Merge branch 'maint' * maint: Update draft release notes for 1.5.3.6 Fix per-directory exclude handing for "git add" core.excludesfile clean-up Fix t9101 test failure caused by Subversion "auto-props" git-send-email: add charset header if we add encoded 'From' --- f1a82fe9a3de780fb2f1fe054d692294544f01e7 diff --combined git-send-email.perl index f9bd2e5a91,2b1f1b598c..fd0a4ad0c2 --- a/git-send-email.perl +++ b/git-send-email.perl @@@ -73,22 -73,11 +73,22 @@@ Options --signed-off-cc Automatically add email addresses that appear in Signed-off-by: or Cc: lines to the cc: list. Defaults to on. + --identity The configuration identity, a subsection to prioritise over + the default section. + --smtp-server If set, specifies the outgoing SMTP server to use. - Defaults to localhost. + Defaults to localhost. Port number can be specified here with + hostname:port format or by using --smtp-server-port option. + + --smtp-server-port Specify a port on the outgoing SMTP server to connect to. + + --smtp-user The username for SMTP-AUTH. - --suppress-from Suppress sending emails to yourself if your address - appears in a From: line. Defaults to off. + --smtp-pass The password for SMTP-AUTH. + + --smtp-ssl If set, connects to the SMTP server using SSL. + + --suppress-from Suppress sending emails to yourself. Defaults to off. --thread Specify that the "In-Reply-To:" header should be set on all emails. Defaults to on. @@@ -156,6 -145,7 +156,6 @@@ my $compose_filename = ".msg.$$" my (@to,@cc,@initial_cc,@bcclist,@xh, $initial_reply_to,$initial_subject,@files,$author,$sender,$compose,$time); -my $smtp_server; my $envelope_sender; # Example reply to: @@@ -174,28 -164,24 +174,28 @@@ my ($quiet, $dry_run) = (0, 0) # Variables with corresponding config settings my ($thread, $chain_reply_to, $suppress_from, $signed_off_cc, $cc_cmd); +my ($smtp_server, $smtp_server_port, $smtp_authuser, $smtp_authpass, $smtp_ssl); +my ($identity, $aliasfiletype, @alias_files, @smtp_host_parts); -my %config_settings = ( +my %config_bool_settings = ( "thread" => [\$thread, 1], "chainreplyto" => [\$chain_reply_to, 1], "suppressfrom" => [\$suppress_from, 0], "signedoffcc" => [\$signed_off_cc, 1], - "cccmd" => [\$cc_cmd, ""], + "smtpssl" => [\$smtp_ssl, 0], ); -foreach my $setting (keys %config_settings) { - my $config = $repo->config_bool("sendemail.$setting"); - ${$config_settings{$setting}->[0]} = (defined $config) ? $config : $config_settings{$setting}->[1]; -} - -@bcclist = $repo->config('sendemail.bcc'); -if (!@bcclist or !$bcclist[0]) { - @bcclist = (); -} +my %config_settings = ( + "smtpserver" => \$smtp_server, + "smtpserverport" => \$smtp_server_port, + "smtpuser" => \$smtp_authuser, + "smtppass" => \$smtp_authpass, + "to" => \@to, + "cccmd" => \$cc_cmd, + "aliasfiletype" => \$aliasfiletype, + "bcc" => \@bcclist, + "aliasesfile" => \@alias_files, +); # Begin by accumulating all the variables (defined above), that we will end up # needing, first, from the command line: @@@ -208,11 -194,6 +208,11 @@@ my $rc = GetOptions("sender|from=s" => "bcc=s" => \@bcclist, "chain-reply-to!" => \$chain_reply_to, "smtp-server=s" => \$smtp_server, + "smtp-server-port=s" => \$smtp_server_port, + "smtp-user=s" => \$smtp_authuser, + "smtp-pass=s" => \$smtp_authpass, + "smtp-ssl!" => \$smtp_ssl, + "identity=s" => \$identity, "compose" => \$compose, "quiet" => \$quiet, "cc-cmd=s" => \$cc_cmd, @@@ -227,43 -208,6 +227,43 @@@ unless ($rc) usage(); } +# Now, let's fill any that aren't set in with defaults: + +sub read_config { + my ($prefix) = @_; + + foreach my $setting (keys %config_bool_settings) { + my $target = $config_bool_settings{$setting}->[0]; + $$target = $repo->config_bool("$prefix.$setting") unless (defined $$target); + } + + foreach my $setting (keys %config_settings) { + my $target = $config_settings{$setting}; + if (ref($target) eq "ARRAY") { + unless (@$target) { + my @values = $repo->config("$prefix.$setting"); + @$target = @values if (@values && defined $values[0]); + } + } + else { + $$target = $repo->config("$prefix.$setting") unless (defined $$target); + } + } +} + +# read configuration from [sendemail "$identity"], fall back on [sendemail] +$identity = $repo->config("sendemail.identity") unless (defined $identity); +read_config("sendemail.$identity") if (defined $identity); +read_config("sendemail"); + +# fall back on builtin bool defaults +foreach my $setting (values %config_bool_settings) { + ${$setting->[0]} = $setting->[1] unless (defined (${$setting->[0]})); +} + +my ($repoauthor) = $repo->ident_person('author'); +my ($repocommitter) = $repo->ident_person('committer'); + # Verify the user input foreach my $entry (@to) { @@@ -278,7 -222,14 +278,7 @@@ foreach my $entry (@bcclist) die "Comma in --bcclist entry: $entry'\n" unless $entry !~ m/,/; } -# Now, let's fill any that aren't set in with defaults: - -my ($repoauthor) = $repo->ident_person('author'); -my ($repocommitter) = $repo->ident_person('committer'); - my %aliases; -my @alias_files = $repo->config('sendemail.aliasesfile'); -my $aliasfiletype = $repo->config('sendemail.aliasfiletype'); my %parse_alias = ( # multiline formats can be supported in the future mutt => sub { my $fh = shift; while (<$fh>) { @@@ -370,7 -321,10 +370,7 @@@ if ($thread && !defined $initial_reply_ $initial_reply_to =~ s/>?\s+$/>/; } -if (!$smtp_server) { - $smtp_server = $repo->config('sendemail.smtpserver'); -} -if (!$smtp_server) { +if (!defined $smtp_server) { foreach (qw( /usr/sbin/sendmail /usr/lib/sendmail )) { if (-x $_) { $smtp_server = $_; @@@ -514,11 -468,13 +514,13 @@@ $time = time - scalar $#files sub unquote_rfc2047 { local ($_) = @_; - if (s/=\?utf-8\?q\?(.*)\?=/$1/g) { + my $encoding; + if (s/=\?([^?]+)\?q\?(.*)\?=/$2/g) { + $encoding = $1; s/_/ /g; s/=([0-9A-F]{2})/chr(hex($1))/eg; } - return "$_"; + return wantarray ? ($_, $encoding) : $_; } # use the simplest quoting being able to handle the recipient @@@ -607,30 -563,8 +609,30 @@@ X-Mailer: git-send-email $gitversio print $sm "$header\n$message"; close $sm or die $?; } else { - require Net::SMTP; - $smtp ||= Net::SMTP->new( $smtp_server ); + + if (!defined $smtp_server) { + die "The required SMTP server is not properly defined." + } + + if ($smtp_ssl) { + $smtp_server_port ||= 465; # ssmtp + require Net::SMTP::SSL; + $smtp ||= Net::SMTP::SSL->new($smtp_server, Port => $smtp_server_port); + } + else { + require Net::SMTP; + $smtp ||= Net::SMTP->new((defined $smtp_server_port) + ? "$smtp_server:$smtp_server_port" + : $smtp_server); + } + + if (!$smtp) { + die "Unable to initialize SMTP properly. Is there something wrong with your config?"; + } + + if ((defined $smtp_authuser) && (defined $smtp_authpass)) { + $smtp->auth( $smtp_authuser, $smtp_authpass ) or die $smtp->message; + } $smtp->mail( $raw_from ) or die $smtp->message; $smtp->to( @recipients ) or die $smtp->message; $smtp->data or die $smtp->message; @@@ -667,6 -601,9 +669,9 @@@ foreach my $t (@files) open(F,"<",$t) or die "can't open file $t"; my $author = undef; + my $author_encoding; + my $has_content_type; + my $body_encoding; @cc = @initial_cc; @xh = (); my $input_format = undef; @@@ -692,12 -629,20 +697,20 @@@ next if ($suppress_from); } elsif ($1 eq 'From') { - $author = unquote_rfc2047($2); + ($author, $author_encoding) + = unquote_rfc2047($2); } printf("(mbox) Adding cc: %s from line '%s'\n", $2, $_) unless $quiet; push @cc, $2; } + elsif (/^Content-type:/i) { + $has_content_type = 1; + if (/charset="?[^ "]+/) { + $body_encoding = $1; + } + push @xh, $_; + } elsif (!/^Date:\s/ && /^[-A-Za-z]+:\s+\S/) { push @xh, $_; } @@@ -729,7 -674,6 +742,7 @@@ if (/^(Signed-off-by|Cc): (.*)$/i && $signed_off_cc) { my $c = $2; chomp $c; + next if ($c eq $sender and $suppress_from); push @cc, $c; printf("(sob) Adding cc: %s from line '%s'\n", $c, $_) unless $quiet; @@@ -738,14 -682,13 +751,14 @@@ } close F; - if ($cc_cmd ne "") { + if (defined $cc_cmd) { open(F, "$cc_cmd $t |") or die "(cc-cmd) Could not execute '$cc_cmd'"; while() { my $c = $_; $c =~ s/^\s*//g; $c =~ s/\n$//g; + next if ($c eq $sender and $suppress_from); push @cc, $c; printf("(cc-cmd) Adding cc: %s from: '%s'\n", $c, $cc_cmd) unless $quiet; @@@ -756,6 -699,21 +769,21 @@@ if (defined $author) { $message = "From: $author\n\n$message"; + if (defined $author_encoding) { + if ($has_content_type) { + if ($body_encoding eq $author_encoding) { + # ok, we already have the right encoding + } + else { + # uh oh, we should re-encode + } + } + else { + push @xh, + 'MIME-Version: 1.0', + "Content-Type: text/plain; charset=$author_encoding"; + } + } } send_message(); diff --combined t/t9101-git-svn-props.sh index 3c83127a0e,02c41697de..d7a704754e --- a/t/t9101-git-svn-props.sh +++ b/t/t9101-git-svn-props.sh @@@ -48,7 -48,7 +48,7 @@@ EO printf "\r\n" > empty_crlf a_empty_crlf=`git-hash-object -w empty_crlf` - svn import -m 'import for git-svn' . "$svnrepo" >/dev/null + svn import --no-auto-props -m 'import for git-svn' . "$svnrepo" >/dev/null cd .. rm -rf import @@@ -126,22 -126,20 +126,22 @@@ cat > show-ignore.expect <<\EO # / /no-such-file* -# deeply +# /deeply/ /deeply/no-such-file* -# deeply/nested +# /deeply/nested/ /deeply/nested/no-such-file* -# deeply/nested/directory +# /deeply/nested/directory/ /deeply/nested/directory/no-such-file* EOF test_expect_success 'test show-ignore' " cd test_wc && mkdir -p deeply/nested/directory && + touch deeply/nested/directory/.keep && svn add deeply && + svn up && svn propset -R svn:ignore 'no-such-file*' . svn commit -m 'propset svn:ignore' cd .. && @@@ -149,69 -147,4 +149,69 @@@ cmp show-ignore.expect show-ignore.got " +cat >create-ignore.expect <<\EOF +/no-such-file* +EOF + +cat >create-ignore-index.expect <<\EOF +100644 8c52e5dfcd0a8b6b6bcfe6b41b89bcbf493718a5 0 .gitignore +100644 8c52e5dfcd0a8b6b6bcfe6b41b89bcbf493718a5 0 deeply/.gitignore +100644 8c52e5dfcd0a8b6b6bcfe6b41b89bcbf493718a5 0 deeply/nested/.gitignore +100644 8c52e5dfcd0a8b6b6bcfe6b41b89bcbf493718a5 0 deeply/nested/directory/.gitignore +EOF + +test_expect_success 'test create-ignore' " + git-svn fetch && git pull . remotes/git-svn && + git-svn create-ignore && + cmp ./.gitignore create-ignore.expect && + cmp ./deeply/.gitignore create-ignore.expect && + cmp ./deeply/nested/.gitignore create-ignore.expect && + cmp ./deeply/nested/directory/.gitignore create-ignore.expect && + git ls-files -s | grep gitignore | cmp - create-ignore-index.expect + " + +cat >prop.expect <<\EOF +no-such-file* + +EOF +cat >prop2.expect <<\EOF +8 +EOF + +# This test can be improved: since all the svn:ignore contain the same +# pattern, it can pass even though the propget did not execute on the +# right directory. +test_expect_success 'test propget' " + git-svn propget svn:ignore . | cmp - prop.expect && + cd deeply && + git-svn propget svn:ignore . | cmp - ../prop.expect && + git-svn propget svn:entry:committed-rev nested/directory/.keep \ + | cmp - ../prop2.expect && + git-svn propget svn:ignore .. | cmp - ../prop.expect && + git-svn propget svn:ignore nested/ | cmp - ../prop.expect && + git-svn propget svn:ignore ./nested | cmp - ../prop.expect && + git-svn propget svn:ignore .././deeply/nested | cmp - ../prop.expect + " + +cat >prop.expect <<\EOF +Properties on '.': + svn:entry:committed-date + svn:entry:committed-rev + svn:entry:last-author + svn:entry:uuid + svn:ignore +EOF +cat >prop2.expect <<\EOF +Properties on 'nested/directory/.keep': + svn:entry:committed-date + svn:entry:committed-rev + svn:entry:last-author + svn:entry:uuid +EOF + +test_expect_success 'test proplist' " + git-svn proplist . | cmp - prop.expect && + git-svn proplist nested/directory/.keep | cmp - prop2.expect + " + test_done