This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Cwd/File::Spec version bump to 3.40
[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 use List::Util qw/maxstr/;
128
129 my %Opts;
130
131 GetOptions(
132     \%Opts,
133     qw[ help|?! man! r|release:s v|version:s a! d diff|D ]
134 );
135
136 pod2usage(1) if $Opts{help};
137 pod2usage(-verbose=>2) if $Opts{man};
138
139 if(exists $Opts{r} ){
140     if ( !$Opts{r} ) {
141         print "\nModule::CoreList has release info for the following perl versions:\n";
142         my $versions = { };
143         my $max_ver_len = max_mod_len(\%Module::CoreList::released);
144         for my $ver ( sort keys %Module::CoreList::released ) {
145           printf "%-${max_ver_len}s    %s\n", format_perl_version($ver), $Module::CoreList::released{$ver};
146         }
147         print "\n";
148         exit 0;
149     }
150
151     my $num_r = numify_version( $Opts{r} );
152     my $version_hash = Module::CoreList->find_version($num_r);
153
154     if( !$version_hash ) {
155         print "\nModule::CoreList has no info on perl $Opts{r}\n\n";
156         exit 1;
157     }
158
159     printf "Perl %s was released on %s\n\n", format_perl_version($num_r), $Module::CoreList::released{$num_r};
160     exit 0;
161 }
162
163 if(exists $Opts{v} ){
164     if( !$Opts{v} ) {
165         print "\nModule::CoreList has info on the following perl versions:\n";
166         print format_perl_version($_)."\n" for sort keys %Module::CoreList::version;
167         print "\n";
168         exit 0;
169     }
170
171     my $num_v = numify_version( $Opts{v} );
172     my $version_hash = Module::CoreList->find_version($num_v);
173
174     if( !$version_hash ) {
175         print "\nModule::CoreList has no info on perl $Opts{v}\n\n";
176         exit 1;
177     }
178
179     if ( !@ARGV ) {
180         print "\nThe following modules were in perl $Opts{v} CORE\n";
181         my $max_mod_len = max_mod_len($version_hash);
182         for my $mod ( sort keys %$version_hash ) {
183             printf "%-${max_mod_len}s  %s\n", $mod, $version_hash->{$mod} || "";
184         }
185         print "\n";
186         exit 0;
187     }
188 }
189
190 if ($Opts{diff}) {
191     if(@ARGV != 2) {
192         die "\nprovide exactly two perl core versions to diff with --diff\n";
193     }
194
195     my ($old_ver, $new_ver) = @ARGV;
196
197     my $old = numify_version($old_ver);
198     my $new = numify_version($new_ver);
199
200     my %diff = Module::CoreList::changes_between($old, $new);
201
202     for my $lib (sort keys %diff) {
203       my $diff = $diff{$lib};
204
205       my $was = ! exists  $diff->{left} ? '(absent)'
206               : ! defined $diff->{left} ? '(undef)'
207               :                          $diff->{left};
208
209       my $now = ! exists  $diff->{right} ? '(absent)'
210               : ! defined $diff->{right} ? '(undef)'
211               :                          $diff->{right};
212
213         printf "%-35s %10s %10s\n", $lib, $was, $now;
214     }
215     exit(0);
216 }
217
218 if ( !@ARGV ) {
219     pod2usage(0);
220 }
221
222 while (@ARGV) {
223         my ($mod, $ver);
224         if ($ARGV[0] =~ /=/) {
225             ($mod, $ver) = split /=/, shift @ARGV;
226         } else {
227             $mod = shift @ARGV;
228             $ver = (@ARGV && $ARGV[0] =~ /^\d/) ? shift @ARGV : "";
229         }
230
231         if ($mod !~ m|^/(.*)/([imosx]*)$|) { # not a regex
232             module_version($mod,$ver);
233         } else {
234             my $re;
235             eval { $re = $2 ? qr/(?$2)($1)/ : qr/$1/; }; # trap exceptions while building regex
236             if ($@) {
237                 # regex errors are usually like 'Quantifier follow nothing in regex; marked by ...'
238                 # then we drop text after ';' to shorten message
239                 my $errmsg = $@ =~ /(.*);/ ? $1 : $@;
240                 warn "\n$mod  is a bad regex: $errmsg\n";
241                 next;
242             }
243             my @mod = Module::CoreList->find_modules($re);
244             if (@mod) {
245                 module_version($_, $ver) for @mod;
246             } else {
247                 $ver |= '';
248                 print "\n$mod $ver has no match in CORE (or so I think)\n";
249             }
250
251         }
252 }
253
254 exit();
255
256 sub module_version {
257     my($mod,$ver) = @_;
258
259     if ( $Opts{v} ) {
260         my $numeric_v = numify_version($Opts{v});
261         my $version_hash = Module::CoreList->find_version($numeric_v);
262         if ($version_hash) {
263             print $mod, " ", $version_hash->{$mod} || 'undef', "\n";
264             return;
265         }
266         else { die "Shouldn't happen" }
267     }
268
269     my $ret = $Opts{d}
270         ? Module::CoreList->first_release_by_date(@_)
271         : Module::CoreList->first_release(@_);
272     my $msg = $mod;
273     $msg .= " $ver" if $ver;
274
275     my $rem = $Opts{d}
276         ? Module::CoreList->removed_from_by_date($mod)
277         : Module::CoreList->removed_from($mod);
278
279         my $when = maxstr(values %Module::CoreList::released);
280     print "\n","Data for $when\n";
281
282     if( defined $ret ) {
283         my $deprecated = Module::CoreList->deprecated_in($mod);
284         $msg .= " was ";
285         $msg .= "first " unless $ver;
286         $msg .= "released with perl " . format_perl_version($ret);
287         $msg .= ( $rem ? ',' : ' and' ) . " deprecated in " . format_perl_version($deprecated) if $deprecated;
288         $msg .= " and removed from " . format_perl_version($rem) if $rem;
289     } else {
290         $msg .= " was not in CORE (or so I think)";
291     }
292
293     print $msg,"\n";
294
295     if(defined $ret and exists $Opts{a} and $Opts{a}){
296         display_a($mod);
297     }
298 }
299
300
301 sub max_mod_len {
302     my $versions = shift;
303     my $max = 0;
304     for my $mod (keys %$versions) {
305         $max = max($max, length $mod);
306     }
307
308     return $max;
309 }
310
311 sub max {
312     my($this, $that) = @_;
313     return $this if $this > $that;
314     return $that;
315 }
316
317 sub display_a {
318     my $mod = shift;
319
320     for my $v (grep !/000$/, sort keys %Module::CoreList::version ) {
321         next unless exists $Module::CoreList::version{$v}{$mod};
322
323         my $mod_v = $Module::CoreList::version{$v}{$mod} || 'undef';
324         printf "  %-10s %-10s\n", format_perl_version($v), $mod_v;
325     }
326     print "\n";
327 }
328
329
330 {
331     my $have_version_pm;
332     sub have_version_pm {
333         return $have_version_pm if defined $have_version_pm;
334         return $have_version_pm = eval { require version; 1 };
335     }
336 }
337
338
339 sub format_perl_version {
340     my $v = shift;
341     return $v if $v < 5.006 or !have_version_pm;
342     return version->new($v)->normal;
343 }
344
345
346 sub numify_version {
347     my $ver = shift;
348     if ($ver =~ /\..+\./) {
349         have_version_pm()
350             or die "You need to install version.pm to use dotted version numbers\n";
351         $ver = version->new($ver)->numify;
352     }
353     $ver += 0;
354     return $ver;
355 }
356
357 =head1 EXAMPLES
358
359     $ corelist File::Spec
360
361     File::Spec was first released with perl 5.005
362
363     $ corelist File::Spec 0.83
364
365     File::Spec 0.83 was released with perl 5.007003
366
367     $ corelist File::Spec 0.89
368
369     File::Spec 0.89 was not in CORE (or so I think)
370
371     $ corelist File::Spec::Aliens
372
373     File::Spec::Aliens  was not in CORE (or so I think)
374
375     $ corelist /IPC::Open/
376
377     IPC::Open2 was first released with perl 5
378
379     IPC::Open3 was first released with perl 5
380
381     $ corelist /MANIFEST/i
382
383     ExtUtils::Manifest was first released with perl 5.001
384
385     $ corelist /Template/
386
387     /Template/  has no match in CORE (or so I think)
388
389     $ corelist -v 5.8.8 B
390
391     B                        1.09_01
392
393     $ corelist -v 5.8.8 /^B::/
394
395     B::Asmdata               1.01
396     B::Assembler             0.07
397     B::Bblock                1.02_01
398     B::Bytecode              1.01_01
399     B::C                     1.04_01
400     B::CC                    1.00_01
401     B::Concise               0.66
402     B::Debug                 1.02_01
403     B::Deparse               0.71
404     B::Disassembler          1.05
405     B::Lint                  1.03
406     B::O                     1.00
407     B::Showlex               1.02
408     B::Stackobj              1.00
409     B::Stash                 1.00
410     B::Terse                 1.03_01
411     B::Xref                  1.01
412
413 =head1 COPYRIGHT
414
415 Copyright (c) 2002-2007 by D.H. aka PodMaster
416
417 Currently maintained by the perl 5 porters E<lt>perl5-porters@perl.orgE<gt>.
418
419 This program is distributed under the same terms as perl itself.
420 See http://perl.org/ or http://cpan.org/ for more info on that.
421
422 =cut