4 use Getopt::Long qw< :config no_ignore_case >;
9 open my $fh, '<', $filename
10 or die "Cannot open file ($filename): $!\n";
15 or die "Cannot close file ($filename): $!\n";
23 print "Error: $msg\n\n";
29 This script creates a release checklist as a simple HTML document. It accepts
30 the following arguments:
32 --version The version you are working on. This will infer the type
33 of release you want to have
35 --html Output HTML instead of POD
41 sub _type_from_version {
44 # 5.26.0 = BLEAD-FINAL
47 # 5.27.0 = BLEAD-POINT
48 # 5.27.1 = BLEAD-POINT
49 $version =~ m{^ 5\. (\d{1,2}) \. (\d{1,2}) (?: -RC(\d) )? $}xms
50 or die "Version must be 5.x.y or 5.x.y-RC#\n";
52 my ( $major, $minor, $rc ) = ( $1, $2, $3 );
55 if ( $major % 2 != 0 ) {
57 and die "Cannot have BLEAD-POINT RC release\n";
65 return $minor == 0 ? 'BLEAD-FINAL' : 'MAINT';
69 my ( $items, $type, $cb ) = @_;
72 foreach my $item ( @{$items} ) {
73 foreach my $meta ( @{ $item->{'metadata'} || [] } ) {
74 if ( $meta =~ /skip .+ $type/xms ) {
77 elsif ( $meta =~ /skip/xms ) {
79 s/^ [^\n]* \b MUST\ SKIP\ this\ step \b [^\n]* \n\n//xms;
87 sub create_checklist {
88 my ( $type, $items ) = @_;
93 iterate_items( $items, $type, sub {
96 foreach my $meta ( @{ $item->{'metadata'} || [] } ) {
97 $meta =~ /checklist \s+ begin/xmsi
100 $meta =~ /checklist \s+ end/xmsi
108 $over_level = ( $item->{'head'} - 1 ) * 4;
110 print $prev_head < $item->{'head'} ? "=over $over_level\n\n"
111 : $prev_head > $item->{'head'} ? "=back\n\n"
114 chomp( my $name = $item->{'name'} );
115 print "=item * L<< /$name >>\n\n";
117 $prev_head = $item->{'head'};
120 print "=back\n\n" x ( $over_level / 4 );
123 my ($version, $html);
125 'version|v=s' => \$version,
127 'help|h' => sub { _help(); },
131 or _help('You must provide a version number');
135 require Pod::Simple::HTML;
136 open my $fh, '>', \$pod_output
137 or die "Can't create fh to string: $!\n";
141 my $type = _type_from_version($version);
143 chomp( my @pod_lines = @{ pod('Porting/release_managers_guide.pod') } );
145 my ( @items, $current_element, @leading_attrs );
146 my $skip_headers = qr/^=encoding/xms;
147 my $passthru_headers = qr/^= (?: over | item | back | cut )/xms;
149 foreach my $line (@pod_lines) {
150 $line =~ $skip_headers
153 if ( $line =~ /^ =head(\d) \s+ (.+) $/xms ) {
154 my ( $head_num, $head_title ) = ( $1, $2 );
158 'name' => $head_title,
161 if (@leading_attrs) {
162 $elem->{'metadata'} = [ @leading_attrs ];
166 $current_element = $elem;
172 if ( $line =~ /^ =for \s+ (.+) $ /xms ) {
173 push @leading_attrs, $1;
177 $line =~ $passthru_headers
178 or length $line == 0 # allow empty lines
179 or $line =~ /^[^=]/xms
180 or die "Cannot recognize line: '$line'\n";
182 $current_element->{'content'} .= "\n" . $line;
185 print << "_END_BEGINNING";
188 Release Manager's Guide with Checklist for $version ($type)
195 # This can also be done with a '=for introduction' in the future
196 $items[0]{'name'} =~ /^NAME/xmsi
199 $items[0]{'name'} =~ /^MAKING \s+ A \s+ CHECKLIST/xmsi
202 create_checklist( $type, \@items );
204 iterate_items( \@items, $type, sub {
206 print "=head$item->{'head'} $item->{'name'}";
207 print "$item->{'content'}\n";
211 my $simple = Pod::Simple::HTML->new;
212 $simple->output_fh(*STDOUT);
213 $simple->parse_string_document($pod_output);