scripts/get_maintainer.pl: fix mailmap handling
authorFlorian Mickler <florian@mickler.org>
Tue, 26 Oct 2010 21:22:56 +0000 (14:22 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 26 Oct 2010 23:52:17 +0000 (16:52 -0700)
Implement it, like it is described in git-shortlog.

Signed-off-by: Florian Mickler <florian@mickler.org>
Signed-off-by: Joe Perches <joe@perches.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
scripts/get_maintainer.pl

index 61d3bb51bddf571d0c7a1dd3edb4bfe36b25860b..faeace4e1fd0d163aa11a19382135a2d177aa759 100755 (executable)
@@ -295,31 +295,76 @@ while (<$maint>) {
 }
 close($maint);
 
-my %mailmap;
 
-if ($email_remove_duplicates) {
-    open(my $mailmap, '<', "${lk_path}.mailmap")
+#
+# Read mail address map
+#
+
+my $mailmap = read_mailmap();
+
+sub read_mailmap {
+    my $mailmap = {
+       names => {},
+       addresses => {}
+   };
+
+    if (!$email_remove_duplicates) {
+       return $mailmap;
+    }
+
+    open(my $mailmap_file, '<', "${lk_path}.mailmap")
        or warn "$P: Can't open .mailmap: $!\n";
-    while (<$mailmap>) {
-       my $line = $_;
 
-       next if ($line =~ m/^\s*#/);
-       next if ($line =~ m/^\s*$/);
+    while (<$mailmap_file>) {
+       s/#.*$//; #strip comments
+       s/^\s+|\s+$//g; #trim
 
-       my ($name, $address) = parse_email($line);
-       $line = format_email($name, $address, $email_usename);
+       next if (/^\s*$/); #skip empty lines
+       #entries have one of the following formats:
+       # name1 <mail1>
+       # <mail1> <mail2>
+       # name1 <mail1> <mail2>
+       # name1 <mail1> name2 <mail2>
+       # (see man git-shortlog)
+       if (/^(.+)<(.+)>$/) {
+               my $real_name = $1;
+               my $address = $2;
 
-       next if ($line =~ m/^\s*$/);
+               $real_name =~ s/\s+$//;
+               $mailmap->{names}->{$address} = $real_name;
 
-       if (exists($mailmap{$name})) {
-           my $obj = $mailmap{$name};
-           push(@$obj, $address);
-       } else {
-           my @arr = ($address);
-           $mailmap{$name} = \@arr;
+       } elsif (/^<([^\s]+)>\s*<([^\s]+)>$/) {
+               my $real_address = $1;
+               my $wrong_address = $2;
+
+               $mailmap->{addresses}->{$wrong_address} = $real_address;
+
+       } elsif (/^(.+)<([^\s]+)>\s*<([^\s]+)>$/) {
+               my $real_name= $1;
+               my $real_address = $2;
+               my $wrong_address = $3;
+
+               $real_name =~ s/\s+$//;
+
+               $mailmap->{names}->{$wrong_address} = $real_name;
+               $mailmap->{addresses}->{$wrong_address} = $real_address;
+
+       } elsif (/^(.+)<([^\s]+)>\s*([^\s].*)<([^\s]+)>$/) {
+               my $real_name = $1;
+               my $real_address = $2;
+               my $wrong_name = $3;
+               my $wrong_address = $4;
+
+               $real_name =~ s/\s+$//;
+               $wrong_name =~ s/\s+$//;
+
+               $mailmap->{names}->{format_email($wrong_name,$wrong_address,1)} = $real_name;
+               $mailmap->{addresses}->{format_email($wrong_name,$wrong_address,1)} = $real_address;
        }
     }
-    close($mailmap);
+    close($mailmap_file);
+
+    return $mailmap;
 }
 
 ## use the filenames on the command line or find the filenames in the patchfiles
@@ -1061,30 +1106,58 @@ sub which_conf {
     return "";
 }
 
-sub mailmap {
-    my (@lines) = @_;
-    my %hash;
+sub mailmap_email {
+       my $line = shift;
 
-    foreach my $line (@lines) {
        my ($name, $address) = parse_email($line);
-       if (!exists($hash{$name})) {
-           $hash{$name} = $address;
-       } elsif ($address ne $hash{$name}) {
-           $address = $hash{$name};
-           $line = format_email($name, $address, $email_usename);
-       }
-       if (exists($mailmap{$name})) {
-           my $obj = $mailmap{$name};
-           foreach my $map_address (@$obj) {
-               if (($map_address eq $address) &&
-                   ($map_address ne $hash{$name})) {
-                   $line = format_email($name, $hash{$name}, $email_usename);
+       my $email = format_email($name, $address, 1);
+       my $real_name = $name;
+       my $real_address = $address;
+
+       if (exists $mailmap->{names}->{$email} || exists $mailmap->{addresses}->{$email}) {
+               if (exists $mailmap->{names}->{$email}) {
+                       $real_name = $mailmap->{names}->{$email};
+               }
+               if (exists $mailmap->{addresses}->{$email}) {
+                       $real_address = $mailmap->{addresses}->{$email};
+               }
+       } else {
+               if (exists $mailmap->{names}->{$address}) {
+                       $real_name = $mailmap->{names}->{$address};
+               }
+               if (exists $mailmap->{addresses}->{$address}) {
+                       $real_address = $mailmap->{addresses}->{$address};
                }
-           }
        }
+       return format_email($real_name, $real_address, 1);
+}
+
+sub mailmap {
+    my (@addresses) = @_;
+
+    my @ret = ();
+    foreach my $line (@addresses) {
+       push(@ret, mailmap_email($line), 1);
     }
 
-    return @lines;
+    merge_by_realname(@ret) if $email_remove_duplicates;
+
+    return @ret;
+}
+
+sub merge_by_realname {
+       my %address_map;
+       my (@emails) = @_;
+       foreach my $email (@emails) {
+               my ($name, $address) = parse_email($email);
+               if (!exists $address_map{$name}) {
+                       $address_map{$name} = $address;
+               } else {
+                       $address = $address_map{$name};
+                       $email = format_email($name,$address,1);
+               }
+       }
+
 }
 
 sub git_execute_cmd {
@@ -1636,9 +1709,7 @@ sub vcs_assign {
        $divisor = 1;
     }
 
-    if ($email_remove_duplicates) {
-       @lines = mailmap(@lines);
-    }
+    @lines = mailmap(@lines);
 
     return if (@lines <= 0);