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 dom\100earth.li dom\100semmle.com
888 domo\100computer.org shouldbedomo\100mac.com
889 + domo\100slipper.ip.lu
891 dougm\100covalent.net dougm\100opengroup.org
893 dougw\100cpan.org doug_wilson\100intuit.com
894 dwegscheid\100qtm.net wegscd\100whirlpool.com
895 edwardp\100excitehome.net epeschko\100den-mdev1
896 + epeschko\100elmer.tci.com
898 egf7\100columbia.edu efifer\100sanwaint.com
899 eggert\100twinsun.com eggert\100sea.sm.unisys.com
900 etj\100cpan.org mohawk2\100users.noreply.github.com
902 fugazi\100zyx.net larrysh\100cpan.org
903 + lshatzer\100islanddata.com
905 gbacon\100itsc.uah.edu gbacon\100adtrn-srv4.adtran.com
906 gerberb\100zenez.com root\100devsys0.zenez.com
907 gfuji\100cpan.org g.psy.va\100gmail.com
908 genesullivan50\100yahoo.com gsullivan\100cpan.org
909 gerard\100ggoossen.net gerard\100tty.nl
910 gibreel\100pobox.com stephen.zander\100interlock.mckesson.com
912 gideon\100cpan.org gidisrael\100gmail.com
913 gnat\100frii.com gnat\100prometheus.frii.com
914 gp\100familiehaase.de gerrit\100familiehaase.de
915 grazz\100pobox.com grazz\100nyc.rr.com
916 gward\100ase.com greg\100bic.mni.mcgill.ca
917 haggai\100cpan.org alanhaggai\100alanhaggai.org
918 + alanhaggai\100gmail.com
919 hansmu\100xs4all.nl hansm\100icgroup.nl
923 + hansm\100euronet.nl
925 hio\100ymir.co.jp hio\100hio.jp
926 hops\100sco.com hops\100scoot.pdev.sco.com
928 ian.goodacre\100xtra.co.nz ian\100debian.lan
929 ingo_weinhold\100gmx.de bonefish\100cs.tu-berlin.de
931 james\100mastros.biz theorb\100desert-island.me.uk
932 jan\100jandubois.com jand\100activestate.com
933 + jan.dubois\100ibm.net
934 japhy\100pobox.com japhy\100pobox.org
935 + japhy\100perlmonk.org
937 + jeffp\100crusoe.net
938 jari.aalto\100poboxes.com jari.aalto\100cante.net
939 jarausch\100numa1.igpm.rwth-aachen.de helmutjarausch\100unknown
940 jasons\100cs.unm.edu jasons\100sandy-home.arc.unm.edu
941 jbuehler\100hekimian.com jhpb\100hekimian.com
942 jcromie\100cpan.org jcromie\100100divsol.com
943 + jim.cromie\100gmail.com
944 jd\100cpanel.net lightsey\100debian.org
946 + john\100nixnuts.net
947 jdhedden\100cpan.org jerry\100hedden.us
948 + jdhedden\1001979.usna.com
949 + jdhedden\100gmail.com
950 + jdhedden\100yahoo.com
951 + jhedden\100pn100-02-2-356p.corp.bloomberg.com
952 + jdhedden\100solydxk
953 jeremy\100zawodny.com jzawodn\100wcnet.org
954 jesse\100sig.bsh.com jesse\100ginger
955 jfriedl\100yahoo.com jfriedl\100yahoo-inc.com
956 jfs\100fluent.com jfs\100jfs.fluent.com
957 jhannah\100mutationgrid.com jay\100jays.net
958 + jhannah\100omnihotels.com
959 jidanni\100jidanni.org jidanni\100hoffa.dreamhost.com
960 jjore\100cpan.org twists\100gmail.com
961 jkeenan\100cpan.org jkeen\100verizon.net
962 + jkeenan\100dromedary-001.ams6.corp.booking.com
963 jns\100integration-house.com jns\100gellyfish.com
964 + gellyfish\100gellyfish.com
965 john\100atlantech.com john\100titanic.atlantech.com
966 john\100johnwright.org john.wright\100hp.com
967 joseph\100cscaper.com joseph\1005sigma.com
968 joshua\100rodd.us jrodd\100pbs.org
969 jtobey\100john-edwin-tobey.org jtobey\100user1.channel1.com
970 jpeacock\100messagesystems.com john.peacock\100havurah-software.org
971 + jpeacock\100havurah-software.org
972 + jpeacock\100dsl092-147-156.wdc1.dsl.speakeasy.net
973 + jpeacock\100jpeacock-hp.doesntexist.org
974 + jpeacock\100cpan.org
975 + jpeacock\100rowman.com
976 james.schneider\100db.com jschneid\100netilla.com
977 jpl.jpl\100gmail.com jpl\100research.att.com
978 jql\100accessone.com jql\100jql.accessone.com
979 jsm28\100hermes.cam.ac.uk jsm28\100cam.ac.uk
981 kane\100dwim.org kane\100xs4all.net
986 keith.s.thompson\100gmail.com kst\100mib.org
987 ken\100mathforum.org kenahoo\100gmail.com
988 + ken.williams\100thomsonreuters.com
989 kentfredric\100gmail.com kentnl\100cpan.org
990 kmx\100volny.cz kmx\100volny.cz
992 kroepke\100dolphin-services.de kay\100dolphin-services.de
993 kst\100mib.org kst\100cts.com
995 kstar\100wolfetech.com kstar\100cpan.org
996 + kurt_starsinic\100ml.com
997 + kstar\100www.chapin.edu
998 + kstar\100chapin.edu
999 larry\100wall.org lwall\100jpl-devvax.jpl.nasa.gov
1000 + lwall\100netlabs.com
1001 + larry\100netlabs.com
1003 + lwall\100scalpel.netlabs.com
1004 laszlo.molnar\100eth.ericsson.se molnarl\100cdata.tvnet.hu
1005 + ml1050\100freemail.hu
1006 lewart\100uiuc.edu lewart\100vadds.cvm.uiuc.edu
1007 + d-lewart\100uiuc.edu
1008 lindblad@gmx.com 52227507+apparluk\100users.noreply.github.com
1009 lkundrak\100v3.sk lubo.rintel\100gooddata.com
1010 lstein\100cshl.org lstein\100formaggio.cshl.org
1011 + lstein\100genome.wi.mit.edu
1012 l.mai\100web.de plokinom\100gmail.com
1013 lupe\100lupe-christoph.de lupe\100alanya.m.isar.de
1014 lutherh\100stratcom.com lutherh\100infinet.com
1015 mab\100wdl.loral.com markb\100rdcf.sm.unisys.com
1016 marcel\100codewerk.com gr\100univie.ac.at
1017 + hanekomu\100gmail.com
1018 marcgreen\100cpan.org marcgreen\100wpi.edu
1019 markleightonfisher\100gmail.com fisherm\100tce.com
1020 + mark-fisher\100mindspring.com
1021 mark.p.lutz\100boeing.com tecmpl1\100triton.ca.boeing.com
1022 marnix\100gmail.com pttesac!marnix!vanam
1023 marty+p5p\100kasei.com marty\100martian.org
1024 mats\100sm6sxl.net mats\100sm5sxl.net
1025 mbarbon\100dsi.unive.it mattia.barbon\100libero.it
1026 + mattia\100barbon.org
1027 mcmahon\100ibiblio.org mcmahon\100metalab.unc.edu
1028 me\100davidglasser.net glasser\100tang-eleven-seventy-nine.mit.edu
1029 merijnb\100iloquent.nl merijnb\100ms.com
1030 + merijnb\100iloquent.com
1031 merlyn\100stonehenge.com merlyn\100gadget.cscaper.com
1032 mestre.smash\100gmail.com smash\100cpan.org
1033 mgjv\100comdyn.com.au mgjv\100tradingpost.com.au
1034 mlh\100swl.msd.ray.com webtools\100uewrhp03.msd.ray.com
1035 michael.schroeder\100informatik.uni-erlangen.de mls\100suse.de
1036 mike\100stok.co.uk mike\100exegenix.com
1037 miyagawa\100bulknews.net miyagawa\100edge.co.jp
1038 mjtg\100cam.ac.uk mjtg\100cus.cam.ac.uk
1039 mikedlr\100tardis.ed.ac.uk mikedlr\100it.com.pl
1040 moritz\100casella.verplant.org moritz\100faui2k3.org
1043 neale\100VMA.TABNSW.COM.AU neale\100pucc.princeton.edu
1044 neeracher\100mac.com neeri\100iis.ee.ethz.ch
1045 neil\100bowers.com neilb\100cre.canon.co.uk
1047 nospam-abuse\100bloodgate.com tels\100bloodgate.com
1048 + perl_dummy\100bloodgate.com
1050 ian.phillipps\100iname.com ian_phillipps\100yahoo.co.uk
1051 + ian\100dial.pipex.com
1052 ignasi.roca\100fujitsu-siemens.com ignasi.roca\100fujitsu.siemens.es
1053 ikegami\100adaelis.com eric\100fmdev10.(none)
1054 ilmari\100ilmari.org ilmari\100vesla.ilmari.org
1055 illpide\100telecel.pt arbor\100al37al08.telecel.pt
1056 # see http://www.nntp.perl.org/group/perl.perl5.porters/2001/01/msg28925.html
1058 ilya\100math.berkeley.edu ilya\100math.ohio-state.edu
1059 + nospam-abuse\100ilyaz.org
1060 + [9]ilya\100math.ohio-state.edu
1061 ilya\100martynov.org ilya\100juil.nonet
1063 joshua\100paloalto.com joshua.pritikin\100db.com
1065 litt\100acm.org tlhackque\100yahoo.com
1067 meyering@asic.sc.ti.com jim\100meyering.net
1069 okamoto\100corp.hp.com okamoto\100hpcc123.corp.hp.com
1070 orwant\100oreilly.com orwant\100media.mit.edu
1072 p5-authors\100crystalflame.net perl\100crystalflame.net
1073 + rs\100crystalflame.net
1074 + coral\100eekeek.org
1075 + coral\100moonlight.crystalflame.net
1076 + rs\100oregonnet.com
1078 paul.green\100stratus.com paul_greenvos\100vos.stratus.com
1079 + pgreen\100seussnt.stratus.com
1080 pmqs pmqs\100cpan.org
1081 + paul.marquess\100btinternet.com
1082 + paul_marquess\100yahoo.co.uk
1083 + paul.marquess\100ntlworld.com
1084 + paul.marquess\100openwave.com
1085 + pmarquess\100bfsec.bt.co.uk
1087 + paul\100paul-desktop.(none)
1088 Pavel.Zakouril\100mff.cuni.cz root\100egg.karlov.mff.cuni.cz
1089 pcg\100goof.com schmorp\100schmorp.de
1090 perl\100cadop.com cdp\100hpescdp.fc.hp.com
1091 perl\100greerga.m-l.org greerga\100m-l.org
1092 perl\100profvince.com vince\100profvince.com
1093 perl-rt\100wizbit.be p5p\100perl.wizbit.be
1094 # Maybe we should special case this to get real names out?
1095 Peter.Dintelmann\100Dresdner-Bank.com peter.dintelmann\100dresdner-bank.com
1096 # NOTE: There is an intentional trailing space in the line above
1097 pfeifer\100wait.de pfeifer\100charly.informatik.uni-dortmund.de
1099 pjacklam\100online.no pjacklam\100gmail.com
1100 ribasushi@cpan.org rabbit\100rabbit.us
1101 + rabbit+bugs\100rabbit.us
1102 arc\100cpan.org perl\100aaroncrane.co.uk
1103 + arc@users.noreply.github.com
1104 phil\100perkpartners.com phil\100finchcomputer.com
1105 pimlott\100idiomtech.com andrew\100pimlott.net
1106 + pimlott\100abel.math.harvard.edu
1107 pixel\100mandriva.com pixel\100mandrakesoft.com
1108 pne\100cpan.org philip.newton\100gmx.net
1109 + philip.newton\100datenrevision.de
1111 pprymmer\100factset.com pvhp\100forte.com
1112 khw\100cpan.org khw\100karl.(none)
1113 + public\100khwilliamson.com
1114 + khw\100khw-desktop.(none)
1116 radu\100netsoft.ro rgreab\100fx.ro
1118 + raiph.mellor\100gmail.com
1119 rajagopa\100pauline.schrodinger.com rajagopa\100schrodinger.com
1120 raphael.manfredi\100pobox.com raphael_manfredi\100grenoble.hp.com
1121 module\100renee-baecker.de renee.baecker\100smart-websolutions.de
1122 + reneeb\100reneeb-desktop.(none)
1123 + github\100renee-baecker.de
1124 + otrs\100ubuntu.(none)
1125 + perl\100renee-baecker.de
1126 + reb\100perl-services.de
1127 + info\100perl-services.de
1128 rich+perl\100hyphen-dash-hyphen.info richardleach\100users.noreply.github.com
1129 richard.foley\100rfi.net richard.foley\100t-online.de
1130 + richard.foley\100ubs.com
1131 + richard.foley\100ubsw.com
1132 rick\100consumercontact.com rick\100bort.ca
1133 + rick.delaney\100rogers.com
1135 + rick.delaney\100home.com
1136 rjbs\100cpan.org rjbs-perl-p5p\100lists.manxome.org
1137 + perl.p5p\100rjbs.manxome.org
1138 + rjbs\100semiotic.systems
1139 + rjbs\100users.noreply.github.com
1140 rjk\100linguist.dartmouth.edu rjk\100linguist.thayer.dartmouth.edu
1141 + rjk-perl-p5p\100tamias.net
1143 rjray\100redhat.com rjray\100uswest.com
1144 rmgiroux\100acm.org rmgiroux\100hotmail.com
1145 + mgiroux\100bear.com
1146 rmbarker\100cpan.org rmb1\100cise.npl.co.uk
1147 + robin.barker\100npl.co.uk
1148 + rmb\100cise.npl.co.uk
1149 + robin\100spade-ubuntu.(none)
1150 + r.m.barker\100btinternet.com
1151 + rmbarker.cpan\100btinternet.com
1152 robertmay\100cpan.org rob\100themayfamily.me.uk
1153 roberto\100keltia.freenix.fr roberto\100eurocontrol.fr
1154 robin\100cpan.org robin\100kitsite.com
1155 roderick\100argon.org roderick\100gate.net
1156 + roderick\100ibcinc.com
1157 argrath\100ub32.org root\100ub32.org
1158 rootbeer\100teleport.com rootbeer\100redcat.com
1159 + tomphoenix\100unknown
1160 rra\100stanford.edu rra\100cpan.org
1161 rurban\100cpan.org rurban\100x-ray.at
1162 + rurban\100cpanel.net
1163 rvtol+news\100isolution.nl rvtol\100isolution.nl
1164 sartak\100gmail.com sartak\100bestpractical.com
1165 + code\100sartak.org
1166 danny-cpan\100sadinoff.com sadinoff\100olf.com
1167 schubiger\100cpan.org steven\100accognoscere.org
1168 + sts\100accognoscere.org
1169 + schubiger\100gmail.com
1170 + stsc\100refcnt.org
1171 schwern\100pobox.com schwern\100gmail.com
1172 + schwern\100athens.arena-i.com
1173 + schwern\100blackrider.aocn.com
1174 + schwern\100ool-18b93024.dyn.optonline.net
1175 scop\100cs132170.pp.htv.fi ville.skytta\100iki.fi
1176 scotth\100sgi.com author scotth\100sgi.com 842220273 +0000
1177 + schotth\100sgi.com
1178 schwab\100suse.de schwab\100issan.informatik.uni-dortmund.de
1179 + schwab\100ls5.informatik.uni-dortmund.de
1180 sebastien\100aperghis.net maddingue\100free.fr
1182 shigeya\100wide.ad.jp shigeya\100foretune.co.jp
1183 shlomif\100cpan.org shlomif\100vipe.technion.ac.il
1184 + shlomif\100iglu.org.il
1185 + shlomif+processed-by-perl\100gmail.com
1186 + shlomif\100shlomifish.org
1187 simon\100netthink.co.uk simon\100simon-cozens.org
1188 + simon\100pembro4.pmb.ox.ac.uk
1189 + simon\100brecon.co.uk
1190 + simon\100othersideofthe.earth.li
1191 + simon\100cozens.net
1193 sisyphus\100cpan.org sisyphus1\100optusnet.com.au
1194 + sisyphus359\100gmail.com
1195 lannings\100who.int lannings\100gmail.com
1196 + slanning\100cpan.org
1197 slaven\100rezic.de slaven.rezic\100berlin.de
1198 + srezic\100iconmobile.com
1199 + srezic\100cpan.org
1200 + eserte\100cs.tu-berlin.de
1201 + eserte\100vran.herceg.de
1202 smcc\100mit.edu smcc\100ocf.berkeley.edu
1203 + smcc\100csua.berkeley.edu
1205 + smccam\100uclink4.berkeley.edu
1206 spider\100orb.nashua.nh.us spider\100web.zk3.dec.com
1207 + spider\100leggy.zk3.dec.com
1208 + spider-perl\100orb.nashua.nh.us
1209 + spider\100peano.zk3.dec.com
1210 + spider.boardman\100orb.nashua.nh.us>
1212 + spider.boardman\100orb.nashua.nh.us
1213 + root\100peano.zk3.dec.com
1214 s.denaxas\100gmail.com spiros\100lokku.com
1215 spp\100ds.net spp\100psa.pencom.com
1216 + spp\100psasolar.colltech.com
1217 + spp\100spotter.yi.org
1218 stef\100mongueurs.net stef\100payrard.net
1219 + s.payrard\100wanadoo.fr
1220 + properler\100freesurf.fr
1221 + stef\100francenet.fr
1222 stevan\100cpan.org stevan.little\100gmail.com
1223 + stevan.little\100iinteractive.com
1224 sthoenna\100efn.org ysth\100raven.shiftboard.com
1226 tassilo.parseval\100post.rwth-aachen.de tassilo.von.parseval\100rwth-aachen.de
1227 tchrist\100perl.com tchrist\100mox.perl.com
1228 + tchrist\100jhereg.perl.com
1229 thomas.dorner\100start.de tdorner\100amadeus.net
1230 tjenness\100cpan.org t.jenness\100jach.hawaii.edu
1231 + timj\100jach.hawaii.edu
1232 tobez\100tobez.org tobez\100plab.ku.dk
1233 toddr\100cpan.org toddr\100cpanel.net
1234 tom\100compton.nu thh\100cyberscience.com
1235 tom.horsley\100mail.ccur.com tom.horsley\100ccur.com
1236 + tom\100amber.ssd.hcsc.com
1238 vkonovalov\100lucent.com vkonovalov\100peterstar.ru
1239 + konovalo\100mail.wplus.net
1240 + vadim\100vkonovalov.ru
1241 + vkonovalov\100spb.lucent.com
1242 + vkonovalov\100alcatel-lucent.com
1243 + vadim.konovalov\100alcatel-lucent.com
1245 whatever\100davidnicol.com davidnicol\100gmail.com
1246 wolfgang.laun\100alcatel.at wolfgang.laun\100chello.at
1247 + wolfgang.laun\100thalesgroup.com
1248 + wolfgang.laun\100gmail.com
1249 wolfsage\100gmail.com mhorsfall\100darmstadtium.(none)
1250 yath\100yath.de yath-perlbug\100yath.de