send-email: extract email-parsing code into a subroutine
authorNathan Payre <nathan.payre@etu.univ-lyon1.fr>
Fri, 15 Dec 2017 15:33:39 +0000 (16:33 +0100)
committerJunio C Hamano <gitster@pobox.com>
Fri, 15 Dec 2017 18:46:53 +0000 (10:46 -0800)
The existing code mixes parsing of email header with regular
expression and actual code. Extract the parsing code into a new
subroutine "parse_header_line()". This improves the code readability
and make parse_header_line reusable in other place.

"parsed_header_line()" and "filter_body()" could be used for
refactoring the part of code which parses the header to prepare the
email and send it.

In contrast to the previous version it doesn't keep the header order
and strip duplicate headers.

Signed-off-by: Nathan Payre <nathan.payre@etu.univ-lyon1.fr>
Signed-off-by: Matthieu Moy <matthieu.moy@univ-lyon1.fr>
Signed-off-by: Timothee Albertin <timothee.albertin@etu.univ-lyon1.fr>
Signed-off-by: Daniel Bensoussan <daniel.bensoussan--bohm@etu.univ-lyon1.fr>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Reviewed-by: Matthieu Moy <matthieu.moy@univ-lyon1.fr>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
git-send-email.perl
index edcc6d34692b28575d9728c25a407782310a39fb..c2b2e8ccfa0df94e25b1de2bf8179dd819982137 100755 (executable)
@@ -703,57 +703,70 @@ sub get_patch_subject {
                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);
 }
@@ -792,6 +805,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 {