Merge branch 'maint'
authorJunio C Hamano <gitster@pobox.com>
Sat, 17 Nov 2007 05:30:06 +0000 (21:30 -0800)
committerJunio C Hamano <gitster@pobox.com>
Sat, 17 Nov 2007 05:30:06 +0000 (21:30 -0800)
* 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'

1  2 
git-send-email.perl
t/t9101-git-svn-props.sh
diff --combined git-send-email.perl
index f9bd2e5a9176ccf7dd8e2ce15233d2d93f9222ec,2b1f1b598c62ddaed693635adef12e490f49838f..fd0a4ad0c24dfedd2fea278733d8f6cff59b2eb5
@@@ -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;
                                                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, $_;
                                }
                        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;
        }
        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(<F>) {
                        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;
  
        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 3c83127a0e862dd89837755103a97ed967c80e0b,02c41697decd70f8e7b6c208fefe8c5e52c37fac..d7a704754ea13f17c098e56a7b068cb4f44c1fd0
@@@ -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 .. &&
        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