This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Refactor corelist-perldelta so we can make it do other things too
[perl5.git] / Porting / corelist-perldelta.pl
1 #!perl
2 use 5.010;
3 use strict;
4 use warnings;
5 use lib 'Porting';
6 use Maintainers qw/%Modules/;
7 use Module::CoreList;
8 use Getopt::Long;
9
10 my $deprecated;
11
12 #--------------------------------------------------------------------------#
13
14 sub added {
15   my ($mod, $old_v, $new_v) = @_;
16   say "=item *\n";
17   say "C<$mod> $new_v has been added to the Perl core.\n";
18 }
19
20 sub updated {
21   my ($mod, $old_v, $new_v) = @_;
22   say "=item *\n";
23   say "C<$mod> has been upgraded from version $old_v to $new_v.\n";
24   if ( $deprecated->{$mod} ) {
25     say "NOTE: C<$mod> is deprecated and may be removed from a future version of Perl.\n";
26   }
27 }
28
29 sub removed {
30   my ($mod, $old_v, $new_v) = @_;
31   say "=item *\n";
32   say "C<$mod> has been removed from the Perl core.  Prior version was $old_v.\n";
33 }
34
35 sub generate_section {
36   my ($title, $item_sub, @mods ) = @_;
37   return unless @mods;
38
39   say "=head2 $title\n";
40   say "=over 4\n";
41
42   for my $tuple ( sort { lc($a->[0]) cmp lc($b->[0]) } @mods ) {
43     my ($mod,$old_v,$new_v) = @$tuple;
44     $old_v //= q('undef');
45     $new_v //= q('undef');
46     $item_sub->($mod, $old_v, $new_v);
47   }
48
49   say "=back\n";
50 }
51
52 #--------------------------------------------------------------------------#
53
54 sub run {
55   my %opt = (mode => 'generate');
56
57   GetOptions(\%opt,
58     'mode|m:s', # 'generate'
59   );
60
61   if ( $opt{mode} eq 'generate' ) {
62     # by default, compare latest two version in CoreList;
63     my @versions = sort keys %Module::CoreList::version;
64     my ($old, $new) = @ARGV;
65     $old ||= $versions[-2];
66     $new ||= $versions[-1];
67
68     do_generate($old => $new);
69   }
70   else {
71     die "Unrecognized mode '$opt{mode}'\n";
72   }
73
74   exit 0;
75 }
76
77 sub do_generate {
78   my ($old, $new) = @_;
79   my $corelist = \%Module::CoreList::version;
80
81   $deprecated = $Module::CoreList::deprecated{$new};
82
83   my (@new,@deprecated,@removed,@pragmas,@modules);
84
85   # %Modules defines what is currently in core
86   for my $k ( keys %Modules ) {
87     next unless exists $corelist->{$new}{$k};
88     my $old_ver = $corelist->{$old}{$k};
89     my $new_ver = $corelist->{$new}{$k};
90     # in core but not in last corelist
91     if ( ! exists $corelist->{$old}{$k} ) {
92       push @new, [$k, undef, $new_ver];
93     }
94     # otherwise just pragmas or modules
95     else {
96       my $old_ver = $corelist->{$old}{$k};
97       my $new_ver = $corelist->{$new}{$k};
98       next unless defined $old_ver && defined $new_ver && $old_ver ne $new_ver;
99       my $tuple = [ $k, $old_ver, $new_ver ];
100       if ( $k eq lc $k ) {
101         push @pragmas, $tuple;
102       }
103       else {
104         push @modules, $tuple;
105       }
106     }
107   }
108
109   # in old corelist, but not this one => removed
110   # N.B. This is exhaustive -- not just what's in %Modules, so modules removed from
111   # distributions will show up here, too.  Some person will have to review to see what's
112   # important. That's the best we can do without a historical Maintainers.pl
113   for my $k ( keys %{ $corelist->{$old} } ) {
114     if ( ! exists $corelist->{$new}{$k} ) {
115       push @removed, [$k, $corelist->{$old}{$k}, undef];
116     }
117   }
118
119   generate_section("New Modules and Pragmata", \&added, @new);
120   generate_section("Pragmata Changes", \&updated, @pragmas);
121   generate_section("Updated Modules", \&updated, @modules);
122   generate_section("Removed Modules and Pragmata", \&removed, @removed);
123 }
124
125 run;