Add Porting/new-perldelta.pl, which automates adding a new perldelta.
authorNicholas Clark <nick@ccl4.org>
Wed, 9 Nov 2011 20:50:56 +0000 (21:50 +0100)
committerNicholas Clark <nick@ccl4.org>
Fri, 18 Nov 2011 10:08:58 +0000 (11:08 +0100)
Strictly, "mostly automates", as it doesn't run `git add`, or test that the
build is clean. However, it simplifies a gnarly step in the release manager's
guide, so it's progress.

MANIFEST
Porting/new-perldelta.pl [new file with mode: 0644]
Porting/perldelta_template.pod
Porting/pod_lib.pl
Porting/release_managers_guide.pod

index 37c9c05..03988cb 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -4692,6 +4692,7 @@ Porting/makerel                   Release making utility
 Porting/make_snapshot.pl       Make a tgz snapshot of our tree with a .patch file in it
 Porting/manicheck              Check against MANIFEST
 Porting/manisort               Sort the MANIFEST
+Porting/new-perldelta.pl       Generate a new perldelta
 Porting/newtests-perldelta.pl  Generate Perldelta stub for newly added tests
 Porting/perldelta_template.pod Template for creating new perldelta.pod files
 Porting/perlhist_calculate.pl          Perform calculations to update perlhist
diff --git a/Porting/new-perldelta.pl b/Porting/new-perldelta.pl
new file mode 100644 (file)
index 0000000..4fa7fd1
--- /dev/null
@@ -0,0 +1,108 @@
+#!/usr/bin/perl -w
+use strict;
+
+# This needs to be able to run from a clean checkout, hence assume only system
+# perl, which may be too old to have autodie
+
+require 'Porting/pod_lib.pl';
+
+my $state = get_pod_metadata(1);
+my (undef, $old_major, $old_minor) = @{$state->{delta_version}};
+# For now, hard code it for the simple ones...
+my $new_major = $old_major;
+my $new_minor = $old_minor + 1;
+# These two are just for "If you are upgrading from earlier releases..." in
+# the perldelta template.
+my $was_major = $old_major;
+my $was_minor = $old_minor - 1;
+# I may have missed some corner cases here:
+if ($was_minor < 0) {
+    $was_minor = 0;
+    --$was_major;
+}
+my $newdelta_filename = "perl5$new_major${new_minor}delta.pod";
+
+{
+    # For now, just tell the user what to add, as it's safer.
+    my %add;
+
+    sub git_add_new {
+        push @{$add{new}}, shift;
+    }
+
+    sub git_add_modified {
+        push @{$add{modified}}, shift;
+    }
+
+    sub notify_success {
+        return unless %add;
+        print "Please run:\n";
+        foreach (qw(new modified)) {
+            print "    git add @{$add{$_}}\n" if $add{$_};
+        }
+        print "\nBefore committing please check that the build works and make test_porting passes\n";
+    }
+}
+
+my $filename = 'pod/.gitignore';
+my $gitignore = slurp_or_die($filename);
+
+$gitignore =~ s{^/$state->{delta_target}$}
+               {/$newdelta_filename}m
+    or die "Can't find /$state->{delta_target} in $filename";
+
+write_or_die($filename, $gitignore);
+git_add_modified($filename);
+
+my $olddelta = slurp_or_die('pod/perldelta.pod');
+
+$olddelta =~ s{^(perl)(delta - what is new for perl v5.$old_major.$old_minor)$}
+              {$1 . "5$old_major$old_minor" . $2}me
+    or die "Can't find expected NAME contents in $olddelta";
+
+my $olddeltaname = "pod/perl5$old_major${old_minor}delta.pod";
+write_or_die($olddeltaname, $olddelta);
+git_add_new($olddeltaname);
+
+$filename = 'Porting/perldelta_template.pod';
+my $newdelta = slurp_or_die($filename);
+
+foreach([rXXX => $was_major],
+        [sXXX => $old_major],
+        [tXXX => $new_major],
+        [aXXX => $was_minor],
+        [bXXX => $old_minor],
+        [cXXX => $new_minor],
+        ['5XXX' => 5 . $old_major . $old_minor]) {
+    my ($token, $value) = @$_;
+    $newdelta =~ s/$token/$value/g
+        or die "Can't find '$token' in $filename";
+}
+
+write_or_die('pod/perldelta.pod', $newdelta);
+git_add_modified('pod/perldelta.pod');
+
+$filename = 'pod.lst';
+my $pod_master = slurp_or_die($filename);
+
+$pod_master =~ s{^(\s*perl5)($old_major$old_minor)(delta\s+Perl changes in version )(5\.\d+\.\d+)(.*)}
+    {$1 . $new_major . $new_minor .$3 . "5.$new_major.$new_minor" . $5 . "\n" .
+         "$1$2$3$4$5"}me
+    or die "Can't find perldelta line in $filename";
+
+write_or_die($filename, $pod_master);
+git_add_modified($filename);
+
+my $command = "$^X Porting/pod_rules.pl";
+system $command
+    and die "Could not run '$command', \$? = $?";
+git_add_modified(map {chomp $_; $_} `$^X Porting/pod_rules.pl --showfiles`);
+
+notify_success();
+
+# Local variables:
+# cperl-indent-level: 4
+# indent-tabs-mode: nil
+# End:
+#
+# ex: set ts=8 sts=4 sw=4 et:
index 8406438..41f39b3 100644 (file)
@@ -5,16 +5,16 @@
 [ this is a template for a new perldelta file. Any text flagged as
 XXX needs to be processed before release. ]
 
-perldelta - what is new for perl v5.XXX.XXX
+perldelta - what is new for perl v5.tXXX.cXXX
 
 =head1 DESCRIPTION
 
-This document describes differences between the 5.XXX.XXX release and
-the 5.XXX.XXX release.
+This document describes differences between the 5.sXXX.bXXX release and
+the 5.tXXX.cXXX release.
 
-If you are upgrading from an earlier release such as 5.YYY.YYY, first read
-L<perl5YYYdelta>, which describes differences between 5.ZZZ.ZZZ and
-5.YYY.YYY.
+If you are upgrading from an earlier release such as 5.rXXX.aXXX, first read
+L<perl5XXXdelta>, which describes differences between 5.rXXX.aXXX and
+5.sXXX.bXXX.
 
 =head1 Notice
 
index 6caeb19..0d7755b 100644 (file)
@@ -18,6 +18,24 @@ sub open_or_die {
     return $fh;
 }
 
+sub slurp_or_die {
+    my $filename = shift;
+    my $fh = open_or_die($filename);
+    binmode $fh;
+    local $/;
+    my $contents = <$fh>;
+    die "Can't read $filename: $!" unless defined $contents and close $fh;
+    return $contents;
+}
+
+sub write_or_die {
+    my ($filename, $contents) = @_;
+    open my $fh, '>', $filename or die "Can't open $filename for writing: $!";
+    binmode $fh;
+    print $fh $contents or die "Can't write to $filename: $!";
+    close $fh or die "Can't close $filename: $!";
+}
+
 sub get_pod_metadata {
     # Do we expect to find generated pods on disk?
     my $permit_missing_generated = shift;
@@ -43,9 +61,10 @@ sub get_pod_metadata {
     my $fh = open_or_die($filename);
     my $contents = do {local $/; <$fh>};
     my @want =
-        $contents =~ /perldelta - what is new for perl v5\.(\d+)\.(\d+)\n/;
+        $contents =~ /perldelta - what is new for perl v(5)\.(\d+)\.(\d+)\n/;
     die "Can't extract version from $filename" unless @want;
-    $state{delta_target} = "perl5$want[0]$want[1]delta.pod";
+    $state{delta_target} = join '', 'perl', @want, 'delta.pod';
+    $state{delta_version} = \@want;
 
     # This way round so that keys can act as a MANIFEST skip list
     # Targets will always be in the pod directory. Currently we can only cope
index 42ecf44..389d5cc 100644 (file)
@@ -861,70 +861,42 @@ to CPAN.
 
 I<You MUST SKIP this step for RC>
 
-Create a new perldelta.
-
-B<Note>: currently, the buildtoc below must be run in a I<built> perl source
-directory, as at least one of the pod files it expects to find is
-autogenerated: perluniprops.pod. But you can't build perl if you've added
-the new perldelta file and not updated toc. So, make sure you have a built
-perl (with a pod/perluniprops.pod file) now, I<before> continuing.
+XXX These steps are not yet battle tested. No plan survives contact with the
+enemy. Delete this line once they been used for real, and any corrections
+made.
 
-First, update the F<pod/.gitignore> file  to ignore the next
-release's generated F<pod/perlNNNdelta.pod> file rather than this release's
-one which we are about to set in stone (where NNN is the perl version number
-without the dots. i.e. 5135 for 5.13.5).
+Create a new perldelta.
 
-    $ (edit pod/.gitignore )
-    $ git add pod/.gitignore
+=over 4
 
-Then, move the existing F<pod/perldelta.pod> to F<pod/perlNNNdelta.pod>,
-and edit the moved delta file to change the C<NAME> from C<perldelta> to
-C<perlNNNdelta>.  For example, assuming you just released 5.10.1, and are
-about to create the 5.10.2 perldelta:
+=item *
 
-    $ rm  pod/perl5101delta.pod # remove the auto-generated file, if any
-    $ git mv pod/perldelta.pod pod/perl5101delta.pod
-    $ (edit pod/perl5101delta.pod to retitle)
-    $ git add pod/perl5101delta.pod
+Confirm that you have a clean checkout with no local changes.
 
-Then create a new empty perldelta.pod file for the new release; see
-F<Porting/how_to_write_a_perldelta.pod>. You should be able to do this by
-just copying in a skeleton template and then doing a quick fix up of the
-version numbers.  Then commit the move and the new file.
+=item *
 
-    $ cp -i Porting/perldelta_template.pod pod/perldelta.pod
-    $ (edit pod/perldelta.pod)
-    $ git add pod/perldelta.pod
-    $ git commit -m 'create perldelta for 5.10.2'
+Run F<Porting/new-perldelta.pl>
 
-=head3 update perldelta TOC and references
+=item *
 
-Now you need to update various tables of contents related to perldelta,
-most of which can be generated automatically.
+Run the C<git add> commands it outputs to add new and modified files.
 
-Edit F<pod.lst>: add the new entry for the perlNNNdelta file for the
-current version (the file that will be symlinked to perldelta).
+=item *
 
-Manually create a temporary link to the new delta file; normally this is
-done from the Makefile, but the Makefile is updated by buildtoc, and
-buildtoc won't run without the file there:
+Verify that the build still works, by running C<./Configure> and
+C<make test_porting>
 
-    $ ln -s pod/perldelta.pod pod/perl5102delta.pod
+=item *
 
-Run C<perl pod/buildtoc --build-all> to update the F<perldelta> version in
-the following files:
+If F<t/porting/podcheck.t> spots errors in the new F<pod/perldelta.pod>,
+run C<./perl -MTestInit t/porting/podcheck.t | less> for more detail.
+Skip to the end of its test output to see the options it offers you.
 
-    MANIFEST
-    Makefile.SH
-    pod/perl.pod
-    vms/descrip_mms.template
-    win32/Makefile
-    win32/makefile.mk
-    win32/pod.mak
+=item *
 
-Finally, commit:
+When C<make test_porting> passes, commit the new perldelta.
 
-    $ git commit -a -m 'update TOC for perlNNNdelta'
+=back
 
 At this point you may want to compare the commit with a previous bump to
 see if they look similar.  See commit dd885b5 for an example of a