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