Add a new utility, Porting/Modules.
Jarkko Hietaniemi [Tue, 1 Jul 2003 20:02:33 +0000 (20:02 +0000)]
p4raw-id: //depot/perl@19918

MANIFEST
Porting/Modules [new file with mode: 0644]

index 190df68..64c507d 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -2383,6 +2383,7 @@ Porting/genlog            Generate formatted changelogs by querying p4d
 Porting/Glossary       Glossary of config.sh variables
 Porting/makerel                Release making utility
 Porting/manicheck      Check against MANIFEST
+Porting/Modules                List which files belong to which CPAN modules
 Porting/p4d2p          Generate patch from p4 diff
 Porting/p4genpatch     Generate patch from p4 change in repository (obsoletes p4desc)
 Porting/patching.pod   How to report changes made to Perl
diff --git a/Porting/Modules b/Porting/Modules
new file mode 100644 (file)
index 0000000..eb55c2d
--- /dev/null
@@ -0,0 +1,428 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+use vars qw($Maintainers $Modules);
+
+$Maintainers =
+       {
+       'ams'           => 'Abhijit Menon-Sen <ams@wiw.org>',
+       'andreas'       => 'Andreas J. Koenig <andreas.koenig@anima.de>',
+       'arthur'        => 'Arthur Bergman <sky@nanisky.com>',
+       'bbb'           => 'Rob Brown <bbb@cpan.org>',
+       'damian'        => 'Damian Conway <damian@conway.org>',
+       'dankogai'      => 'Dan Kogai <dankogai@dan.co.jp>',
+       'gbarr'         => 'Graham Barr <gbarr@pobox.com>',
+       'gisle'         => 'Gisle Aas <gisle@activestate.com>',
+       'ilyaz'         => 'Ilya Zakharevich <ilyaz@cpan.org>',
+       'jhi'           => 'Jarkko Hietaniemi <jhi@iki.fi>',
+       'jns'           => 'Jonathan Stowe <jns@gellyfish.com>',
+       'jvromans'      => 'Johan Vromans <jvromans@squirrel.nl>',
+       'lstein'        => 'Lincoln D. Stein <lstein@cshl.org>',
+       'mjd'           => 'Mark-Jason Dominus <mjd@plover.com>',
+       'muir'          => 'David Muir Sharnoff <muir@idiom.com>',
+       'neilb'         => 'Neil Bowers <neil@bowers.com>',
+       'rra'           => 'Russ Allbery <rra@stanford.edu>',
+       'pmarquess'     => 'Paul Marquess <Paul.Marquess@btinternet.com>',
+       'sadahiro'      => 'SADAHIRO Tomoyuki <SADAHIRO@cpan.org>',
+       'sburke'        => 'Sean Burke <sburke@cpan.org>',
+       'schwern'       => 'Michael Schwern <schwern@pobox.com>',
+       'tels'          => 'Tels a t bloodgate.com',
+       'tjenness'      => 'Tim Jenness <t.jenness@jach.hawaii.edu>'
+       };
+
+$Modules = {
+
+       'Attribute::Handlers' =>
+               {
+               'MAINTAINER'    => 'arthur',
+               'FILES'         =>
+                       q[lib/Attribute/Handlers.pm lib/Attribute/Handlers],
+               },
+
+       'bignum' =>
+               {
+               'MAINTAINER'    => 'tels',
+               'FILES'         => q[lib/big{int,num,rat}.pm lib/bignum],
+               },
+
+       'CGI' =>
+               {
+               'MAINTAINER'    => 'lstein',
+               'FILES'         => q[lib/CGI.pm lib/CGI],
+               },
+
+       'Class::ISA' =>
+               {
+               'MAINTAINER'    => 'sburke',
+               'FILES'         => q[lib/Class/ISA.pm lib/Class/ISA],
+               },
+
+       'CPAN' =>
+               {
+               'MAINTAINER'    => 'andreas',
+               'FILES'         => q[lib/CPAN.pm lib/CPAN],
+               },
+
+# Data::Dumper is not here, Sarathy has given up the maintenance
+# and Data::Dumper should be considered a part of the Perl core.
+
+       'DB::File' =>
+               {
+               'MAINTAINER'    => 'pmarquess',
+               'FILES'         => q[ext/DB_File],
+               },
+
+       'Devel::PPPort' =>
+               {
+               'MAINTAINER'    => 'pmarquess',
+               'FILES'         => q[ext/Devel/PPPort],
+               },
+
+       'Digest' =>
+               {
+               'MAINTAINER'    => 'gisle',
+               'FILES'         => q[lib/Digest.{pm,t}],
+               },
+
+       'Digest::MD5' =>
+               {
+               'MAINTAINER'    => 'gisle',
+               'FILES'         => q[ext/Digest/MD5],
+               },
+
+       'Encode' =>
+               {
+               'MAINTAINER'    => 'dankogai',
+               'FILES'         => q[ext/Encode],
+               },
+
+# Errno is not here, Graham has given up the maintenance
+# and Errno should be considered a part of the Perl core.
+
+       'ExtUtils::MakeMaker' =>
+               {
+               'MAINTAINER'    => 'schwern',
+               'FILES'         => q[lib/ExtUtils/MakeMaker],
+               },
+
+       'File::Temp' =>
+               {
+               'MAINTAINER'    => 'tjenness',
+               'FILES'         => q[lib/File/Temp.pm lib/File/Temp],
+               },
+
+       'Filter::Simple' =>
+               {
+               'MAINTAINER'    => 'damian',
+               'FILES'         => q[lib/Filter/Simple.pm lib/Filter/Simple],
+               },
+
+       'Filter::Util::Call' =>
+               {
+               'MAINTAINER'    => 'pmarquess',
+               'FILES'         => q[ext/Filter/Util/Call],
+               },
+
+       'Getopt::Long' =>
+               {
+               'MAINTAINER'    => 'jvromans',
+               'FILES'         => q[lib/Getopt/Long.pm lib/Getopt/Long],
+               },
+
+       'I18N::LangTags' =>
+               {
+               'MAINTAINER'    => 'sburke',
+               'FILES'         => q[lib/I18N/LangTags.pm lib/I18N/LangTags],
+               },
+
+       'if' =>
+               {
+               'MAINTAINER'    => 'ilyaz',
+               'FILES'         => q[lib/if.{pm,t}],
+               },
+
+# IO is not here, Graham has given up the maintenance
+# and IO should be considered a part of the Perl core.
+
+       'libnet' =>
+               {
+               'MAINTAINER'    => 'gbarr',
+               'FILES'         =>
+                       q[lib/Net/{Cmd,Domain,FTP,Netrc,NNTP,POP3,SMTP,Time}.pm lib/Net/ChangeLog.libnet lib/Net/FTP lib/Net/*.eg lib/Net/libnetFAQ.pod lib/Net/README.libnet lib/Net/t],
+               },
+
+       'Scalar-List-Util' =>
+               {
+               'MAINTAINER'    => 'gbarr',
+               'FILES'         => q[ext/List/Util],
+               },
+
+       'Locale::Codes' =>
+               {
+               'MAINTAINER'    => 'neilb',
+               'FILES'         => q[lib/Locale/{Country,Currency,Language}],
+               },
+
+       'Locale::Maketext' =>
+               {
+               'MAINTAINER'    => 'sburke',
+               'FILES'         => q[lib/Locale/Maketext.pm lib/Locale/Maketext],
+               },
+
+       'Math::BigFloat' =>
+               {
+               'MAINTAINER'    => 'tels',
+               'FILES'         => q[lib/Math/BigFloat.pm lib/Math/BigFloat],
+               },
+
+       'Math::BigInt' =>
+               {
+               'MAINTAINER'    => 'tels',
+               'FILES'         => q[lib/Math/BigInt.pm lib/Math/BigInt],
+               },
+
+       'Math::BigRat' =>
+               {
+               'MAINTAINER'    => 'tels',
+               'FILES'         => q[lib/Math/BigRat.pm lib/Math/BigRat],
+               },
+
+       'Memoize' =>
+               {
+               'MAINTAINER'    => 'mjd',
+               'FILES'         => q[lib/Memoize.pm lib/Memoize],
+               },
+
+       'MIME::Base64' =>
+               {
+               'MAINTAINER'    => 'gisle',
+               'FILES'         => q[ext/MIME/Base64],
+               },
+
+       'Net::Ping' =>
+               {
+               'MAINTAINER'    => 'bbb',
+               'FILES'         => q[lib/Net/Ping.pm lib/Net/Ping],
+               },
+
+       'NEXT' =>
+               {
+               'MAINTAINER'    => 'damian',
+               'FILES'         => q[lib/NEXT.pm lib/NEXT],
+               },
+
+# The PerlIO::* are part of Perl core.
+
+       'podlators' =>
+               {
+               'MAINTAINER'    => 'rra',
+               'FILES'         => q[lib/Pod/{Html,Man,ParseLink,Text,Text/{Color,Overstrike,Termcap}}.pm pod/pod2man.PL pod/pod2text.PL lib/Pod/t/{basic.*,{basic,man,parselink,text*}.t}],
+               },
+
+       'Storable' =>
+               {
+               'MAINTAINER'    => 'ams',
+               'FILES'         => q[ext/Storable],
+               },
+
+       'Switch' =>
+               {
+               'MAINTAINER'    => 'damian',
+               'FILES'         => q[lib/Switch.pm lib/Switch],
+               },
+
+       'TabsWrap' =>
+               {
+               'MAINTAINER'    => 'muir',
+               'FILES'         =>
+                       q[lib/Text/{Tabs,Wrap}.pm lib/Text/TabsWrap],
+               },
+
+       'Text::Balanced' =>
+               {
+               'MAINTAINER'    => 'damian',
+               'FILES'         => q[lib/Text/Balanced.pm lib/Text/Balanced],
+               },
+
+       'Term::ANSIColor' =>
+               {
+               'MAINTAINER'    => 'rra',
+               'FILES'         => q[lib/Term/ANSIColor.pm lib/Term/ANSIColor],
+               },
+
+       'Test::Builder' =>
+               {
+               'MAINTAINER'    => 'schwern',
+               'FILES'         => q[lib/Test/Builder.pm],
+               },
+
+       'Test::Harness' =>
+               {
+               'MAINTAINER'    => 'schwern',
+               'FILES'         => q[lib/Test/Harness.pm lib/Test/Harness],
+               },
+
+       'Test::More' =>
+               {
+               'MAINTAINER'    => 'schwern',
+               'FILES'         => q[lib/Test/More.pm],
+               },
+
+       'Test::Simple' =>
+               {
+               'MAINTAINER'    => 'schwern',
+               'FILES'         => q[lib/Test/Simple.pm lib/Test/Simple],
+               },
+
+       'Term::Cap' =>
+               {
+               'MAINTAINER'    => 'jns',
+               'FILES'         => q[lib/Term/Cap.{pm,t}],
+               },
+
+
+       'threads' =>
+               {
+               'MAINTAINER' => 'arthur',
+               'FILES'  => q[ext/threads],
+               },
+
+       'Tie::File' =>
+               {
+               'MAINTAINER'    => 'mjd',
+               'FILES'         => q[lib/Tie/File.pm lib/Tie/File],
+               },
+
+       'Time::HiRes' =>
+               {
+               'MAINTAINER'    => 'jhi',
+               'FILES'         => q[ext/Time/HiRes],
+               },
+
+       'Unicode::Collate' =>
+               {
+               'MAINTAINER'    => 'sadahiro',
+               'FILES'         =>
+                       q[lib/Unicode/Collate.pm lib/Unicode/Collate],
+               },
+
+       'Unicode::Normalize' =>
+               {
+               'MAINTAINER'    => 'sadahiro',
+               'FILES'         => q[ext/Unicode/Normalize],
+               },
+
+       };
+
+# Sanity check.
+
+use Getopt::Long;
+use File::Find;
+
+my $All;
+my $Maintainer;
+my $Module;
+my %ModuleByFile;
+my %FilesByModule;
+
+sub usage {
+    print <<__EOF__;
+$0: Usage: $0 [--all|--maintainer M|--module M|file ...]
+$0 --all               lists all the modules and their files
+$0 --maintainer M      lists all the modules of maintainer
+$0 --module M          lists all the files of the modules
+The matching of maintainer names is done both on the short name
+and the full name.
+__EOF__
+    exit(0);
+}
+
+usage() unless
+    GetOptions(
+              'all'            => \$All,
+              'maintainer=s'   => \$Maintainer,
+              'module=s'       => \$Module,
+             );
+
+if (defined $Maintainer) {
+    unless (exists $Maintainers->{$Maintainer}) {
+       my @m;
+       for my $m (sort keys %$Maintainers) {
+           if ($m =~ /$Maintainer/i ||
+               $Maintainers->{$m} =~ /$Maintainer/i) {
+               push @m, $m;
+           }
+       }
+       if (@m) {
+           if (@m == 1) {
+               $Maintainer = $m[0];
+           } else {
+               die "$0: more than one match for '$Maintainer': @m\n";
+           }
+       } else {
+           die "$0: no matches for maintainer '$Maintainer'\n";
+       }
+    }
+}
+
+print "$0: maintainer '$Maintainers->{$Maintainer}'\n" if defined $Maintainer;
+
+my @Files = @ARGV;
+
+usage() unless @Files || $All || $Maintainer || $Module;
+
+for my $module (sort { lc $a cmp lc $b } keys %$Modules) {
+    next if defined $Module && $Module ne $module;
+    warn "$0: Module '$module' missing MAINTAINER\n"
+       unless exists $Modules->{$module}->{MAINTAINER};
+    my $maintainer = $Modules->{$module}->{MAINTAINER};
+    next if defined $Maintainer && $Maintainer ne $maintainer;
+    warn "$0: Module '$module' missing FILES\n"
+       unless exists $Modules->{$module}->{FILES};
+    my $files = $Modules->{$module}->{FILES};
+    warn "$0: Module '$module' maintainer '$maintainer' unknown\n"
+       unless exists $Maintainers->{$maintainer};
+    my @files =
+       sort { lc $a cmp lc $b }
+           map { -d $_ ?
+                     do { my @files;
+                          find(sub{ push @files, $File::Find::name if -f $_ },
+                               $_); @files } :
+                     -f $_ ? $_ : glob($_)
+                 } split(' ', $files);
+    $FilesByModule{$module} = [ @files ];
+    $ModuleByFile{$_} = $module for @files;
+    print "$module\n"          if $Maintainer;
+    print "$module @files\n"   if $All || $Module;
+}
+
+if (@Files) {
+    for my $file (@Files) {
+       my $module;
+       if (-f $file) {
+           $module =
+               [ exists $ModuleByFile{$file} ? $ModuleByFile{$file} : '-' ];
+       } elsif (-d $file) {
+           # Show the modules that have the most matches.
+           my %m;
+           for my $module (keys %$Modules) {
+               my @m = grep { m:^$file/:i } @{$FilesByModule{$module}};
+               $m{$module} = @m;
+           }
+           my @m = sort { $m{$b} <=> $m{$a} } keys %m;
+           if ($m{$m[0]}) {
+               $module = [ shift @m ];
+               push @$module, shift @m
+                   while @m && $m{$m[0]} == $m{$module->[0]};
+           }
+       }
+       if (defined $module) {
+           print "$file @$module\n";
+       } else {
+           warn "$0: no module matches for file '$file'\n";
+       }
+    }
+}
+
+exit(0);