70 lines
		
	
	
	
		
			1.3 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			70 lines
		
	
	
	
		
			1.3 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable file
		
	
	
	
	
| #!/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";
 | |
| }
 |