3 # Produce a status page for all current and pending OCaml packages.
4 # By Richard W.M. Jones <rjones@redhat.com>
5 # $Id: ocaml-status.pl,v 1.7 2008/12/05 17:44:39 rjones Exp $
8 # . All OCaml-related packages have to be checked out
9 # under $HOME/d/fedora.
10 # . All pending packages have to be checked out under
11 # $HOME/d/redhat/ocaml.
13 # The output is normally placed here:
14 # http://cocan.org/getting_started_with_ocaml_on_red_hat_and_fedora
16 # Checks that the package build-requires OCaml in order to know if
17 # it's an OCaml-related package.
19 # Only recognizes the Fedora/EPEL branches listed below and ignores
20 # anything else. There are no OCaml packages in RHEL at this time.
24 use POSIX qw(strftime);
25 use CGI qw/:standard/;
27 my $fedora = $ENV{HOME} . "/d/fedora";
28 my $pending = $ENV{HOME} . "/d/redhat/ocaml";
32 url => "http://fedoraproject.org/wiki/EPEL",
33 title => "Packages for Red Hat Enterprise Linux 4",
39 url => "http://fedoraproject.org/wiki/EPEL",
40 title => "Packages for Red Hat Enterprise Linux 5",
46 url => "http://fedoraproject.org/",
52 url => "http://fedoraproject.org/",
58 url => "http://fedoraproject.org/",
64 url => "http://fedoraproject.org/wiki/Releases/Rawhide",
65 title => "Fedora 11 in development a.k.a. Rawhide",
71 url => "https://bugzilla.redhat.com/buglist.cgi?version=rawhide&component=Package+Review&target_milestone=&bug_status=NEW&bug_status=ASSIGNED&bug_status=NEEDINFO&bug_status=MODIFIED&short_desc_type=allwordssubstr&short_desc=ocaml&long_desc_type=allwordssubstr&long_desc=",
77 # List of packages to ignore in pending.
78 my %ignore_pending = (
83 # List of packages to ignore in Fedora.
97 # Count of packages by branch.
100 # Collect the package names & status from the specfiles.
104 # Fedora and EPEL packages.
105 foreach $specfile (<$fedora/*/*/*.spec>) {
106 if ($specfile =~ m{/([^/]+)/([^/]+)\.spec$}) {
107 my $specfile_name = $2;
109 if (exists $branches{$branch} &&
110 !exists $ignore_fedora{$specfile_name} &&
111 $specfile_name !~ /^mingw32/) {
112 collect_specfile ($specfile, $branch);
117 # Pending packages in review.
118 foreach $specfile (<$pending/*/*.spec>) {
119 collect_specfile ($specfile, "pending");
123 sub collect_specfile {
124 my $specfile = shift;
127 # Read the specfile and parse the bits we understand.
128 my ($name, $version, $summary, $description, $url, $is_ocaml,
130 @rpmdefines = (["nil", ""]);
132 open SPEC, "$specfile" or die "$specfile: $!";
134 if (/^Name:\s*(\S+)/) {
136 $name = rpmsubst ($name, 1, @rpmdefines) if $name =~ /%{/;
137 $is_ocaml = 1 if $name =~ /ocaml/;
138 } elsif (/^Version:\s*(\S+)/) {
140 $version = rpmsubst ($version, 1, @rpmdefines) if $version =~ /%{/;
141 } elsif (!$url && /^URL:\s*(\S+)/) {
143 $url = rpmsubst ($url, 1, @rpmdefines) if $url =~ /%{/;
144 } elsif (!$summary && /^Summary:\s*(.*)/) {
146 $is_ocaml = 1 if $summary =~ /ocaml/i;
147 } elsif (/^(Build)?Requires:.*ocaml/) {
149 } elsif (!$description && /^%description/) {
155 $description = rpmsubst ($description, 1, @rpmdefines)
156 if $description =~ /%{/;
157 $is_ocaml = 1 if $description =~ /ocaml/i;
160 # Handle simple RPM defines.
161 elsif (/^%define\s+([A-Za-z_]+)\s+(.*)/) {
164 if (only_simple_substs ($val)) {
165 $val = rpmsubst ($val, 0, @rpmdefines);
166 push @rpmdefines, [ $name, $val ];
171 # Check it's an OCaml package. If name/summary/description contains
172 # 'ocaml' or it Requires/BuildRequires some ocaml package then we
173 # assume it's OCaml-related.
175 warn "warning: $name ($branch) ignored, not an OCaml package\n";
179 # Ignore certain packages appearing in pending branch.
180 if ($branch eq "pending" && exists $ignore_pending{$name}) {
184 #print "$name $version $url\n";
186 # If the package is in "pending" then there shouldn't be a
187 # Fedora package also.
188 if ($branch eq "pending" && exists $packages{$name}) {
189 die "error: pending $name is also in Fedora repo\n"
193 $packages{$name} = {} unless exists $packages{$name};
194 if (exists $packages{$name}{$branch}) {
195 die "$name ($branch) package already seen\n";
197 $packages{$name}{$branch} = {
203 description => $description,
207 sub only_simple_substs {
211 s/%\([A-Za-z_]+\)//g;
215 # Simple RPM '%define' substitutions.
222 my $var = $pair->[0];
223 my $val = $pair->[1];
229 if ($fail && (m/%{/ || m/%\(/)) {
230 die "rpmsubst: string contains undefined substitutions: $_\n";
236 sub branchsortorder {
237 $branches{$a}{sortorder} <=> $branches{$b}{sortorder}
247 print "Status of packages in Fedora, EPEL and RHEL, last updated on ";
248 print strftime("%Y-%m-%d",gmtime);
251 print "<table class=\"top_table fedoratbl\">\n";
252 print "<tr><th>Name</th>\n";
253 foreach (sort branchsortorder (keys %branches)) {
254 my $name = $branches{$_}{name};
255 my $url = $branches{$_}{url};
256 my $class = $branches{$_}{class};
258 print "<th class=\"$class\">";
259 if (exists $branches{$_}{title}) {
260 my $title = escapeHTML ($branches{$_}{title});
261 print "<a title=\"$title\" href=\"$url\">",
262 nbsp(escapeHTML($name)),
265 print "<a href=\"$url\">",
266 nbsp(escapeHTML($name)),
273 # Count the packages in each branch.
275 foreach (keys %branches) {
283 # Get the URL, summary and description from devel
284 # or pending (if possible).
285 my ($url, $summary, $description);
286 if (exists $packages{$name}{devel}) {
287 $url = $packages{$name}{devel}{url};
288 $summary = $packages{$name}{devel}{summary};
289 $description = $packages{$name}{devel}{description};
290 } elsif (exists $packages{$name}{pending}) {
291 $url = $packages{$name}{pending}{url};
292 $summary = $packages{$name}{pending}{summary};
293 $description = $packages{$name}{pending}{description};
298 if (defined $summary && defined $description) {
300 escapeHTML($description),
304 escapeHTML($summary),
307 print "<a href=\"$url\">", escapeHTML($name), "</a>";
310 print (escapeHTML($name));
315 foreach $branch (sort branchsortorder (keys %branches)) {
316 my $brclass = $branches{$branch}{class};
318 if (exists $packages{$name}{$branch}) {
321 my %r = %{$packages{$name}{$branch}};
323 my $class = "released";
324 $class = "pending" if $branch eq "pending";
325 $class = "devel" if $branch eq "devel";
326 $class = "ocaml" if $name eq "ocaml";
328 print "<td class=\"$brclass $class\">$r{version}</td>\n";
330 # No package in this branch.
331 print "<td class=\"$brclass\"> </td>\n"
339 # Summary of packages in each branch.
340 print "<tr><td>Totals</td>";
342 foreach $branch (sort branchsortorder (keys %branches)) {
343 print "<td>$count{$branch}</td>";
351 # Define a standard package name order.
353 # "ocaml-*" packages always sort first.
354 return -1 if $a =~ /^ocaml/ && $b !~ /^ocaml/;
355 return 1 if $a !~ /^ocaml/ && $b =~ /^ocaml/;
357 return (lc($a) cmp lc($b))
361 # Collect all the specfiles, into %packages hash.
364 # Get the package names.
365 my @names = sort pkgnameorder (keys %packages);
367 # Generate the output.