./perl -Ilib Porting/corelist-perldelta.pl
# update the module changes for the Perl you are currently building
- perl Porting/corelist-perldelta.pl --mode=update Porting/perldelta.pod
+ ./perl -Ilib Porting/corelist-perldelta.pl --mode=update pod/perldelta.pod
# generate a diff between the corelist sections of two perldelta* files:
perl Porting/corelist-perldelta.pl --mode=check 5.017001 5.017002 <perl5172delta.pod
to generate the text and one to show the diff between the
corelist sections of the last perldelta and the next perldelta.
+Currently no information about Removed Modules is displayed in any of the
+modes.
+
=cut
my %sections = (
);
# by default, compare latest two version in CoreList;
- my @versions = sort keys %Module::CoreList::version;
- my ($old, $new) = (shift @ARGV, shift @ARGV);
- $old ||= $versions[-2];
- $new ||= $versions[-1];
+ my ($old, $new) = latest_two_perl_versions();
+
+ # use the provided versions if present
+ # @ARGV >=2 means [old_version] [new_version] [path/to/file]
+ if ( @ARGV >= 2) {
+ ($old, $new) = (shift @ARGV, shift @ARGV);
+ die "$old is an invalid version\n" if not exists
+ $Module::CoreList::version{$old};
+ die "$new is an invalid version\n" if not exists
+ $Module::CoreList::version{$new};
+ }
if ( $opt{mode} eq 'generate' ) {
do_generate($old => $new);
exit 0;
}
+sub latest_two_perl_versions {
+
+ my @versions = sort keys %Module::CoreList::version;
+
+ my $new = pop @versions;
+
+ # If a fully-padded version number ends in a zero (as in "5.019010"), that
+ # version shows up in %Module::CoreList::version both with and without its
+ # trailing zeros. So skip all versions that are numerically equal to $new.
+ pop @versions while @versions && $versions[-1] == $new;
+
+ die "Too few distinct core versions in %Module::CoreList::version ?!\n"
+ if !@versions;
+
+ return $versions[-1], $new;
+}
+
# Given two perl versions, it returns a list describing the core distributions that have changed.
# The first three elements are hashrefs corresponding to new, updated, and removed modules
# and are of the form (mostly, see the special remarks about removed):
# 'Distribution Name' => ['Distribution Name', previous version number, current version number]
-# where the version number is undef if the distribution did not exist the fourth element is
-# an arrayref of core distribution names of those distribution for which it is unknown whether
-# they have changed and therefore need to be manually checked.
+# where the version number is undef if the distribution did not exist.
+# The fourth element is an arrayref of core distribution names of those distribution for which it
+# is unknown whether they have changed and therefore need to be manually checked.
#
# In most cases, the distribution name in %Modules corresponds to the module that is representative
# of the distribution as listed in Module::CoreList. However, there are a few distribution names
-# that do not correspond to a module. %distToModules, has been created which maps the distribution
+# that do not correspond to a module. %distToModules has been created which maps the distribution
# name to a representative module. The representative module was chosen by either looking at the
# Makefile of the distribution or by seeing which module the distribution has been traditionally
-# listed under in past perldelta.
+# listed under in past perldeltas.
#
# There are a few distributions for which there is no single representative module (e.g. libnet).
# These distributions are returned as the last element of the list.
# %Modules contains a final key, _PERLLIB, which contains a list of modules that are owned by p5p.
# This list contains modules and pragmata that may also be present in Module::CoreList.
# A list of modules are in the list @unclaimedModules, which were manually listed based on whether
-# they were independent modules and whether they have been listed in past perldelta.
+# they were independent modules and whether they have been listed in past perldeltas.
# The pragmata were found by doing something like:
# say for sort grep { $_ eq lc $_ and !exists $Modules{$_}}
# keys %{$Module::CoreList::version{'5.019003'}}
};
my @unclaimedModules = qw/AnyDBM_File B B::Concise B::Deparse Benchmark Class::Struct Config::Extensions DB DBM_Filter Devel::Peek DirHandle DynaLoader English Errno ExtUtils::Embed ExtUtils::Miniperl ExtUtils::Typemaps ExtUtils::XSSymSet Fcntl File::Basename File::Compare File::Copy File::DosGlob File::Find File::Glob File::stat FileCache FileHandle FindBin GDBM_File Getopt::Std Hash::Util Hash::Util::FieldHash I18N::Langinfo IPC::Open3 NDBM_File ODBM_File Opcode PerlIO PerlIO::encoding PerlIO::mmap PerlIO::scalar PerlIO::via Pod::Functions Pod::Html POSIX SDBM_File SelectSaver Symbol Sys::Hostname Thread Tie::Array Tie::Handle Tie::Hash Tie::Hash::NamedCapture Tie::Memoize Tie::Scalar Tie::StdHandle Tie::SubstrHash Time::gmtime Time::localtime Time::tm Unicode::UCD UNIVERSAL User::grent User::pwent VMS::DCLsym VMS::Filespec VMS::Stdio XS::Typemap Win32CORE/;
- my @unclaimedPragmata = qw/_charnames arybase attributes blib bytes charnames deprecate diagnostics encoding feature fields filetest inc::latest integer less locale mro open ops overload overloading re sigtrap sort strict subs utf8 vars vmsish/;
+ my @unclaimedPragmata = qw/arybase attributes blib bytes charnames deprecate diagnostics encoding feature fields filetest inc::latest integer less locale mro open ops overload overloading re sigtrap sort strict subs utf8 vars vmsish/;
my @unclaimed = (@unclaimedModules, @unclaimedPragmata);
my %distToModules = (
'IO-Compress' => [
{
- 'name' => 'IO-Compress',
+ 'name' => 'IO-Compress',
'modification' => $getModifyType->( $changes{'IO::Compress::Base'} ),
- 'data' => $changes{'IO::Compress::Base'}
+ 'data' => $changes{'IO::Compress::Base'}
+ }
+ ],
+ 'libnet' => [
+ {
+ 'name' => 'libnet',
+ 'modification' => $getModifyType->( $changes{'Net::Cmd'} ),
+ 'data' => $changes{'Net::Cmd'}
}
],
'Locale-Codes' => [
'data' => $changes{'Cwd'}
}
],
+ 'podlators' => [
+ {
+ 'name' => 'podlators',
+ 'modification' => $getModifyType->( $changes{'Pod::Text'} ),
+ 'data' => $changes{'Pod::Text'}
+ }
+ ],
'Scalar-List-Utils' => [
{
'name' => 'List::Util',
'name' => 'Scalar::Util',
'modification' => $getModifyType->( $changes{'Scalar::Util'} ),
'data' => $changes{'Scalar::Util'}
+ },
+ {
+ 'name' => 'Sub::Util',
+ 'modification' => $getModifyType->( $changes{'Sub::Util'} ),
+ 'data' => $changes{'Sub::Util'}
}
],
'Text-Tabs+Wrap' => [
my ( $existing, $old, $new ) = @_;
my ( $added, $removed, $updated, $manuallyCheck ) = corelist_delta( $old => $new );
- if ($manuallyCheck) {
- say "Please check whether the following distributions have been modified and list accordingly";
+ if (@{$manuallyCheck}) {
+ print "It cannot be determined whether the following distributions have changed.\n";
+ print "Please check and list accordingly:\n";
say "\t* $_" for sort @{$manuallyCheck};
+ print "\n";
}
my $data = {
my $text = DeltaUpdater::transform_pod( $existing, $data );
open my $out, '>', $existing or die "can't open perldelta file $existing: $!";
+ binmode($out);
print $out $text;
close $out;
+ say "The New and Updated Modules and Pragamata sections in $existing have been updated";
+ say "Please ensure the Removed Modules and Pragmata section is up-to-date";
}
sub do_generate {
my ($added, $removed, $updated, $manuallyCheck) = corelist_delta($old => $new);
if ($manuallyCheck) {
- say "\nXXXPlease check whether the following distributions have been modified and list accordingly";
+ print "\nXXXIt cannot be determined whether the following distributions have changed.\n";
+ print "Please check and list accordingly:\n";
say "\t$_" for @{$manuallyCheck};
+ print "\n";
}
my $data = {
my $content = $item->{text};
my $module = $item->{name};
+ #skip dummy items
+ next if !$module and $content =~ /\s*xx*\s*/i;
+
say "Could not parse module name; line is:\n\t$content" and next unless $module;
- say "$module is not in Module::CoreList; check to see that it is not covered by another section" and next
- unless $data->{$title}{$module};
+
+ if ( !$data->{$title}{$module} ) {
+ print "$module is not listed as being $title in Module::CoreList.\n";
+ print "Ensure Module::CoreList has been updated and\n";
+ print "check to see that the distribution is not listed under another name.\n\n";
+ next;
+ }
if ( $title eq 'new' ) {
my ($new) = $content =~ /(\d[^\s]+)\s+has\s+been.*$/m;
sub add_to_section {
my ( $section, $data, $title ) = @_;
- #undef is a valid version name in Module::CoreList so supress warnings about concatenating undef values
+ #undef is a valid version name in Module::CoreList so suppress warnings about concatenating undef values
no warnings 'uninitialized';
for ( values %{ $data->{$title} } ) {
my ( $mod, $old_v, $new_v ) = @{$_};
# if we could not parse the module name, it will be uninitalized
# in sort. This is not a problem as it will just result in these
- # sections being placed near the begining of the section
+ # sections being placed near the beginning of the section
no warnings 'uninitialized';
$section->{items} =
[ sort { lc $a->{name} cmp lc $b->{name} } @{ $section->{items} } ];
my ( $section_name, $title ) = @{$_};
my $section = $sections{$section_name} // {
- name => $section_name,
- preceeding_text => "=head2 $_->[0]\n=over 4\n",
- following_text => "=back\n",
- items => [],
- manual => 1
+ name => $section_name,
+ preceding_text => "=head2 $_->[0]\n=over 4\n",
+ following_text => "=back\n",
+ items => [],
+ manual => 1
};
$section = update_section( $section, $data, $title );
my $items = reduce { no warnings 'once'; $a . $b->{text} }
( '', @{ $section->{items} } );
$out .=
- ( $section->{preceeding_text} // '' )
+ ( $section->{preceding_text} // '' )
. $items
. ( $section->{following_text} // '' );
}
# will contain hashrefs corresponding to new, updated and removed
# modules and pragmata keyed by section name
# each section is hashref of the structure
- # preceeding_text => Text occuring before and including the over
- # region containing the list of modules,
- # items => [Arrayref of hashrefs corresponding to a module
- # entry],
+ # preceding_text => Text occurring before and including the over
+ # region containing the list of modules,
+ # items => [Arrayref of hashrefs corresponding to a module
+ # entry],
# an entry has the form:
# name => Module name or undef if the name could not be determined
# text => The text of the entry, including the item heading
#
- # following_text => Any text not corresponding to a module
- # that occurs after the first module
+ # following_text => Any text not corresponding to a module
+ # that occurs after the first module
#
# the sections are converted to a pod string by calling sections_to_pod()
my %sections;
# we are in the Modules_and_Pragmata's section
my $in_Modules_and_Pragmata;
+
# we are the Modules_and_Pragmata's section but have not
# encountered any of the desired sections. We use this
# flag to determine whether we should append the text to $out
# or we need to delay appending until the module listings are
# processed and instead append to $append_to_out
my $in_Modules_and_Pragmata_preamble;
+
my $done_processing_Modules_and_Pragmata;
my $current_section;
+
# $nested_element_level == 0 : not in an over region, treat lines as text
# $nested_element_level == 1 : presumably in the top over region that
# corresponds to the module listing. Treat
# $nested_element_level > 1 : we only consider these values when we are in an item
# We treat lines as the text of the current item.
my $nested_element_level = 0;
+
my $current_item;
my $need_to_parse_module_name;
my $append_to_out = '';
open my $fh, '<', $existing or die "can't open perldelta file $existing: $!";
+ binmode($fh);
while (<$fh>) {
# treat the rest of the file as plain text
}
my $title = get_section_name_from_heading($name);
if ( exists $sections{$title} ) {
- die "$name occured twice at line no. $.";
+ die "$name occurred twice at line no. $.";
}
- $current_section = {};
- $current_section->{name} = $title;
- $current_section->{preceeding_text} = $_;
- $current_section->{items} = [];
- $nested_element_level = 0;
+ $current_section = {};
+ $current_section->{name} = $title;
+ $current_section->{preceding_text} = $_;
+ $current_section->{items} = [];
+ $nested_element_level = 0;
next;
}
$current_section->{following_text} .= $_;
}
else {
- $current_section->{preceeding_text} .= $_;
+ $current_section->{preceding_text} .= $_;
}
next;
}
}
if ( scalar @{ $current_section->{items} } == 0 ) {
- $current_section->{preceeding_text} .= $_;
+ $current_section->{preceding_text} .= $_;
}
else {
$current_section->{following_text} .= $_;
# from VERSION_NUMBER to VERSION_NUMBER and MODULE from VERSION_NUMBER to VERSION_NUMBER
# from VERSION_NUMBER to VERSION_NUMBER, and MODULE from VERSION_NUMBER to VERSION_NUMBER
#
- # some perldelta contain more than one module listed in an entry, this only attempts to match the
+ # some perldeltas contain more than one module listed in an entry, this only attempts to match the
# first module
my ($old, $new) = $second =~
/from\s+(?:version\s+)?(\d[^\s]+)\s+to\s+(?:version\s+)?(\d[^\s,]+?)(?=[\s,]|\.\s|\.$|$).*/s;