#!/usr/bin/perl use strict; use warnings; my $index = ""; my $out = ""; foreach my $dir (sort {lc($a) cmp lc($b)} <*>) { open PATCHLIST, "<$dir/patchlist.txt" or next; my $patch = ""; my %is_obsolete = (); my %desc = (); my %versions = (); while () { chomp; if (s/^\t//) { die "$dir/patchlist.txt:$.: missing patch name\n" if !$patch; $desc{$patch} .= " " if defined($desc{$patch}); $desc{$patch} .= $_; } else { my $obs = 0; if (s/^!//) { $obs = 1; } $patch = $_; $is_obsolete{$patch} = $obs; my $dir_esc = $dir; $dir_esc =~ s/(\W)/\\$1/g; foreach my $verpath (<$dir/*>) { my $version = $verpath; $version =~ s,^$dir_esc/,, or die "bad: $verpath [$dir]"; push @{$versions{$patch}}, $version if -f "$verpath/$patch"; } } } map { my $A = "\1"; s/&/&/g; s//>/g; s!(?:~<(?:\{([^\}]+)\})?((?:https?|ftp)://\S+?)>~)!"".($1||$2)." (dead link".($1 ? " to $1" : "").")"!eg; s!(?:<(?:\{([^\}]+)\})?((?:https?|ftp)://\S+?)>)!"".($1||$2).""!eg; s/\\\`/$A/g; s!`((?:.|\n)+?)`!$1!g; s/$A/`/g; s/\\~/$A/g; s!~~((?:.|\n)+?)~~!$1!g; s/$A/~/g; s/\\\^/$A/g; s!\^(\d+)!$1!g; s/$A/^/g; } values(%desc); if (!%desc) { print STDERR "$dir/patchlist.txt: no patches!\n"; next; } my $dirid = $dir; $dirid =~ s/([^a-zA-Z0-9-])/sprintf("_%02X",ord($1))/eg; $index .= "
" if $index; $index .= "$dir"; $out .= "
" if $out; $out .= "

$dir

\n
\n"; foreach $patch (sort {my ($c, $d) = (lc($a), lc($b)); $c =~ s/\.(?:diff|patch)$//; $d =~ s/\.(?:diff|patch)$//; $is_obsolete{$a} <=> $is_obsolete{$b} || $c cmp $d} keys(%desc)) { my @vers = @{$versions{$patch} || []}; if (!@vers) { print STDERR "$dir/patchlist.txt: patch $patch has no versions!\n"; next; } @vers = sort { my ($a_ver, $a_extra) = ($a =~ /^\D*([0-9.]*)(.*)$/); my ($b_ver, $b_extra) = ($b =~ /^\D*([0-9.]*)(.*)$/); my @a_ver = split(/\./, $a_ver); my @b_ver = split(/\./, $b_ver); while (@a_ver && @b_ver) { my $p = shift(@a_ver); my $q = shift(@b_ver); return -1 if $p < $q; return 1 if $p > $q; } return 1 if @a_ver; return -1 if @b_ver; while ($a_extra ne "" && $b_extra ne "") { my ($p_name, $p_num, $q_name, $q_num); ($p_name, $p_num, $a_extra) = ($a_extra =~ /^[^A-Za-z0-9]*([A-Za-z]*)(.*?)(?:[-._](.*))?$/); ($q_name, $q_num, $b_extra) = ($b_extra =~ /^[^A-Za-z0-9]*([A-Za-z]*)(.*?)(?:[-._](.*))?$/); $a_extra = "" if !defined($a_extra); $b_extra = "" if !defined($b_extra); return -1 if $p_name lt $q_name; return 1 if $p_name gt $q_name; return -1 if $p_num < $q_num; return 1 if $p_num > $q_num; return -1 if $p_num lt $q_num; return 1 if $p_num gt $q_num; } return $a_extra cmp $b_extra; } @vers; my $obsolete = $is_obsolete{$patch} ? "(Obsolete) " : ""; $out .= "
$obsolete$patch (" . join(" | ", map {my $url = "$dir/$_/$patch"; $url =~ s/\+/%2B/g; "$_"} @vers) . ")
\n"; $out .= "
$desc{$patch}
\n"; } $out .= "
\n"; } my @localtime = localtime(); my $date = sprintf("%d/%d/%d", $localtime[5]+1900, $localtime[4]+1, $localtime[3]); open OUT, ">index.html" or die "index.html: $!\n"; print OUT < The Patch Pile

The Patch Pile

Except where noted otherwise in the patch description or the patch file itself, all patches linked from this page were written by me (Andrew Church) and are hereby placed in the public domain. These patches are provided as-is; use at your own risk.


Package index

$index


$out
Generated on $date
EOT