7 my ($committer, $patch, $author);
12 $Text::Wrap::columns = 80;
14 my ($rank, $ta, $ack, $who, $tap, $update) = (0) x 6;
15 my ($author_file, $percentage, $cumulative, $reverse);
16 my (%authors, %untraced, %patchers, %committers, %real_names);
17 my ( $from_commit, $to_commit );
19 my $result = GetOptions (
23 "thanks-applied" => \$ta,
29 "authors=s" => \$author_file,
30 "percentage" => \$percentage, # show as %age
31 "cumulative" => \$cumulative,
32 "reverse" => \$reverse,
33 "from=s" => \$from_commit,
34 "to=s" => \$to_commit,
39 my $has_from_commit = defined $from_commit ? 1 : 0;
41 if ( !$result # GetOptions failed
42 or ( $rank + $ta + $who + $ack + $tap + $update != 1 ) # use one and one exactly 'mode'
43 or !( scalar @ARGV + $has_from_commit ) # gitlog provided from --from or stdin
48 $author_file ||= './AUTHORS';
49 die "Can't locate '$author_file'. Specify it with '--authors <path>'."
50 unless -f $author_file;
52 my ( $map, $preferred_email_or_github ) = generate_known_author_map();
54 my $preserve_case = $update ? 1 : 0;
55 my $AUTHORS_header = read_authors_file($author_file, $preserve_case);
59 display_ordered(\%patchers);
62 display_ordered(\%committers);
64 parse_commits_authors();
65 display_test_output(\%patchers, \%authors, \%real_names);
68 display_missing_authors(\%patchers, \%authors, \%real_names);
71 list_authors(\%patchers, \%authors);
73 update_authors_files( \%authors, $map, $preferred_email_or_github, $author_file );
83 Usage: $0 [modes] [modifiers] <git-log-output-file>
86 --who # show list of unique authors by full name
87 --rank # rank authors by patches
88 --thanks-applied # ranks committers of others' patches
89 --missing # display authors not in AUTHORS
90 --tap # show authors present/missing as TAP
91 --update # update the AUTHORS file with missing
94 --authors <authors-file> # path to authors file (default: ./AUTHORS)
95 --percentage # show rankings as percentages
96 --cumulative # show rankings cumulatively
97 --reverse # show rankings in reverse
98 --from # git commit ID used for 'git log' source (use file from STDIN when missing)
99 --to[=HEAD] # git commit ID used for 'git log' destination, default to HEAD.
103 \$ perl Porting/checkAUTHORS.pl --who --from=v5.31.6 --to=v5.31.7
104 \$ perl Porting/checkAUTHORS.pl --rank --percentage --from=v5.31.6
105 \$ perl Porting/checkAUTHORS.pl --thanks-applied --from=v5.31.6
106 \$ perl Porting/checkAUTHORS.pl --missing --from=v5.31.6
107 \$ perl Porting/checkAUTHORS.pl --tap --from=v5.31.6
108 \$ perl Porting/checkAUTHORS.pl --update --from=v5.31.6
110 or the split int two and generate your own git log output
112 Generate git-log-output-file with git log --pretty=fuller rev1..rev2
113 (or pipe by specifying '-' for stdin). For example:
114 \$ git log --pretty=fuller v5.31.6..v5.31.7 > gitlog
115 \$ perl Porting/checkAUTHORS.pl --rank --percentage gitlog
122 my ($patchers, $authors) = @_;
123 binmode(STDOUT, ":utf8");
124 print wrap '', '', join(', ', Unicode::Collate->new(level => 1)->sort(
125 map { $authors->{$_} }
126 grep { length $_ > 1 } # skip the exception '!' and '?'
127 keys %$patchers)) . ".\n";
130 # use --from [and --to] if provided
131 # otherwise fallback to stdin for backward compatibility
133 if ( length $from_commit ) {
134 my ( $from, $to ) = ( $from_commit, $to_commit );
136 my $gitlog = [ qx{git log --pretty=fuller $from..$to} ];
137 die "git log failed: $!" unless $? == 0;
145 my ( $process ) = @_;
147 $process //= \&process; # default processor
149 my $git_log = _git_log();
151 my @lines = split( /^commit\s*/sm, join( '', $git_log->@* ) );
154 next if m/^(\S*?)^Merge:/ism; # skip merge commits
155 if (m/^(.*?)^Author:\s*(.*?)^AuthorDate:\s*.*?^Commit:\s*(.*?)^(.*)$/gism) {
158 ( $patch, $author, $committer ) = ( $1, $2, $3 );
160 unless ($author) { die $_ }
162 unless ($committer) { die $_ }
164 $process->( $committer, $patch, $author );
166 die "XXX $_ did not match";
173 # just grab authors. Quicker than parse_commits
175 sub parse_commits_authors {
177 my $git_log = _git_log();
179 foreach ($git_log->@*) {
180 next unless /^Author:\s*(.*)$/;
182 $author = _raw_address($author);
183 $patchers{$author}++;
189 sub generate_known_author_map {
192 my %preferred_email_or_github;
194 my $previous_name = "";
195 my $previous_preferred_contact = "";
203 if ( my ( $name, $contact ) = /^\s*([^#\s]\S*)\s+(.*\S)/ ) {
205 $name =~ s/^\\043/#/;
206 # use the previous stored email if the line starts by a '+'
207 if ( $name eq '+' ) {
208 $name = $previous_name;
211 $previous_name = $name;
212 $previous_preferred_contact = $contact;
213 if ( index($name, '@' ) > 0 ) {
214 # if name is an email, then this is our preferred email... legacy list
215 $previous_preferred_contact = $name;
219 $map{$contact} = $name;
221 if ( $contact ne $previous_preferred_contact ) {
222 $preferred_email_or_github{$contact} = $previous_preferred_contact;
224 if ( $name ne '+' ) {
225 $preferred_email_or_github{$name} = $previous_preferred_contact;
231 # Email addresses for we do not have names.
235 "bah\100longitude.com",
236 "bbucklan\100jpl-devvax.jpl.nasa.gov",
238 "bob\100starlabs.net",
239 "cygwin\100cygwin.com",
240 "david\100dhaller.de", "erik\100cs.uni-jena.de", "info\100lingo.kiev.ua", # Lingo Translation agency
241 "jms\100mathras.comcast.net",
242 "premchai21\100yahoo.com",
244 "raf\100tradingpost.com.au",
245 "smoketst\100hp46t243.cup.hp.com", "root\100chronos.fi.muni.cz", # no clue - jrv 20090803
246 "gomar\100md.media-web.de", # no clue - jrv 20090803
247 "data-drift\100so.uio.no", # no data. originally private message from 199701282014.VAA12645@selters.uio.no
248 "arbor\100al37al08.telecel.pt"
249 , # reported perlbug ticket 5196 - no actual code contribution. no real name - jrv 20091006
250 "oracle\100pcr8.pcr.com", # Reported perlbug ticket 1015 - no patch - Probably Ed Eddington ed@pcr.com
251 "snaury\100gmail.com", # Reported cpan ticket 35943, with patch for fix
255 # Email addresses for people that don't have an email address in AUTHORS
256 # Presumably deliberately?
261 # Nick Ing-Simmons has passed away (2006-09-25).
262 "nick\100ing-simmons.net",
263 "nik\100tiuk.ti.com",
264 "nick.ing-simmons\100elixent.com",
265 "nick\100ni-s.u-net.com",
266 "nick.ing-simmons\100tiuk.ti.com",
268 # Iain Truskett has passed away (2003-12-29).
269 "perl\100dellah.anu.edu.au", "spoon\100dellah.org", "spoon\100cpan.org",
272 "me-02\100ton.iguana.be", "perl-5.8.0\100ton.iguana.be", "perl5-porters\100ton.iguana.be",
275 "beau\100beaucox.com",
278 "ml-perl\100thepierianspring.org",
281 "pravus\100cpan.org",
283 # perl internal addresses
284 "perl5-porters\100africa.nicoh.com",
285 "perlbug\100perl.org",,
286 "perl5-porters.nicoh.com",
287 "perlbug-followup\100perl.org",
288 "perlbug-comment\100perl.org",
289 "bug-module-corelist\100rt.cpan.org",
290 "bug-storable\100rt.cpan.org",
291 "bugs-perl5\100bugs6.perl.org",
293 "unknown\100unknown",
294 "unknown\100longtimeago",
295 "unknown\100perl.org",
300 return ( \%map, \%preferred_email_or_github );
303 sub read_authors_file {
304 my ( $filename, $preserve_case ) = @_;
305 return unless defined $filename;
311 open my $fh, '<', $filename or die "Can't open $filename: $!";
312 binmode $fh, ':encoding(UTF-8)';
316 do { $in_header = 0; next } if /^-- /;
317 if (/^([^<]+)<([^>]+)>/) {
319 my ($name, $email) = ($1, $2);
321 $raw{$email} = $name;
323 } elsif ( /^([^@]+)\s+(\@\S+)\s*$/ ) {
324 my ($name, $github) = ($1, $2);
326 $raw{$github} = $name;
328 } elsif (/^([- .'\w]+)[\t\n]/) {
332 } elsif ( length $_ ) {
334 warn "Can't parse line '$_'";
340 push @headers, $_ if $in_header;
343 foreach my $contact ( sort keys %raw ) {
344 print "E-mail $contact occurs $count{$contact} times\n" if $count{$contact} > 1;
345 my $lc = lc $contact;
346 my $key = $preserve_case ? $contact : $lc;
347 $authors{ $map->{$lc} || $key } = $raw{$contact};
349 $authors{$_} = $_ for qw(? !);
351 push @headers, '-- ', "\n";
353 return join( '', @headers );
356 sub update_authors_files {
357 my ( $authors, $known_authors, $preferred_email_or_github, $author_file ) = @_;
359 die qq[Cannot find AUTHORS file '$author_file'] unless -f $author_file;
360 binmode(STDOUT, ":utf8");
362 # add missing authors from the recent commits
363 _detect_new_authors_from_recent_commit( $authors, $known_authors );
365 my @author_names = sort { $a cmp $b } values %$authors;
366 my $maxlen = length [ sort { length $b <=> length $a } @author_names ]->[0];
369 foreach my $github_or_email ( sort keys %authors ) {
371 next if length $github_or_email == 1;
373 my $name = $authors{$github_or_email};
376 #$github_or_email = $known_authors->{ $github_or_email } // $github_or_email;
377 $github_or_email = $preferred_email_or_github->{ $github_or_email } // $github_or_email;
379 if ( index( $github_or_email, '@' ) != 0 ) { # preserve '<>' for unicode consortium
380 $github_or_email = '<' . $github_or_email . '>';
383 push @list, sprintf( "%-${maxlen}s %s\n", $name, $github_or_email);
386 # preserve the untraced authors :-) [without email or GitHub account]
387 push @list, map { "$_\n" } keys %untraced;
390 open my $fh, '>', $author_file or die "Can't open $author_file: $!";
391 binmode $fh, ':raw:encoding(UTF-8)';
393 print {$fh} $AUTHORS_header;
395 map { print {$fh} $_ } sort { lc $a cmp lc $b } @list;
404 # read all recent commits and check if the author email is known
405 # if the email is unknown add the author's GitHub account if possible or his email
406 sub _detect_new_authors_from_recent_commit {
407 my ( $authors, $known_authors ) = @_;
409 my $check_if_email_known = sub {
412 my $preferred = $map->{$email} // $map->{lc $email}
413 // $preferred_email_or_github->{$email}
414 // $preferred_email_or_github->{lc $email}
417 return $authors{$preferred} || $authors{ lc $preferred } ? 1 : 0;
420 my $already_checked = {};
422 my ( $committer, $patch, $author ) = @_;
424 foreach my $person ( $author, $committer ) {
425 next unless length $person;
426 next if $already_checked->{$person};
427 $already_checked->{$person} = 1;
429 my $is_author = $person eq $author;
431 if ( $person =~ m{^(.+)\s+<(.+)>$} ) {
432 my ( $name, $email ) = ( $1, $2 );
434 # skip unicode consortium and bad emails
435 if ( index( $email, '@' ) <= 0 ) {
436 warn "# Skipping new author: $person - bad email";
440 next if $check_if_email_known->( $email );
442 # for new users we would prefer using the GitHub account
443 my $github_or_email = _commit_to_github_id( $patch, $is_author ) // $email;
445 next if $check_if_email_known->( $github_or_email );
447 print "# Detected a new author: $name using email $email [ $github_or_email ]\n";
448 $authors{$github_or_email} = $name; # add it to the list of authors
450 warn "Fail to parse author: $person";
455 parse_commits( $process );
460 sub _commit_to_github_id {
461 my ( $commit, $is_author ) = @_;
463 chomp $commit if defined $commit;
464 return unless length $commit;
466 eval { require HTTP::Tiny; 1 } or do {
467 warn "HTTP::Tiny is missing, cannot detect GitHub account from commit id.";
469 *_commit_to_github_id = sub {};
473 my $github_url_for_commit = q[https://github.com/Perl/perl5/commit/] . $commit;
474 my $response = HTTP::Tiny->new->get( $github_url_for_commit );
476 if ( ! $response->{success} ) {
477 warn "HTTP Request Failed: '$github_url_for_commit'";
481 my $content = $response->{content} // '';
483 # poor man scrapping - probably have to be improved over time
484 # try to parse something like: <a href="/Perl/perl5/commits?author=ThisIsMyGitHubID"
485 my @github_ids; # up to two entries author and committer
486 while ( $content =~ s{\Q<a href="/Perl/perl5/commits?author=\E(.+)"}{} ) {
487 push @github_ids, '@' . $1;
490 warn "Found more than two github ids for $github_url_for_commit" if scalar @github_ids > 2;
492 return $github_ids[0] if $is_author;
493 if ( !$is_author && scalar @github_ids >= 2 ) {
494 return $github_ids[1]; # committer is the second entry
497 return $github_ids[0];
501 sub display_test_output {
502 my $patchers = shift;
504 my $real_names = shift;
506 printf "1..%d\n", scalar keys %$patchers;
508 foreach my $email ( sort keys %$patchers ) {
510 if ($authors->{$email}) {
511 print "ok $count - ".$real_names->{$email} ." $email\n";
513 print "not ok $count - Contributor not found in AUTHORS: $email ".($real_names->{$email} || '???' )."\n";
514 print STDERR ($real_names->{$email} || '???' )." <$email> not found in AUTHORS\n";
521 sub display_missing_authors {
522 my $patchers = shift;
524 my $real_names = shift;
526 foreach ( sort keys %$patchers ) {
527 next if $authors->{$_};
529 # Sort by number of patches, then name.
530 $missing{ $patchers{$_} }->{$_}++;
532 foreach my $patches ( sort { $b <=> $a } keys %missing ) {
533 print "\n\n=head1 $patches patch(es)\n\n";
534 foreach my $author ( sort keys %{ $missing{$patches} } ) {
535 my $xauthor = $author;
536 $xauthor =~ s/@/\\100/g; # xxx temp hack
537 print "" . ( $real_names->{$author} || $author ) . "\t\t\t<" . $xauthor . ">\n";
544 sub display_ordered {
549 while ( my ( $name, $count ) = each %$what ) {
550 push @{ $sorted[$count] }, $name;
555 return unless @sorted;
557 foreach my $i ( $reverse ? 0 .. $#sorted : reverse 0 .. $#sorted ) {
558 next unless $sorted[$i];
560 $sum += $i * @{ $sorted[$i] };
562 # Value to display is either this one, or the cumulative sum.
563 my $value = $cumulative ? $sum : $i;
565 $prefix = sprintf "%6.2f:\t", 100 * $value / $total;
567 $prefix = "$value:\t";
569 print wrap ( $prefix, "\t", join( " ", sort @{ $sorted[$i] } ), "\n" );
576 my ( $committer, $patch, $author ) = @_;
577 return unless $author;
578 return unless $committer;
580 $author = _raw_address($author);
581 $patchers{$author}++;
583 $committer = _raw_address($committer);
584 if ( $committer ne $author ) {
586 # separate commit credit only if committing someone else's patch
587 $committers{$committer}++;
596 if ($addr =~ /(?:\\?")?\s*\(via RT\) <perlbug-followup\@perl\.org>$/p) {
597 my $name = ${^PREMATCH};
598 $addr = 'perlbug-followup@perl.org';
600 # Try to find the author
602 if (exists $map->{$name}) {
603 $addr = $map->{$name};
604 $real_name = $authors{$addr};
607 while (my ($email, $author_name) = each %authors) {
608 if ($name eq $author_name) {
616 elsif ( $addr =~ /<.*>/ ) {
617 $addr =~ s/^\s*(.*)\s*<\s*(.*?)\s*>.*$/$2/;
620 $addr =~ s/\[mailto://;
623 $addr = $map->{$addr} || $addr;
624 $addr =~ s/\\100/@/g; # Sometimes, there are encoded @ signs in the git log.
626 if ($real_name) { $real_names{$addr} = $real_name }
635 # List of mappings. First entry the "correct" email address or GitHub account,
636 # as appears in the AUTHORS file. Other lines are "alias" mapped to it.
638 # If the "correct" email address is a '+', the entry above it is reused;
639 # this for addresses with more than one alias.
641 # Note that all entries are in lowercase. Further, no '@' signs should
642 # appear; use \100 instead.
648 + bytesguy\100users.noreply.github.com
649 + git\100ahartley.com
650 adi enache\100rdslink.ro
651 alanbur alan.burlison\100sun.com
652 + alan.burlison\100uk.sun.com
653 + aburlison\100cix.compulink.co.uk
654 ams ams\100toroid.org
657 + atoomic\100cpan.org
658 + cpan\100atoomic.org
659 + nicolas\100atoomic.org
660 chip chip\100pobox.com
662 + salzench\100nielsenmedia.com
663 + chip\100atlantic.net
664 + chip\100rio.atlantic.net
665 + salzench\100dun.nielsen.com
666 + chip\100ci005.sv2.upperbeyond.com
667 craigb craigberry\100mac.com
668 + craig.berry\100metamorgs.com
669 + craig.berry\100signaltreesolutions.com
670 + craig.berry\100psinetcs.com
671 + craig.a.berry\100gmail.com
673 davem davem\100iabyn.nospamdeletethisbit.com
674 + davem\100fdgroup.com
676 + davem\100fdgroup.co.uk
677 + davem\100fdisolutions.com
679 demerphq demerphq\100gmail.com
680 + yves.orton\100de.mci.com
681 + yves.orton\100mciworldcom.de
682 + yves.orton\100booking.com
683 + demerphq\100dromedary.booking.com
684 + demerphq\100gemini.(none)
685 + demerphq\100camel.booking.com
686 + demerphq\100hotmail.com
687 doughera doughera\100lafayette.edu
688 + doughera\100lafcol.lafayette.edu
689 + doughera\100fractal.phys.lafayette.edu
690 + doughera.lafayette.edu
691 + doughera\100newton.phys.lafayette.edu
693 gbarr gbarr\100pobox.com
694 + bodg\100tiuk.ti.com
696 + graham.barr\100tiuk.ti.com
697 + gbarr\100monty.mutatus.co.uk
698 gisle gisle\100aas.no
699 + gisle\100activestate.com
701 + aas\100bergen.sn.no
702 gsar gsar\100cpan.org
703 + gsar\100activestate.com
704 + gsar\100engin.umich.edu
706 + hv\100crypt.compulink.co.uk
709 + jhietaniemi\100gmail.com
711 + jhi\100alpha.hut.fi
714 + jarkko.hietaniemi\100nokia.com
715 + jarkko.hietaniemi\100cc.hut.fi
716 + jarkko.hietaniemi\100booking.com
717 jesse jesse\100fsck.com
718 + jesse\100bestpractical.com
720 merijn h.m.brand\100xs4all.nl
721 + h.m.brand\100procura.nl
722 + merijn.brand\100procura.nl
723 + h.m.brand\100hccnet.nl
724 + merijn\100l1.procura.nl
725 + merijn\100a5.(none)
726 + perl5\100tux.freedom.nl
727 mhx mhx-perl\100gmx.net
730 mst mst\100shadowcat.co.uk
731 + matthewt\100hercule.scsys.co.uk
732 nicholas nick\100ccl4.org
733 + nick\100unfortu.net
734 + nick\100talking.bollo.cx
735 + nick\100plum.flirble.org
736 + nick\100babyhippo.co.uk
737 + nick\100bagpuss.unfortu.net
738 + nick\100babyhippo.com
739 + nicholas\100dromedary.ams6.corp.booking.com
740 + Nicholas Clark (sans From field in mail header)
741 pudge pudge\100pobox.com
742 rgs rgs@consttype.org
743 + rgarciasuarez\100free.fr
744 + rgarciasuarez\100mandrakesoft.com
745 + rgarciasuarez\100mandriva.com
746 + rgarciasuarez\100gmail.com
747 + raphel.garcia-suarez\100hexaflux.com
748 sky artur\100contiller.se
750 + arthur\100contiller.se
751 smueller smueller\100cpan.org
752 + 7k8lrvf02\100sneakemail.com
753 + kjx9zthh3001\100sneakemail.com
754 + dtr8sin02\100sneakemail.com
755 + rt8363b02\100sneakemail.com
756 + o6hhmk002\100sneakemail.com
757 + l2ot9pa02\100sneakemail.com
758 + wyp3rlx02\100sneakemail.com
759 + 0mgwtfbbq\100sneakemail.com
760 + xyey9001\100sneakemail.com
761 steveh steve.m.hay\100googlemail.com
762 + stevehay\100planit.com
763 + steve.hay\100uk.radan.com
764 stevep steve\100fisharerojo.org
765 + steve.peters\100gmail.com
766 + root\100dixie.cscaper.com
767 timb Tim.Bunce\100pobox.com
768 + tim.bunce\100ig.co.uk
769 tonyc tony\100develop-help.com
770 + tony\100openbsd32.tony.develop-help.com
771 + tony\100saturn.(none)
776 \043####\100juerd.nl juerd\100cpan.org
777 + juerd\100c3.convolution.nl
778 + juerd\100convolution.nl
779 a.r.ferreira\100gmail.com aferreira\100shopzilla.com
780 abe\100ztreet.demon.nl abeltje\100cpan.org
781 abela\100hsc.fr abela\100geneanet.org
782 abigail\100abigail.be abigail\100foad.org
783 + abigail\100abigail.nl
785 aburt\100isis.cs.du.edu isis!aburt
786 ach\100mpe.mpg.de ach\100rosat.mpe-garching.mpg.de
787 adavies\100ptc.com alex.davies\100talktalk.net
788 ajohnson\100nvidia.com ajohnson\100wischip.com
789 + anders\100broadcom.com
790 alexm\100netli.com alexm\100w-m.ru
791 alex-p5p\100earth.li alex\100rcon.rog
792 alexmv\100mit.edu alex\100chmrr.net
793 alian\100cpan.org alian\100alianwebserver.com
794 allen\100grumman.com allen\100gateway.grumman.com
795 allen\100huarp.harvard.edu nort\100bottesini.harvard.edu
797 allens\100cpan.org easmith\100beatrice.rutgers.edu
798 + root\100dogberry.rutgers.edu
799 ambs\100cpan.org hashashin\100gmail.com
800 andrea a.koenig@mind.de
801 + andreas.koenig\100anima.de
802 + andreas.koenig.gmwojprw\100franz.ak.mind.de
803 + andreas.koenig.7os6vvqr\100franz.ak.mind.de
804 + a.koenig\100mind.de
805 + k\100anna.in-berlin.de
807 + koenig\100anna.mind.de
809 + root\100ak-71.mind.de
810 + root\100ak-75.mind.de
811 + k\100sissy.in-berlin.de
812 + a.koenig\100kulturbox.de
813 + k\100sissy.in-berlin.de
814 + root\100dubravka.in-berlin.de
815 anno4000\100lublin.zrz.tu-berlin.de anno4000\100mailbox.tu-berlin.de
816 + siegel\100zrz.tu-berlin.de
817 apocal@cpan.org perl\1000ne.us
818 arnold\100gnu.ai.mit.edu arnold\100emoryu2.arpa
819 + gatech!skeeve!arnold
820 arodland\100cpan.org andrew\100hbslabs.com
821 arussell\100cs.uml.edu adam\100adam-pc.(none)
822 ash\100cpan.org ash_cpan\100firemirror.com
823 avar avar\100cpan.org
824 + avarab\100gmail.com
825 bailey\100newman.upenn.edu bailey\100hmivax.humgen.upenn.edu
826 + bailey\100genetics.upenn.edu
827 + bailey.charles\100gmail.com
828 bah\100ecnvantage.com bholzman\100longitude.com
829 barries\100slaysys.com root\100jester.slaysys.com
830 bkedryna\100home.com bart\100cg681574-a.adubn1.nj.home.com
831 bcarter\100gumdrop.flyinganvil.org q.eibcartereio.=~m-b.{6}-cgimosx\100gumdrop.flyinganvil.org
832 ben_tilly\100operamail.com btilly\100gmail.com
833 + ben_tilly\100hotmail.com
834 ben\100morrow.me.uk mauzo\100csv.warwick.ac.uk
836 bepi\100perl.it enrico.sorcinelli\100gmail.com
837 bert\100alum.mit.edu bert\100genscan.com
838 bigbang7\100gmail.com ddascalescu+github\100gmail.com
839 blgl\100stacken.kth.se blgl\100hagernas.com
840 + 2bfjdsla52kztwejndzdstsxl9athp\100gmail.com
841 brian.d.foy\100gmail.com bdfoy\100cpan.org
842 BQW10602\100nifty.com sadahiro\100cpan.org
843 bulk88\100hotmail.com bulk88
845 chad.granum\100dreamhost.com exodist7\100gmail.com
846 choroba\100cpan.org choroba\100weed.(none)
847 + choroba\100matfyz.cz
848 chromatic\100wgz.org chromatic\100rmci.net
849 ckuskie\100cadence.com colink\100perldreamer.com
850 claes\100surfar.nu claes\100versed.se
851 clintp\100geeksalad.org cpierce1\100ford.com
852 clkao\100clkao.org clkao\100bestpractical.com
853 corion\100corion.net corion\100cpan.org
855 cp\100onsitetech.com publiustemp-p5p\100yahoo.com
856 + publiustemp-p5p3\100yahoo.com
857 cpan\100audreyt.org autrijus\100egb.elixus.org
858 + autrijus\100geb.elixus.org
859 + autrijus\100gmail.com
860 + autrijus\100ossf.iis.sinica.edu.tw
861 + autrijus\100autrijus.org
862 + audreyt\100audreyt.org
863 cpan\100ton.iguana.be me-01\100ton.iguana.be
864 crt\100kiski.net perl\100ctweten.amsite.com
866 dairiki\100dairiki.org dairiki at dairiki.org
867 dagolden\100cpan.org xdaveg\100gmail.com
869 damian\100conway.org damian\100cs.monash.edu.au
870 dan\100sidhe.org sugalsd\100lbcc.cc.or.us
871 + sugalskd\100osshe.edu
872 daniel\100bitpusher.com daniel\100biz.bitpusher.com
873 dave\100mag-sol.com dave\100dave.org.uk
874 david.dyck\100fluke.com dcd\100tc.fluke.com
875 david\100justatheory.com david\100wheeler.net
876 + david\100kineticode.com
877 + david\100wheeler.com
878 + david\100wheeler.net
879 whatever\100davidnicol.com davidnicol\100gmail.com
880 dennis\100booking.com dennis\100camel.ams6.corp.booking.com
881 + dennis.kaarsemaker\100booking.com
882 + dennis\100kaarsemaker.net
883 dev-perl\100pimb.org knew-p5p\100pimb.org
884 + lists-p5p\100pimb.org
885 djberg86\100attbi.com djberg96\100attbi.com
886 dk\100tetsuo.karasik.eu.org dmitry\100karasik.eu.org
887 dma+github@stripysock.com dominichamon@users.noreply.github.com
888 dom\100earth.li dom\100semmle.com
889 domo\100computer.org shouldbedomo\100mac.com
890 + domo\100slipper.ip.lu
892 dougm\100covalent.net dougm\100opengroup.org
894 dougw\100cpan.org doug_wilson\100intuit.com
895 dwegscheid\100qtm.net wegscd\100whirlpool.com
896 edwardp\100excitehome.net epeschko\100den-mdev1
897 + epeschko\100elmer.tci.com
899 egf7\100columbia.edu efifer\100sanwaint.com
900 eggert\100twinsun.com eggert\100sea.sm.unisys.com
901 etj\100cpan.org mohawk2\100users.noreply.github.com
903 fugazi\100zyx.net larrysh\100cpan.org
904 + lshatzer\100islanddata.com
906 gbacon\100itsc.uah.edu gbacon\100adtrn-srv4.adtran.com
907 gerberb\100zenez.com root\100devsys0.zenez.com
908 gfuji\100cpan.org g.psy.va\100gmail.com
909 genesullivan50\100yahoo.com gsullivan\100cpan.org
910 gerard\100ggoossen.net gerard\100tty.nl
911 gibreel\100pobox.com stephen.zander\100interlock.mckesson.com
913 gideon\100cpan.org gidisrael\100gmail.com
914 gnat\100frii.com gnat\100prometheus.frii.com
915 gp\100familiehaase.de gerrit\100familiehaase.de
916 grazz\100pobox.com grazz\100nyc.rr.com
917 gward\100ase.com greg\100bic.mni.mcgill.ca
918 haggai\100cpan.org alanhaggai\100alanhaggai.org
919 + alanhaggai\100gmail.com
920 hansmu\100xs4all.nl hansm\100icgroup.nl
924 + hansm\100euronet.nl
926 hio\100ymir.co.jp hio\100hio.jp
927 hops\100sco.com hops\100scoot.pdev.sco.com
929 ian.goodacre\100xtra.co.nz ian\100debian.lan
930 ingo_weinhold\100gmx.de bonefish\100cs.tu-berlin.de
932 james\100mastros.biz theorb\100desert-island.me.uk
933 jan\100jandubois.com jand\100activestate.com
934 + jan.dubois\100ibm.net
935 japhy\100pobox.com japhy\100pobox.org
936 + japhy\100perlmonk.org
938 + jeffp\100crusoe.net
939 jari.aalto\100poboxes.com jari.aalto\100cante.net
940 jarausch\100numa1.igpm.rwth-aachen.de helmutjarausch\100unknown
941 jasons\100cs.unm.edu jasons\100sandy-home.arc.unm.edu
942 jbuehler\100hekimian.com jhpb\100hekimian.com
943 jcromie\100cpan.org jcromie\100100divsol.com
944 + jim.cromie\100gmail.com
945 jd\100cpanel.net lightsey\100debian.org
947 + john\100nixnuts.net
948 jdhedden\100cpan.org jerry\100hedden.us
949 + jdhedden\1001979.usna.com
950 + jdhedden\100gmail.com
951 + jdhedden\100yahoo.com
952 + jhedden\100pn100-02-2-356p.corp.bloomberg.com
953 + jdhedden\100solydxk
954 jeremy\100zawodny.com jzawodn\100wcnet.org
955 jesse\100sig.bsh.com jesse\100ginger
956 jfriedl\100yahoo.com jfriedl\100yahoo-inc.com
957 jfs\100fluent.com jfs\100jfs.fluent.com
958 jhannah\100mutationgrid.com jay\100jays.net
959 + jhannah\100omnihotels.com
960 jidanni\100jidanni.org jidanni\100hoffa.dreamhost.com
961 jjore\100cpan.org twists\100gmail.com
962 jkeenan\100cpan.org jkeen\100verizon.net
963 + jkeenan\100dromedary-001.ams6.corp.booking.com
964 jns\100integration-house.com jns\100gellyfish.com
965 + gellyfish\100gellyfish.com
966 john\100atlantech.com john\100titanic.atlantech.com
967 john\100johnwright.org john.wright\100hp.com
968 joseph\100cscaper.com joseph\1005sigma.com
969 joshua\100rodd.us jrodd\100pbs.org
970 jtobey\100john-edwin-tobey.org jtobey\100user1.channel1.com
971 jpeacock\100messagesystems.com john.peacock\100havurah-software.org
972 + jpeacock\100havurah-software.org
973 + jpeacock\100dsl092-147-156.wdc1.dsl.speakeasy.net
974 + jpeacock\100jpeacock-hp.doesntexist.org
975 + jpeacock\100cpan.org
976 + jpeacock\100rowman.com
977 james.schneider\100db.com jschneid\100netilla.com
978 jpl.jpl\100gmail.com jpl\100research.att.com
979 jql\100accessone.com jql\100jql.accessone.com
980 jsm28\100hermes.cam.ac.uk jsm28\100cam.ac.uk
982 kane\100dwim.org kane\100xs4all.net
987 keith.s.thompson\100gmail.com kst\100mib.org
988 ken\100mathforum.org kenahoo\100gmail.com
989 + ken.williams\100thomsonreuters.com
990 kentfredric\100gmail.com kentnl\100cpan.org
991 kmx\100volny.cz kmx\100volny.cz
993 kroepke\100dolphin-services.de kay\100dolphin-services.de
994 kst\100mib.org kst\100cts.com
996 kstar\100wolfetech.com kstar\100cpan.org
997 + kurt_starsinic\100ml.com
998 + kstar\100www.chapin.edu
999 + kstar\100chapin.edu
1000 larry\100wall.org lwall\100jpl-devvax.jpl.nasa.gov
1001 + lwall\100netlabs.com
1002 + larry\100netlabs.com
1004 + lwall\100scalpel.netlabs.com
1005 laszlo.molnar\100eth.ericsson.se molnarl\100cdata.tvnet.hu
1006 + ml1050\100freemail.hu
1007 lewart\100uiuc.edu lewart\100vadds.cvm.uiuc.edu
1008 + d-lewart\100uiuc.edu
1009 lindblad@gmx.com 52227507+apparluk\100users.noreply.github.com
1010 lkundrak\100v3.sk lubo.rintel\100gooddata.com
1011 lstein\100cshl.org lstein\100formaggio.cshl.org
1012 + lstein\100genome.wi.mit.edu
1013 l.mai\100web.de plokinom\100gmail.com
1014 lupe\100lupe-christoph.de lupe\100alanya.m.isar.de
1015 lutherh\100stratcom.com lutherh\100infinet.com
1016 mab\100wdl.loral.com markb\100rdcf.sm.unisys.com
1017 marcel\100codewerk.com gr\100univie.ac.at
1018 + hanekomu\100gmail.com
1019 marcgreen\100cpan.org marcgreen\100wpi.edu
1020 markleightonfisher\100gmail.com fisherm\100tce.com
1021 + mark-fisher\100mindspring.com
1022 mark.p.lutz\100boeing.com tecmpl1\100triton.ca.boeing.com
1023 marnix\100gmail.com pttesac!marnix!vanam
1024 marty+p5p\100kasei.com marty\100martian.org
1025 mats\100sm6sxl.net mats\100sm5sxl.net
1026 mbarbon\100dsi.unive.it mattia.barbon\100libero.it
1027 + mattia\100barbon.org
1028 mcmahon\100ibiblio.org mcmahon\100metalab.unc.edu
1029 me\100davidglasser.net glasser\100tang-eleven-seventy-nine.mit.edu
1030 merijnb\100iloquent.nl merijnb\100ms.com
1031 + merijnb\100iloquent.com
1032 merlyn\100stonehenge.com merlyn\100gadget.cscaper.com
1033 mestre.smash\100gmail.com smash\100cpan.org
1034 mgjv\100comdyn.com.au mgjv\100tradingpost.com.au
1035 mlh\100swl.msd.ray.com webtools\100uewrhp03.msd.ray.com
1036 michael.schroeder\100informatik.uni-erlangen.de mls\100suse.de
1037 mike\100stok.co.uk mike\100exegenix.com
1038 61100689+mikefultondev\100users.noreply.github.com mikefultonpersonal\100gmail.com
1039 miyagawa\100bulknews.net miyagawa\100edge.co.jp
1040 mjtg\100cam.ac.uk mjtg\100cus.cam.ac.uk
1041 mikedlr\100tardis.ed.ac.uk mikedlr\100it.com.pl
1042 moritz\100casella.verplant.org moritz\100faui2k3.org
1045 neale\100VMA.TABNSW.COM.AU neale\100pucc.princeton.edu
1046 neeracher\100mac.com neeri\100iis.ee.ethz.ch
1047 neilb\100neilb.org neilb\100cre.canon.co.uk
1048 + neil\100bowers.com
1050 nospam-abuse\100bloodgate.com tels\100bloodgate.com
1051 + perl_dummy\100bloodgate.com
1053 ian.phillipps\100iname.com ian_phillipps\100yahoo.co.uk
1054 + ian\100dial.pipex.com
1055 ignasi.roca\100fujitsu-siemens.com ignasi.roca\100fujitsu.siemens.es
1056 ikegami\100adaelis.com eric\100fmdev10.(none)
1057 ilmari\100ilmari.org ilmari\100vesla.ilmari.org
1058 illpide\100telecel.pt arbor\100al37al08.telecel.pt
1059 # see http://www.nntp.perl.org/group/perl.perl5.porters/2001/01/msg28925.html
1061 ilya\100math.berkeley.edu ilya\100math.ohio-state.edu
1062 + nospam-abuse\100ilyaz.org
1063 + [9]ilya\100math.ohio-state.edu
1064 ilya\100martynov.org ilya\100juil.nonet
1066 joshua\100paloalto.com joshua.pritikin\100db.com
1068 litt\100acm.org tlhackque\100yahoo.com
1070 meyering@asic.sc.ti.com jim\100meyering.net
1072 okamoto\100corp.hp.com okamoto\100hpcc123.corp.hp.com
1073 orwant\100oreilly.com orwant\100media.mit.edu
1075 p5-authors\100crystalflame.net perl\100crystalflame.net
1076 + rs\100crystalflame.net
1077 + coral\100eekeek.org
1078 + coral\100moonlight.crystalflame.net
1079 + rs\100oregonnet.com
1081 paul.green\100stratus.com paul_greenvos\100vos.stratus.com
1082 + pgreen\100seussnt.stratus.com
1083 pmqs pmqs\100cpan.org
1084 + paul.marquess\100btinternet.com
1085 + paul_marquess\100yahoo.co.uk
1086 + paul.marquess\100ntlworld.com
1087 + paul.marquess\100openwave.com
1088 + pmarquess\100bfsec.bt.co.uk
1090 + paul\100paul-desktop.(none)
1091 Pavel.Zakouril\100mff.cuni.cz root\100egg.karlov.mff.cuni.cz
1092 pcg\100goof.com schmorp\100schmorp.de
1093 perl\100cadop.com cdp\100hpescdp.fc.hp.com
1094 perl\100greerga.m-l.org greerga\100m-l.org
1095 perl\100profvince.com vince\100profvince.com
1096 perl-rt\100wizbit.be p5p\100perl.wizbit.be
1097 # Maybe we should special case this to get real names out?
1098 Peter.Dintelmann\100Dresdner-Bank.com peter.dintelmann\100dresdner-bank.com
1099 # NOTE: There is an intentional trailing space in the line above
1100 pfeifer\100wait.de pfeifer\100charly.informatik.uni-dortmund.de
1102 pjacklam\100online.no pjacklam\100gmail.com
1103 ribasushi@cpan.org rabbit\100rabbit.us
1104 + rabbit+bugs\100rabbit.us
1105 arc\100cpan.org perl\100aaroncrane.co.uk
1106 + arc@users.noreply.github.com
1107 phil\100perkpartners.com phil\100finchcomputer.com
1108 pimlott\100idiomtech.com andrew\100pimlott.net
1109 + pimlott\100abel.math.harvard.edu
1110 pixel\100mandriva.com pixel\100mandrakesoft.com
1111 pne\100cpan.org philip.newton\100gmx.net
1112 + philip.newton\100datenrevision.de
1114 pprymmer\100factset.com pvhp\100forte.com
1115 khw\100cpan.org khw\100karl.(none)
1116 + public\100khwilliamson.com
1117 + khw\100khw-desktop.(none)
1119 radu\100netsoft.ro rgreab\100fx.ro
1121 + raiph.mellor\100gmail.com
1122 rajagopa\100pauline.schrodinger.com rajagopa\100schrodinger.com
1123 raphael.manfredi\100pobox.com raphael_manfredi\100grenoble.hp.com
1124 module\100renee-baecker.de renee.baecker\100smart-websolutions.de
1125 + reneeb\100reneeb-desktop.(none)
1126 + github\100renee-baecker.de
1127 + otrs\100ubuntu.(none)
1128 + perl\100renee-baecker.de
1129 + reb\100perl-services.de
1130 + info\100perl-services.de
1131 rich+perl\100hyphen-dash-hyphen.info richardleach\100users.noreply.github.com
1132 richard.foley\100rfi.net richard.foley\100t-online.de
1133 + richard.foley\100ubs.com
1134 + richard.foley\100ubsw.com
1135 rick\100consumercontact.com rick\100bort.ca
1136 + rick.delaney\100rogers.com
1138 + rick.delaney\100home.com
1139 rjbs\100cpan.org rjbs-perl-p5p\100lists.manxome.org
1140 + perl.p5p\100rjbs.manxome.org
1141 + rjbs\100semiotic.systems
1142 + rjbs\100users.noreply.github.com
1143 rjk\100linguist.dartmouth.edu rjk\100linguist.thayer.dartmouth.edu
1144 + rjk-perl-p5p\100tamias.net
1146 rjray\100redhat.com rjray\100uswest.com
1147 rmgiroux\100acm.org rmgiroux\100hotmail.com
1148 + mgiroux\100bear.com
1149 rmbarker\100cpan.org rmb1\100cise.npl.co.uk
1150 + robin.barker\100npl.co.uk
1151 + rmb\100cise.npl.co.uk
1152 + robin\100spade-ubuntu.(none)
1153 + r.m.barker\100btinternet.com
1154 + rmbarker.cpan\100btinternet.com
1155 robertmay\100cpan.org rob\100themayfamily.me.uk
1156 roberto\100keltia.freenix.fr roberto\100eurocontrol.fr
1157 robin\100cpan.org robin\100kitsite.com
1158 roderick\100argon.org roderick\100gate.net
1159 + roderick\100ibcinc.com
1160 argrath\100ub32.org root\100ub32.org
1161 rootbeer\100teleport.com rootbeer\100redcat.com
1162 + tomphoenix\100unknown
1163 rra\100stanford.edu rra\100cpan.org
1164 rurban\100cpan.org rurban\100x-ray.at
1165 + rurban\100cpanel.net
1166 rvtol+news\100isolution.nl rvtol\100isolution.nl
1167 sartak\100gmail.com sartak\100bestpractical.com
1168 + code\100sartak.org
1169 danny-cpan\100sadinoff.com sadinoff\100olf.com
1170 schubiger\100cpan.org steven\100accognoscere.org
1171 + sts\100accognoscere.org
1172 + schubiger\100gmail.com
1173 + stsc\100refcnt.org
1174 schwern\100pobox.com schwern\100gmail.com
1175 + schwern\100athens.arena-i.com
1176 + schwern\100blackrider.aocn.com
1177 + schwern\100ool-18b93024.dyn.optonline.net
1178 scop\100cs132170.pp.htv.fi ville.skytta\100iki.fi
1179 scotth\100sgi.com author scotth\100sgi.com 842220273 +0000
1180 + schotth\100sgi.com
1181 schwab\100suse.de schwab\100issan.informatik.uni-dortmund.de
1182 + schwab\100ls5.informatik.uni-dortmund.de
1183 sebastien\100aperghis.net maddingue\100free.fr
1185 shigeya\100wide.ad.jp shigeya\100foretune.co.jp
1186 shlomif\100cpan.org shlomif\100vipe.technion.ac.il
1187 + shlomif\100iglu.org.il
1188 + shlomif+processed-by-perl\100gmail.com
1189 + shlomif\100shlomifish.org
1190 simon\100netthink.co.uk simon\100simon-cozens.org
1191 + simon\100pembro4.pmb.ox.ac.uk
1192 + simon\100brecon.co.uk
1193 + simon\100othersideofthe.earth.li
1194 + simon\100cozens.net
1196 sisyphus\100cpan.org sisyphus1\100optusnet.com.au
1197 + sisyphus359\100gmail.com
1198 lannings\100who.int lannings\100gmail.com
1199 + slanning\100cpan.org
1200 slaven\100rezic.de slaven.rezic\100berlin.de
1201 + srezic\100iconmobile.com
1202 + srezic\100cpan.org
1203 + eserte\100cs.tu-berlin.de
1204 + eserte\100vran.herceg.de
1205 smcc\100mit.edu smcc\100ocf.berkeley.edu
1206 + smcc\100csua.berkeley.edu
1208 + smccam\100uclink4.berkeley.edu
1209 spider\100orb.nashua.nh.us spider\100web.zk3.dec.com
1210 + spider\100leggy.zk3.dec.com
1211 + spider-perl\100orb.nashua.nh.us
1212 + spider\100peano.zk3.dec.com
1213 + spider.boardman\100orb.nashua.nh.us>
1215 + spider.boardman\100orb.nashua.nh.us
1216 + root\100peano.zk3.dec.com
1217 s.denaxas\100gmail.com spiros\100lokku.com
1218 spp\100ds.net spp\100psa.pencom.com
1219 + spp\100psasolar.colltech.com
1220 + spp\100spotter.yi.org
1221 stef\100mongueurs.net stef\100payrard.net
1222 + s.payrard\100wanadoo.fr
1223 + properler\100freesurf.fr
1224 + stef\100francenet.fr
1225 stevan\100cpan.org stevan.little\100gmail.com
1226 + stevan.little\100iinteractive.com
1227 sthoenna\100efn.org ysth\100raven.shiftboard.com
1229 tassilo.parseval\100post.rwth-aachen.de tassilo.von.parseval\100rwth-aachen.de
1230 tchrist\100perl.com tchrist\100mox.perl.com
1231 + tchrist\100jhereg.perl.com
1232 thomas.dorner\100start.de tdorner\100amadeus.net
1233 tjenness\100cpan.org t.jenness\100jach.hawaii.edu
1234 + timj\100jach.hawaii.edu
1235 tobez\100tobez.org tobez\100plab.ku.dk
1236 toddr\100cpan.org toddr\100cpanel.net
1237 tom\100compton.nu thh\100cyberscience.com
1238 tom.horsley\100mail.ccur.com tom.horsley\100ccur.com
1239 + tom\100amber.ssd.hcsc.com
1241 vkonovalov\100lucent.com vkonovalov\100peterstar.ru
1242 + konovalo\100mail.wplus.net
1243 + vadim\100vkonovalov.ru
1244 + vkonovalov\100spb.lucent.com
1245 + vkonovalov\100alcatel-lucent.com
1246 + vadim.konovalov\100alcatel-lucent.com
1248 whatever\100davidnicol.com davidnicol\100gmail.com
1249 wolfgang.laun\100alcatel.at wolfgang.laun\100chello.at
1250 + wolfgang.laun\100thalesgroup.com
1251 + wolfgang.laun\100gmail.com
1252 wolfsage\100gmail.com mhorsfall\100darmstadtium.(none)
1253 yath\100yath.de yath-perlbug\100yath.de