This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #112776] avoid warning on an initialized non-parameter
[perl5.git] / dist / Module-CoreList / corelist
1 #!/usr/bin/perl
2
3 =head1 NAME
4
5 corelist - a commandline frontend to Module::CoreList
6
7 =head1 DESCRIPTION
8
9 See L<Module::CoreList> for one.
10
11 =head1 SYNOPSIS
12
13     corelist -v
14     corelist [-a|-d] <ModuleName> | /<ModuleRegex>/ [<ModuleVersion>] ...
15     corelist [-v <PerlVersion>] [ <ModuleName> | /<ModuleRegex>/ ] ...
16     corelist [-r <PerlVersion>] ...
17     corelist --diff PerlVersion PerlVersion
18
19 =head1 OPTIONS
20
21 =over
22
23 =item -a
24
25 lists all versions of the given module (or the matching modules, in case you
26 used a module regexp) in the perls Module::CoreList knows about.
27
28     corelist -a Unicode
29
30     Unicode was first released with perl v5.6.2
31       v5.6.2     3.0.1
32       v5.8.0     3.2.0
33       v5.8.1     4.0.0
34       v5.8.2     4.0.0
35       v5.8.3     4.0.0
36       v5.8.4     4.0.1
37       v5.8.5     4.0.1
38       v5.8.6     4.0.1
39       v5.8.7     4.1.0
40       v5.8.8     4.1.0
41       v5.8.9     5.1.0
42       v5.9.0     4.0.0
43       v5.9.1     4.0.0
44       v5.9.2     4.0.1
45       v5.9.3     4.1.0
46       v5.9.4     4.1.0
47       v5.9.5     5.0.0
48       v5.10.0    5.0.0
49       v5.10.1    5.1.0
50       v5.11.0    5.1.0
51       v5.11.1    5.1.0
52       v5.11.2    5.1.0
53       v5.11.3    5.2.0
54       v5.11.4    5.2.0
55       v5.11.5    5.2.0
56       v5.12.0    5.2.0
57       v5.12.1    5.2.0
58       v5.12.2    5.2.0
59       v5.12.3    5.2.0
60       v5.12.4    5.2.0
61       v5.13.0    5.2.0
62       v5.13.1    5.2.0
63       v5.13.2    5.2.0
64       v5.13.3    5.2.0
65       v5.13.4    5.2.0
66       v5.13.5    5.2.0
67       v5.13.6    5.2.0
68       v5.13.7    6.0.0
69       v5.13.8    6.0.0
70       v5.13.9    6.0.0
71       v5.13.10   6.0.0
72       v5.13.11   6.0.0
73       v5.14.0    6.0.0
74       v5.14.1    6.0.0
75       v5.15.0    6.0.0
76
77 =item -d
78
79 finds the first perl version where a module has been released by
80 date, and not by version number (as is the default).
81
82 =item --diff
83
84 Given two versions of perl, this prints a human-readable table of all module
85 changes between the two.  The output format may change in the future, and is
86 meant for I<humans>, not programs.  For programs, use the L<Module::CoreList>
87 API.
88
89 =item -? or -help
90
91 help! help! help! to see more help, try --man.
92
93 =item -man
94
95 all of the help
96
97 =item -v
98
99 lists all of the perl release versions we got the CoreList for.
100
101 If you pass a version argument (value of C<$]>, like C<5.00503> or C<5.008008>),
102 you get a list of all the modules and their respective versions.
103 (If you have the C<version> module, you can also use new-style version numbers,
104 like C<5.8.8>.)
105
106 In module filtering context, it can be used as Perl version filter.
107
108 =item -r
109
110 lists all of the perl releases and when they were released
111
112 If you pass a perl version you get the release date for that version only.
113
114 =back
115
116 As a special case, if you specify the module name C<Unicode>, you'll get
117 the version number of the Unicode Character Database bundled with the
118 requested perl versions.
119
120 =cut
121
122 use Module::CoreList;
123 use Getopt::Long;
124 use Pod::Usage;
125 use strict;
126 use warnings;
127
128 my %Opts;
129
130 GetOptions(
131     \%Opts,
132     qw[ help|?! man! r|release:s v|version:s a! d diff|D ]
133 );
134
135 pod2usage(1) if $Opts{help};
136 pod2usage(-verbose=>2) if $Opts{man};
137
138 if(exists $Opts{r} ){
139     if ( !$Opts{r} ) {
140         print "\nModule::CoreList has release info for the following perl versions:\n";
141         my $versions = { };
142         my $max_ver_len = max_mod_len(\%Module::CoreList::released);
143         for my $ver ( sort keys %Module::CoreList::released ) {
144           printf "%-${max_ver_len}s    %s\n", format_perl_version($ver), $Module::CoreList::released{$ver};
145         }
146         print "\n";
147         exit 0;
148     }
149
150     my $num_r = numify_version( $Opts{r} );
151     my $version_hash = Module::CoreList->find_version($num_r);
152
153     if( !$version_hash ) {
154         print "\nModule::CoreList has no info on perl $Opts{r}\n\n";
155         exit 1;
156     }
157
158     printf "Perl %s was released on %s\n\n", format_perl_version($num_r), $Module::CoreList::released{$num_r};
159     exit 0;
160 }
161
162 if(exists $Opts{v} ){
163     if( !$Opts{v} ) {
164         print "\nModule::CoreList has info on the following perl versions:\n";
165         print format_perl_version($_)."\n" for sort keys %Module::CoreList::version;
166         print "\n";
167         exit 0;
168     }
169
170     my $num_v = numify_version( $Opts{v} );
171     my $version_hash = Module::CoreList->find_version($num_v);
172
173     if( !$version_hash ) {
174         print "\nModule::CoreList has no info on perl $Opts{v}\n\n";
175         exit 1;
176     }
177
178     if ( !@ARGV ) {
179         print "\nThe following modules were in perl $Opts{v} CORE\n";
180         my $max_mod_len = max_mod_len($version_hash);
181         for my $mod ( sort keys %$version_hash ) {
182             printf "%-${max_mod_len}s  %s\n", $mod, $version_hash->{$mod} || "";
183         }
184         print "\n";
185         exit 0;
186     }
187 }
188
189 if ($Opts{diff}) {
190     if(@ARGV != 2) {
191         die "\nprovide exactly two perl core versions to diff with --diff\n";
192     }
193
194     my ($old_ver, $new_ver) = @ARGV;
195
196     my $old = numify_version($old_ver);
197     my $new = numify_version($new_ver);
198
199     my %diff = Module::CoreList::changes_between($old, $new);
200
201     for my $lib (sort keys %diff) {
202       my $diff = $diff{$lib};
203
204       my $was = ! exists  $diff->{left} ? '(absent)'
205               : ! defined $diff->{left} ? '(undef)'
206               :                          $diff->{left};
207
208       my $now = ! exists  $diff->{right} ? '(absent)'
209               : ! defined $diff->{right} ? '(undef)'
210               :                          $diff->{right};
211
212         printf "%-35s %10s %10s\n", $lib, $was, $now;
213     }
214     exit(0);
215 }
216
217 if ( !@ARGV ) {
218     pod2usage(0);
219 }
220
221 while (@ARGV) {
222         my ($mod, $ver);
223         if ($ARGV[0] =~ /=/) {
224             ($mod, $ver) = split /=/, shift @ARGV;
225         } else {
226             $mod = shift @ARGV;
227             $ver = (@ARGV && $ARGV[0] =~ /^\d/) ? shift @ARGV : "";
228         }
229
230         if ($mod !~ m|^/(.*)/([imosx]*)$|) { # not a regex
231             module_version($mod,$ver);
232         } else {
233             my $re;
234             eval { $re = $2 ? qr/(?$2)($1)/ : qr/$1/; }; # trap exceptions while building regex
235             if ($@) {
236                 # regex errors are usually like 'Quantifier follow nothing in regex; marked by ...'
237                 # then we drop text after ';' to shorten message
238                 my $errmsg = $@ =~ /(.*);/ ? $1 : $@;
239                 warn "\n$mod  is a bad regex: $errmsg\n";
240                 next;
241             }
242             my @mod = Module::CoreList->find_modules($re);
243             if (@mod) {
244                 module_version($_, $ver) for @mod;
245             } else {
246                 $ver |= '';
247                 print "\n$mod $ver has no match in CORE (or so I think)\n";
248             }
249
250         }
251 }
252
253 exit();
254
255 sub module_version {
256     my($mod,$ver) = @_;
257
258     if ( $Opts{v} ) {
259         my $numeric_v = numify_version($Opts{v});
260         my $version_hash = Module::CoreList->find_version($numeric_v);
261         if ($version_hash) {
262             print $mod, " ", $version_hash->{$mod} || 'undef', "\n";
263             return;
264         }
265         else { die "Shouldn't happen" }
266     }
267
268     my $ret = $Opts{d}
269         ? Module::CoreList->first_release_by_date(@_)
270         : Module::CoreList->first_release(@_);
271     my $msg = $mod;
272     $msg .= " $ver" if $ver;
273
274     my $rem = $Opts{d}
275         ? Module::CoreList->removed_from_by_date($mod)
276         : Module::CoreList->removed_from($mod);
277
278     if( defined $ret ) {
279         $msg .= " was ";
280         $msg .= "first " unless $ver;
281         $msg .= "released with perl " . format_perl_version($ret);
282         $msg .= " and removed from " . format_perl_version($rem) if $rem;
283     } else {
284         $msg .= " was not in CORE (or so I think)";
285     }
286
287     print "\n",$msg,"\n";
288
289     if(defined $ret and exists $Opts{a} and $Opts{a}){
290         display_a($mod);
291     }
292 }
293
294
295 sub max_mod_len {
296     my $versions = shift;
297     my $max = 0;
298     for my $mod (keys %$versions) {
299         $max = max($max, length $mod);
300     }
301
302     return $max;
303 }
304
305 sub max {
306     my($this, $that) = @_;
307     return $this if $this > $that;
308     return $that;
309 }
310
311 sub display_a {
312     my $mod = shift;
313
314     for my $v (grep !/000$/, sort keys %Module::CoreList::version ) {
315         next unless exists $Module::CoreList::version{$v}{$mod};
316
317         my $mod_v = $Module::CoreList::version{$v}{$mod} || 'undef';
318         printf "  %-10s %-10s\n", format_perl_version($v), $mod_v;
319     }
320     print "\n";
321 }
322
323
324 {
325     my $have_version_pm;
326     sub have_version_pm {
327         return $have_version_pm if defined $have_version_pm;
328         return $have_version_pm = eval { require version; 1 };
329     }
330 }
331
332
333 sub format_perl_version {
334     my $v = shift;
335     return $v if $v < 5.006 or !have_version_pm;
336     return version->new($v)->normal;
337 }
338
339
340 sub numify_version {
341     my $ver = shift;
342     if ($ver =~ /\..+\./) {
343         have_version_pm()
344             or die "You need to install version.pm to use dotted version numbers\n";
345         $ver = version->new($ver)->numify;
346     }
347     $ver += 0;
348     return $ver;
349 }
350
351 =head1 EXAMPLES
352
353     $ corelist File::Spec
354
355     File::Spec was first released with perl 5.005
356
357     $ corelist File::Spec 0.83
358
359     File::Spec 0.83 was released with perl 5.007003
360
361     $ corelist File::Spec 0.89
362
363     File::Spec 0.89 was not in CORE (or so I think)
364
365     $ corelist File::Spec::Aliens
366
367     File::Spec::Aliens  was not in CORE (or so I think)
368
369     $ corelist /IPC::Open/
370
371     IPC::Open2 was first released with perl 5
372
373     IPC::Open3 was first released with perl 5
374
375     $ corelist /MANIFEST/i
376
377     ExtUtils::Manifest was first released with perl 5.001
378
379     $ corelist /Template/
380
381     /Template/  has no match in CORE (or so I think)
382
383     $ corelist -v 5.8.8 B
384
385     B                        1.09_01
386
387     $ corelist -v 5.8.8 /^B::/
388
389     B::Asmdata               1.01
390     B::Assembler             0.07
391     B::Bblock                1.02_01
392     B::Bytecode              1.01_01
393     B::C                     1.04_01
394     B::CC                    1.00_01
395     B::Concise               0.66
396     B::Debug                 1.02_01
397     B::Deparse               0.71
398     B::Disassembler          1.05
399     B::Lint                  1.03
400     B::O                     1.00
401     B::Showlex               1.02
402     B::Stackobj              1.00
403     B::Stash                 1.00
404     B::Terse                 1.03_01
405     B::Xref                  1.01
406
407 =head1 COPYRIGHT
408
409 Copyright (c) 2002-2007 by D.H. aka PodMaster
410
411 Currently maintained by the perl 5 porters E<lt>perl5-porters@perl.orgE<gt>.
412
413 This program is distributed under the same terms as perl itself.
414 See http://perl.org/ or http://cpan.org/ for more info on that.
415
416 =cut