Implement it, like it is described in git-shortlog.
Unified · Split
| @@ -295,31 +295,76 @@ while (<$maint>) { · 294 unmodified lines | ||
| 295 | 295 | } |
| 296 | 296 | close($maint); |
| 297 | 297 | |
| 298 | −my %mailmap; | |
| 299 | 298 | |
| 300 | −if ($email_remove_duplicates) { | |
| 301 | − open(my $mailmap, '<', "${lk_path}.mailmap") | |
| 299 | +# | |
| 300 | +# Read mail address map | |
| 301 | +# | |
| 302 | + | |
| 303 | +my $mailmap = read_mailmap(); | |
| 304 | + | |
| 305 | +sub read_mailmap { | |
| 306 | + my $mailmap = { | |
| 307 | + names => {}, | |
| 308 | + addresses => {} | |
| 309 | + }; | |
| 310 | + | |
| 311 | + if (!$email_remove_duplicates) { | |
| 312 | + return $mailmap; | |
| 313 | + } | |
| 314 | + | |
| 315 | + open(my $mailmap_file, '<', "${lk_path}.mailmap") | |
| 302 | 316 | or warn "$P: Can't open .mailmap: $!\n"; |
| 303 | − while (<$mailmap>) { | |
| 304 | − my $line = $_; | |
| 305 | 317 | |
| 306 | − next if ($line =~ m/^\s*#/); | |
| 307 | − next if ($line =~ m/^\s*$/); | |
| 318 | + while (<$mailmap_file>) { | |
| 319 | + s/#.*$//; #strip comments | |
| 320 | + s/^\s+|\s+$//g; #trim | |
| 308 | 321 | |
| 309 | − my ($name, $address) = parse_email($line); | |
| 310 | − $line = format_email($name, $address, $email_usename); | |
| 322 | + next if (/^\s*$/); #skip empty lines | |
| 323 | + #entries have one of the following formats: | |
| 324 | + # name1 <mail1> | |
| 325 | + # <mail1> <mail2> | |
| 326 | + # name1 <mail1> <mail2> | |
| 327 | + # name1 <mail1> name2 <mail2> | |
| 328 | + # (see man git-shortlog) | |
| 329 | + if (/^(.+)<(.+)>$/) { | |
| 330 | + my $real_name = $1; | |
| 331 | + my $address = $2; | |
| 311 | 332 | |
| 312 | − next if ($line =~ m/^\s*$/); | |
| 333 | + $real_name =~ s/\s+$//; | |
| 334 | + $mailmap->{names}->{$address} = $real_name; | |
| 313 | 335 | |
| 314 | − if (exists($mailmap{$name})) { | |
| 315 | − my $obj = $mailmap{$name}; | |
| 316 | − push(@$obj, $address); | |
| 317 | − } else { | |
| 318 | − my @arr = ($address); | |
| 319 | − $mailmap{$name} = \@arr; | |
| 336 | + } elsif (/^<([^\s]+)>\s*<([^\s]+)>$/) { | |
| 337 | + my $real_address = $1; | |
| 338 | + my $wrong_address = $2; | |
| 339 | + | |
| 340 | + $mailmap->{addresses}->{$wrong_address} = $real_address; | |
| 341 | + | |
| 342 | + } elsif (/^(.+)<([^\s]+)>\s*<([^\s]+)>$/) { | |
| 343 | + my $real_name= $1; | |
| 344 | + my $real_address = $2; | |
| 345 | + my $wrong_address = $3; | |
| 346 | + | |
| 347 | + $real_name =~ s/\s+$//; | |
| 348 | + | |
| 349 | + $mailmap->{names}->{$wrong_address} = $real_name; | |
| 350 | + $mailmap->{addresses}->{$wrong_address} = $real_address; | |
| 351 | + | |
| 352 | + } elsif (/^(.+)<([^\s]+)>\s*([^\s].*)<([^\s]+)>$/) { | |
| 353 | + my $real_name = $1; | |
| 354 | + my $real_address = $2; | |
| 355 | + my $wrong_name = $3; | |
| 356 | + my $wrong_address = $4; | |
| 357 | + | |
| 358 | + $real_name =~ s/\s+$//; | |
| 359 | + $wrong_name =~ s/\s+$//; | |
| 360 | + | |
| 361 | + $mailmap->{names}->{format_email($wrong_name,$wrong_address,1)} = $real_name; | |
| 362 | + $mailmap->{addresses}->{format_email($wrong_name,$wrong_address,1)} = $real_address; | |
| 320 | 363 | } |
| 321 | 364 | } |
| 322 | − close($mailmap); | |
| 365 | + close($mailmap_file); | |
| 366 | + | |
| 367 | + return $mailmap; | |
| 323 | 368 | } |
| 324 | 369 | |
| 325 | 370 | ## use the filenames on the command line or find the filenames in the patchfiles |
| @@ -1061,30 +1106,58 @@ sub which_conf { · 735 unmodified lines | ||
| 1061 | 1106 | return ""; |
| 1062 | 1107 | } |
| 1063 | 1108 | |
| 1064 | −sub mailmap { | |
| 1065 | − my (@lines) = @_; | |
| 1066 | − my %hash; | |
| 1109 | +sub mailmap_email { | |
| 1110 | + my $line = shift; | |
| 1067 | 1111 | |
| 1068 | − foreach my $line (@lines) { | |
| 1069 | 1112 | my ($name, $address) = parse_email($line); |
| 1070 | − if (!exists($hash{$name})) { | |
| 1071 | − $hash{$name} = $address; | |
| 1072 | − } elsif ($address ne $hash{$name}) { | |
| 1073 | − $address = $hash{$name}; | |
| 1074 | − $line = format_email($name, $address, $email_usename); | |
| 1075 | − } | |
| 1076 | − if (exists($mailmap{$name})) { | |
| 1077 | − my $obj = $mailmap{$name}; | |
| 1078 | − foreach my $map_address (@$obj) { | |
| 1079 | − if (($map_address eq $address) && | |
| 1080 | − ($map_address ne $hash{$name})) { | |
| 1081 | − $line = format_email($name, $hash{$name}, $email_usename); | |
| 1113 | + my $email = format_email($name, $address, 1); | |
| 1114 | + my $real_name = $name; | |
| 1115 | + my $real_address = $address; | |
| 1116 | + | |
| 1117 | + if (exists $mailmap->{names}->{$email} || exists $mailmap->{addresses}->{$email}) { | |
| 1118 | + if (exists $mailmap->{names}->{$email}) { | |
| 1119 | + $real_name = $mailmap->{names}->{$email}; | |
| 1120 | + } | |
| 1121 | + if (exists $mailmap->{addresses}->{$email}) { | |
| 1122 | + $real_address = $mailmap->{addresses}->{$email}; | |
| 1123 | + } | |
| 1124 | + } else { | |
| 1125 | + if (exists $mailmap->{names}->{$address}) { | |
| 1126 | + $real_name = $mailmap->{names}->{$address}; | |
| 1127 | + } | |
| 1128 | + if (exists $mailmap->{addresses}->{$address}) { | |
| 1129 | + $real_address = $mailmap->{addresses}->{$address}; | |
| 1082 | 1130 | } |
| 1083 | − } | |
| 1084 | 1131 | } |
| 1132 | + return format_email($real_name, $real_address, 1); | |
| 1133 | +} | |
| 1134 | + | |
| 1135 | +sub mailmap { | |
| 1136 | + my (@addresses) = @_; | |
| 1137 | + | |
| 1138 | + my @ret = (); | |
| 1139 | + foreach my $line (@addresses) { | |
| 1140 | + push(@ret, mailmap_email($line), 1); | |
| 1085 | 1141 | } |
| 1086 | 1142 | |
| 1087 | − return @lines; | |
| 1143 | + merge_by_realname(@ret) if $email_remove_duplicates; | |
| 1144 | + | |
| 1145 | + return @ret; | |
| 1146 | +} | |
| 1147 | + | |
| 1148 | +sub merge_by_realname { | |
| 1149 | + my %address_map; | |
| 1150 | + my (@emails) = @_; | |
| 1151 | + foreach my $email (@emails) { | |
| 1152 | + my ($name, $address) = parse_email($email); | |
| 1153 | + if (!exists $address_map{$name}) { | |
| 1154 | + $address_map{$name} = $address; | |
| 1155 | + } else { | |
| 1156 | + $address = $address_map{$name}; | |
| 1157 | + $email = format_email($name,$address,1); | |
| 1158 | + } | |
| 1159 | + } | |
| 1160 | + | |
| 1088 | 1161 | } |
| 1089 | 1162 | |
| 1090 | 1163 | sub git_execute_cmd { |
| @@ -1636,9 +1709,7 @@ sub vcs_assign { · 545 unmodified lines | ||
| 1636 | 1709 | $divisor = 1; |
| 1637 | 1710 | } |
| 1638 | 1711 | |
| 1639 | − if ($email_remove_duplicates) { | |
| 1640 | − @lines = mailmap(@lines); | |
| 1641 | − } | |
| 1712 | + @lines = mailmap(@lines); | |
| 1642 | 1713 | |
| 1643 | 1714 | return if (@lines <= 0); |
| 1644 | 1715 | |