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 miyagawa\100bulknews.net miyagawa\100edge.co.jp
1039 mjtg\100cam.ac.uk mjtg\100cus.cam.ac.uk
1040 mikedlr\100tardis.ed.ac.uk mikedlr\100it.com.pl
1041 moritz\100casella.verplant.org moritz\100faui2k3.org
1044 neale\100VMA.TABNSW.COM.AU neale\100pucc.princeton.edu
1045 neeracher\100mac.com neeri\100iis.ee.ethz.ch
1046 neilb\100neilb.org neilb\100cre.canon.co.uk
1047 + neil\100bowers.com
1049 nospam-abuse\100bloodgate.com tels\100bloodgate.com
1050 + perl_dummy\100bloodgate.com
1052 ian.phillipps\100iname.com ian_phillipps\100yahoo.co.uk
1053 + ian\100dial.pipex.com
1054 ignasi.roca\100fujitsu-siemens.com ignasi.roca\100fujitsu.siemens.es
1055 ikegami\100adaelis.com eric\100fmdev10.(none)
1056 ilmari\100ilmari.org ilmari\100vesla.ilmari.org
1057 illpide\100telecel.pt arbor\100al37al08.telecel.pt
1058 # see http://www.nntp.perl.org/group/perl.perl5.porters/2001/01/msg28925.html
1060 ilya\100math.berkeley.edu ilya\100math.ohio-state.edu
1061 + nospam-abuse\100ilyaz.org
1062 + [9]ilya\100math.ohio-state.edu
1063 ilya\100martynov.org ilya\100juil.nonet
1065 joshua\100paloalto.com joshua.pritikin\100db.com
1067 litt\100acm.org tlhackque\100yahoo.com
1069 meyering@asic.sc.ti.com jim\100meyering.net
1071 okamoto\100corp.hp.com okamoto\100hpcc123.corp.hp.com
1072 orwant\100oreilly.com orwant\100media.mit.edu
1074 p5-authors\100crystalflame.net perl\100crystalflame.net
1075 + rs\100crystalflame.net
1076 + coral\100eekeek.org
1077 + coral\100moonlight.crystalflame.net
1078 + rs\100oregonnet.com
1080 paul.green\100stratus.com paul_greenvos\100vos.stratus.com
1081 + pgreen\100seussnt.stratus.com
1082 pmqs pmqs\100cpan.org
1083 + paul.marquess\100btinternet.com
1084 + paul_marquess\100yahoo.co.uk
1085 + paul.marquess\100ntlworld.com
1086 + paul.marquess\100openwave.com
1087 + pmarquess\100bfsec.bt.co.uk
1089 + paul\100paul-desktop.(none)
1090 Pavel.Zakouril\100mff.cuni.cz root\100egg.karlov.mff.cuni.cz
1091 pcg\100goof.com schmorp\100schmorp.de
1092 perl\100cadop.com cdp\100hpescdp.fc.hp.com
1093 perl\100greerga.m-l.org greerga\100m-l.org
1094 perl\100profvince.com vince\100profvince.com
1095 perl-rt\100wizbit.be p5p\100perl.wizbit.be
1096 # Maybe we should special case this to get real names out?
1097 Peter.Dintelmann\100Dresdner-Bank.com peter.dintelmann\100dresdner-bank.com
1098 # NOTE: There is an intentional trailing space in the line above
1099 pfeifer\100wait.de pfeifer\100charly.informatik.uni-dortmund.de
1101 pjacklam\100online.no pjacklam\100gmail.com
1102 ribasushi@cpan.org rabbit\100rabbit.us
1103 + rabbit+bugs\100rabbit.us
1104 arc\100cpan.org perl\100aaroncrane.co.uk
1105 + arc@users.noreply.github.com
1106 phil\100perkpartners.com phil\100finchcomputer.com
1107 pimlott\100idiomtech.com andrew\100pimlott.net
1108 + pimlott\100abel.math.harvard.edu
1109 pixel\100mandriva.com pixel\100mandrakesoft.com
1110 pne\100cpan.org philip.newton\100gmx.net
1111 + philip.newton\100datenrevision.de
1113 pprymmer\100factset.com pvhp\100forte.com
1114 khw\100cpan.org khw\100karl.(none)
1115 + public\100khwilliamson.com
1116 + khw\100khw-desktop.(none)
1118 radu\100netsoft.ro rgreab\100fx.ro
1120 + raiph.mellor\100gmail.com
1121 rajagopa\100pauline.schrodinger.com rajagopa\100schrodinger.com
1122 raphael.manfredi\100pobox.com raphael_manfredi\100grenoble.hp.com
1123 module\100renee-baecker.de renee.baecker\100smart-websolutions.de
1124 + reneeb\100reneeb-desktop.(none)
1125 + github\100renee-baecker.de
1126 + otrs\100ubuntu.(none)
1127 + perl\100renee-baecker.de
1128 + reb\100perl-services.de
1129 + info\100perl-services.de
1130 rich+perl\100hyphen-dash-hyphen.info richardleach\100users.noreply.github.com
1131 richard.foley\100rfi.net richard.foley\100t-online.de
1132 + richard.foley\100ubs.com
1133 + richard.foley\100ubsw.com
1134 rick\100consumercontact.com rick\100bort.ca
1135 + rick.delaney\100rogers.com
1137 + rick.delaney\100home.com
1138 rjbs\100cpan.org rjbs-perl-p5p\100lists.manxome.org
1139 + perl.p5p\100rjbs.manxome.org
1140 + rjbs\100semiotic.systems
1141 + rjbs\100users.noreply.github.com
1142 rjk\100linguist.dartmouth.edu rjk\100linguist.thayer.dartmouth.edu
1143 + rjk-perl-p5p\100tamias.net
1145 rjray\100redhat.com rjray\100uswest.com
1146 rmgiroux\100acm.org rmgiroux\100hotmail.com
1147 + mgiroux\100bear.com
1148 rmbarker\100cpan.org rmb1\100cise.npl.co.uk
1149 + robin.barker\100npl.co.uk
1150 + rmb\100cise.npl.co.uk
1151 + robin\100spade-ubuntu.(none)
1152 + r.m.barker\100btinternet.com
1153 + rmbarker.cpan\100btinternet.com
1154 robertmay\100cpan.org rob\100themayfamily.me.uk
1155 roberto\100keltia.freenix.fr roberto\100eurocontrol.fr
1156 robin\100cpan.org robin\100kitsite.com
1157 roderick\100argon.org roderick\100gate.net
1158 + roderick\100ibcinc.com
1159 argrath\100ub32.org root\100ub32.org
1160 rootbeer\100teleport.com rootbeer\100redcat.com
1161 + tomphoenix\100unknown
1162 rra\100stanford.edu rra\100cpan.org
1163 rurban\100cpan.org rurban\100x-ray.at
1164 + rurban\100cpanel.net
1165 rvtol+news\100isolution.nl rvtol\100isolution.nl
1166 sartak\100gmail.com sartak\100bestpractical.com
1167 + code\100sartak.org
1168 danny-cpan\100sadinoff.com sadinoff\100olf.com
1169 schubiger\100cpan.org steven\100accognoscere.org
1170 + sts\100accognoscere.org
1171 + schubiger\100gmail.com
1172 + stsc\100refcnt.org
1173 schwern\100pobox.com schwern\100gmail.com
1174 + schwern\100athens.arena-i.com
1175 + schwern\100blackrider.aocn.com
1176 + schwern\100ool-18b93024.dyn.optonline.net
1177 scop\100cs132170.pp.htv.fi ville.skytta\100iki.fi
1178 scotth\100sgi.com author scotth\100sgi.com 842220273 +0000
1179 + schotth\100sgi.com
1180 schwab\100suse.de schwab\100issan.informatik.uni-dortmund.de
1181 + schwab\100ls5.informatik.uni-dortmund.de
1182 sebastien\100aperghis.net maddingue\100free.fr
1184 shigeya\100wide.ad.jp shigeya\100foretune.co.jp
1185 shlomif\100cpan.org shlomif\100vipe.technion.ac.il
1186 + shlomif\100iglu.org.il
1187 + shlomif+processed-by-perl\100gmail.com
1188 + shlomif\100shlomifish.org
1189 simon\100netthink.co.uk simon\100simon-cozens.org
1190 + simon\100pembro4.pmb.ox.ac.uk
1191 + simon\100brecon.co.uk
1192 + simon\100othersideofthe.earth.li
1193 + simon\100cozens.net
1195 sisyphus\100cpan.org sisyphus1\100optusnet.com.au
1196 + sisyphus359\100gmail.com
1197 lannings\100who.int lannings\100gmail.com
1198 + slanning\100cpan.org
1199 slaven\100rezic.de slaven.rezic\100berlin.de
1200 + srezic\100iconmobile.com
1201 + srezic\100cpan.org
1202 + eserte\100cs.tu-berlin.de
1203 + eserte\100vran.herceg.de
1204 smcc\100mit.edu smcc\100ocf.berkeley.edu
1205 + smcc\100csua.berkeley.edu
1207 + smccam\100uclink4.berkeley.edu
1208 spider\100orb.nashua.nh.us spider\100web.zk3.dec.com
1209 + spider\100leggy.zk3.dec.com
1210 + spider-perl\100orb.nashua.nh.us
1211 + spider\100peano.zk3.dec.com
1212 + spider.boardman\100orb.nashua.nh.us>
1214 + spider.boardman\100orb.nashua.nh.us
1215 + root\100peano.zk3.dec.com
1216 s.denaxas\100gmail.com spiros\100lokku.com
1217 spp\100ds.net spp\100psa.pencom.com
1218 + spp\100psasolar.colltech.com
1219 + spp\100spotter.yi.org
1220 stef\100mongueurs.net stef\100payrard.net
1221 + s.payrard\100wanadoo.fr
1222 + properler\100freesurf.fr
1223 + stef\100francenet.fr
1224 stevan\100cpan.org stevan.little\100gmail.com
1225 + stevan.little\100iinteractive.com
1226 sthoenna\100efn.org ysth\100raven.shiftboard.com
1228 tassilo.parseval\100post.rwth-aachen.de tassilo.von.parseval\100rwth-aachen.de
1229 tchrist\100perl.com tchrist\100mox.perl.com
1230 + tchrist\100jhereg.perl.com
1231 thomas.dorner\100start.de tdorner\100amadeus.net
1232 tjenness\100cpan.org t.jenness\100jach.hawaii.edu
1233 + timj\100jach.hawaii.edu
1234 tobez\100tobez.org tobez\100plab.ku.dk
1235 toddr\100cpan.org toddr\100cpanel.net
1236 tom\100compton.nu thh\100cyberscience.com
1237 tom.horsley\100mail.ccur.com tom.horsley\100ccur.com
1238 + tom\100amber.ssd.hcsc.com
1240 vkonovalov\100lucent.com vkonovalov\100peterstar.ru
1241 + konovalo\100mail.wplus.net
1242 + vadim\100vkonovalov.ru
1243 + vkonovalov\100spb.lucent.com
1244 + vkonovalov\100alcatel-lucent.com
1245 + vadim.konovalov\100alcatel-lucent.com
1247 whatever\100davidnicol.com davidnicol\100gmail.com
1248 wolfgang.laun\100alcatel.at wolfgang.laun\100chello.at
1249 + wolfgang.laun\100thalesgroup.com
1250 + wolfgang.laun\100gmail.com
1251 wolfsage\100gmail.com mhorsfall\100darmstadtium.(none)
1252 yath\100yath.de yath-perlbug\100yath.de