| #!/usr/bin/perl |
| |
| use warnings 'all'; |
| use strict; |
| use Getopt::Long; |
| |
| my $match_emails; |
| my $match_names; |
| my $order_by = 'count'; |
| Getopt::Long::Configure(qw(bundling)); |
| GetOptions( |
| 'emails|e!' => \$match_emails, |
| 'names|n!' => \$match_names, |
| 'count|c' => sub { $order_by = 'count' }, |
| 'time|t' => sub { $order_by = 'stamp' }, |
| ) or exit 1; |
| $match_emails = 1 unless $match_names; |
| |
| my $email = {}; |
| my $name = {}; |
| |
| open(my $fh, '-|', "git log --format='%at <%aE> %aN'"); |
| while(<$fh>) { |
| my ($t, $e, $n) = /(\S+) <(\S+)> (.*)/; |
| mark($email, $e, $n, $t); |
| mark($name, $n, $e, $t); |
| } |
| close($fh); |
| |
| if ($match_emails) { |
| foreach my $e (dups($email)) { |
| foreach my $n (vals($email->{$e})) { |
| show($n, $e, $email->{$e}->{$n}); |
| } |
| print "\n"; |
| } |
| } |
| if ($match_names) { |
| foreach my $n (dups($name)) { |
| foreach my $e (vals($name->{$n})) { |
| show($n, $e, $name->{$n}->{$e}); |
| } |
| print "\n"; |
| } |
| } |
| exit 0; |
| |
| sub mark { |
| my ($h, $k, $v, $t) = @_; |
| my $e = $h->{$k}->{$v} ||= { count => 0, stamp => 0 }; |
| $e->{count}++; |
| $e->{stamp} = $t unless $t < $e->{stamp}; |
| } |
| |
| sub dups { |
| my $h = shift; |
| return grep { keys($h->{$_}) > 1 } keys($h); |
| } |
| |
| sub vals { |
| my $h = shift; |
| return sort { |
| $h->{$b}->{$order_by} <=> $h->{$a}->{$order_by} |
| } keys($h); |
| } |
| |
| sub show { |
| my ($n, $e, $h) = @_; |
| print "$n <$e> ($h->{$order_by})\n"; |
| } |