Merge branch 'np/send-email-header-parsing'
authorJunio C Hamano <gitster@pobox.com>
Thu, 15 Mar 2018 22:00:45 +0000 (15:00 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 15 Mar 2018 22:00:45 +0000 (15:00 -0700)
Code refactoring.

* np/send-email-header-parsing:
send-email: extract email-parsing code into a subroutine

1  2 
git-send-email.perl
diff --combined git-send-email.perl
index 435c7c9e26d75e8f6a4f635753f248fcf8106790,c2b2e8ccfa0df94e25b1de2bf8179dd819982137..a4a560bb834c9595fb3f2f1c315a00f8f7150e06
@@@ -26,11 -26,10 +26,11 @@@ use Text::ParseWords
  use Term::ANSIColor;
  use File::Temp qw/ tempdir tempfile /;
  use File::Spec::Functions qw(catdir catfile);
 -use Error qw(:try);
 +use Git::Error qw(:try);
  use Cwd qw(abs_path cwd);
  use Git;
  use Git::I18N;
 +use Git::Mail::Address;
  
  Getopt::Long::Configure qw/ pass_through /;
  
@@@ -379,10 -378,6 +379,10 @@@ unless ($rc) 
  die __("Cannot run git format-patch from outside a repository\n")
        if $format_patch and not $repo;
  
 +die __("`batch-size` and `relogin` must be specified together " .
 +      "(via command-line or configuration option)\n")
 +      if defined $relogin_delay and not defined $batch_size;
 +
  # Now, let's fill any that aren't set in with defaults:
  
  sub read_config {
@@@ -494,7 -489,7 +494,7 @@@ my ($repoauthor, $repocommitter)
  ($repocommitter) = Git::ident_person(@repo, 'committer');
  
  sub parse_address_line {
 -      return Git::parse_mailboxes($_[0]);
 +      return map { $_->format } Mail::Address->parse($_[0]);
  }
  
  sub split_addrs {
@@@ -708,57 -703,70 +708,70 @@@ EOT
                do_edit($compose_filename);
        }
  
-       open my $c2, ">", $compose_filename . ".final"
-               or die sprintf(__("Failed to open %s.final: %s"), $compose_filename, $!);
        open $c, "<", $compose_filename
                or die sprintf(__("Failed to open %s: %s"), $compose_filename, $!);
  
-       my $need_8bit_cte = file_has_nonascii($compose_filename);
-       my $in_body = 0;
-       my $summary_empty = 1;
        if (!defined $compose_encoding) {
                $compose_encoding = "UTF-8";
        }
-       while(<$c>) {
-               next if m/^GIT:/;
-               if ($in_body) {
-                       $summary_empty = 0 unless (/^\n$/);
-               } elsif (/^\n$/) {
-                       $in_body = 1;
-                       if ($need_8bit_cte) {
-                               print $c2 "MIME-Version: 1.0\n",
-                                        "Content-Type: text/plain; ",
-                                          "charset=$compose_encoding\n",
-                                        "Content-Transfer-Encoding: 8bit\n";
-                       }
-               } elsif (/^MIME-Version:/i) {
-                       $need_8bit_cte = 0;
-               } elsif (/^Subject:\s*(.+)\s*$/i) {
-                       $initial_subject = $1;
-                       my $subject = $initial_subject;
-                       $_ = "Subject: " .
-                               quote_subject($subject, $compose_encoding) .
-                               "\n";
-               } elsif (/^In-Reply-To:\s*(.+)\s*$/i) {
-                       $initial_reply_to = $1;
-                       next;
-               } elsif (/^From:\s*(.+)\s*$/i) {
-                       $sender = $1;
-                       next;
-               } elsif (/^(?:To|Cc|Bcc):/i) {
-                       print __("To/Cc/Bcc fields are not interpreted yet, they have been ignored\n");
-                       next;
+       my %parsed_email;
+       while (my $line = <$c>) {
+               next if $line =~ m/^GIT:/;
+               parse_header_line($line, \%parsed_email);
+               if ($line =~ /^$/) {
+                       $parsed_email{'body'} = filter_body($c);
                }
-               print $c2 $_;
        }
        close $c;
-       close $c2;
  
-       if ($summary_empty) {
+       open my $c2, ">", $compose_filename . ".final"
+       or die sprintf(__("Failed to open %s.final: %s"), $compose_filename, $!);
+       if ($parsed_email{'From'}) {
+               $sender = delete($parsed_email{'From'});
+       }
+       if ($parsed_email{'In-Reply-To'}) {
+               $initial_reply_to = delete($parsed_email{'In-Reply-To'});
+       }
+       if ($parsed_email{'Subject'}) {
+               $initial_subject = delete($parsed_email{'Subject'});
+               print $c2 "Subject: " .
+                       quote_subject($initial_subject, $compose_encoding) .
+                       "\n";
+       }
+       if ($parsed_email{'MIME-Version'}) {
+               print $c2 "MIME-Version: $parsed_email{'MIME-Version'}\n",
+                               "Content-Type: $parsed_email{'Content-Type'};\n",
+                               "Content-Transfer-Encoding: $parsed_email{'Content-Transfer-Encoding'}\n";
+               delete($parsed_email{'MIME-Version'});
+               delete($parsed_email{'Content-Type'});
+               delete($parsed_email{'Content-Transfer-Encoding'});
+       } elsif (file_has_nonascii($compose_filename)) {
+               my $content_type = (delete($parsed_email{'Content-Type'}) or
+                       "text/plain; charset=$compose_encoding");
+               print $c2 "MIME-Version: 1.0\n",
+                       "Content-Type: $content_type\n",
+                       "Content-Transfer-Encoding: 8bit\n";
+       }
+       # Preserve unknown headers
+       foreach my $key (keys %parsed_email) {
+               next if $key eq 'body';
+               print $c2 "$key: $parsed_email{$key}";
+       }
+       if ($parsed_email{'body'}) {
+               print $c2 "\n$parsed_email{'body'}\n";
+               delete($parsed_email{'body'});
+       } else {
                print __("Summary email is empty, skipping it\n");
                $compose = -1;
        }
+       close $c2;
  } elsif ($annotate) {
        do_edit(@files);
  }
@@@ -797,6 -805,32 +810,32 @@@ sub ask 
        return;
  }
  
+ sub parse_header_line {
+       my $lines = shift;
+       my $parsed_line = shift;
+       my $addr_pat = join "|", qw(To Cc Bcc);
+       foreach (split(/\n/, $lines)) {
+               if (/^($addr_pat):\s*(.+)$/i) {
+                       $parsed_line->{$1} = [ parse_address_line($2) ];
+               } elsif (/^([^:]*):\s*(.+)\s*$/i) {
+                       $parsed_line->{$1} = $2;
+               }
+       }
+ }
+ sub filter_body {
+       my $c = shift;
+       my $body = "";
+       while (my $body_line = <$c>) {
+               if ($body_line !~ m/^GIT:/) {
+                       $body .= $body_line;
+               }
+       }
+       return $body;
+ }
  my %broken_encoding;
  
  sub file_declares_8bit_cte {