#!/usr/bin/perl

# Copyright (C) 2004 Simon Josefsson.
#
# This file is part of Autobuild.
#
# Autobuild is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# Autobuild is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Autobuild; see the file COPYING.  If not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
# MA 02111-1307, USA.

use strict;
use Getopt::Long;

# Parse command line parameters.
my $Verbose;
my ($PrintHelp, $PrintVersion);
my ($Abort, $DryRun);
GetOptions ('help|usage|h' => \$PrintHelp,
	    'version|V'    => \$PrintVersion,
	    'verbose|v'    => \$Verbose,
	    'abort|a'      => \$Abort,
	    'dry-run|n'    => \$DryRun);

# Handle --help.
if ($PrintHelp) {
    print "Usage: $0 [OPTION]... FILE...\n";
    print "\n";
    print "Create HTML index to Autobuild generated build logs.  Each file is\n";
    print "assumed to be named on the Autobuild format.  If an argument is a directory,\n";
    print "all files in that directory is parsed.\n";
    print "\n";
    print "Mandatory arguments to long options are mandatory for short options too.\n";
    print "\n";
    print "      --abort             Abort when encountering bad filenames.\n";
    print "  -n, --dry-run           Just parse, don't write file.\n";
    print "\n";
    print "Other options:\n";
    print "\n";
    print "  -v, --verbose           Explain what is being done.\n";
    print "      --help              Display this help and exit.\n";
    print "      --version           Output version information and exit.\n";
    print "\n";
    print "Report bugs to <bug-autobuild\@josefsson.org>.\n";
    exit 0;
}

# Handle --verison.
if ($PrintVersion) {
    print "abindex (autobuild) 1.5\n";
    print "\n";
    print "Copyright (C) 2004 Simon Josefsson\n";
    print "This is free software; see the source for copying conditions.  There is NO\n";
    print "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n";
    exit 0;
}

my (@Files, $arg, $file);

my (%Projects);
my (%Revisions);
my (%Modes);
my (%Hosttypes);
my (%Buildtypes);
my (%Hostnames);
my (%Timestamps);
my (%Statuss);

foreach $arg (@ARGV) {
    my (@files);

    if (-d $arg) {
	if (!opendir DIRH, $arg) {
	    warn "Cannot open directory: $arg";
	    next;
	}
	@files = grep { /^[^.]/ && -f "$arg/$_" } readdir(DIRH);
	closedir DIRH;
    } elsif (-f $arg) {
	push @files, $arg;
    } else {
	warn "Skipping unknown file: $arg";
	next;
    }

    foreach $file (@files) {
	if (!$file =~ m:autobuild(,.*,)log.[a-z]+:) {
	    warn "Skipping file (unrecognized file name): `$file'";
	    next;
	}

	my ($Project);
	my ($Revision);
	my ($Mode);
	my ($Hosttype);
	my ($Buildtype);
	my ($Hostname);
	my ($Timestamp);
	my ($Status);

	$Project = $1 if $file =~ m:,project=([^,]+),:;
	$Revision = $1 if $file =~ m:,revision=([^,]+),:;
	$Mode = $1 if $file =~ m:,mode=([^,]+),:;
	$Hosttype = $1 if $file =~ m:,hosttype=([^,]+),:;
	$Buildtype = $1 if $file =~ m:,buildtype=([^,]+),:;
	$Hostname = $1 if $file =~ m:,hostname=([^,]+),:;
	$Timestamp = $1 if $file =~ m:,timestamp=([^,]+),:;
	$Status = $1 if $file =~ m:,status=([^,]+),:;

	if ($Verbose) {
	    print STDERR "$file:\n";
	    print STDERR " Project: $Project\n";
	    print STDERR " Revision: $Revision\n";
	    print STDERR " Mode: $Mode\n";
	    print STDERR " Hosttype: $Hosttype\n";
	    print STDERR " Buildtype: $Buildtype\n";
	    print STDERR " Hostname: $Hostname\n";
	    print STDERR " Timestamp: $Timestamp\n";
	    print STDERR " Status: $Status\n";
	}

	if (!$Project || $Revision eq "" || !$Mode || !$Hosttype ||
	    !$Buildtype || !$Hostname || !$Timestamp || !$Status) {
	    warn "Skipping file (missing values): `$file'";
	    die if $Abort;
	    next;
	}

	push @Files, $file;

	$Projects{$Project} = 0;
	${$Revisions{$Project}}{$Revision} = 0;
	${$Hosttypes{$Project}}{$Hosttype} = 0;
	${$Hostnames{$Project}}{$Hostname} = 0;
    }
}

my ($project, $revision, $hosttype, $hostname);

print "<html>\n";
print "<head>\n";
print "<title>Index to Autobuild logs</title>\n";
print "</head>\n";
print "\n";
print "<body>\n";
print "<h1>Index to Autobuild logs</h1>\n";
print "\n";
print "<p>This page was created on " . (scalar localtime) . " using <a href=\"http://josefsson.org/autobuild/\">Autobuild</a> written by Simon Josefsson.\n";
print "\n";

if (%Projects > 1) {
    print "<hr>\n";
    print "<h2>Quick links to each project</h2>\n";
    print "\n";
    print "<p><ul>\n";
    foreach $project (sort keys %Projects) {
	print "<li><a href=\"#$project\">$project</a>\n";
    }
    print "</ul>\n";
}

foreach $project (sort keys %Projects) {
    print "<hr>\n";
    print "<h2><a name=\"$project\">Project '$project'</a></h2>\n";
    print "\n";
    print "<p>Revisions (" . keys(%{$Revisions{$project}}) . "): ";
    foreach $revision (reverse sort { if ($a eq $b) { return 0; } else { my $i = 0; do { my $j = substr ($a, $i, 1); my $k = substr ($b, $i, 1); if ($j != $k) { $j = substr ($a, $i); $k = substr ($b, $i); return $j <=> $k; } $i++; } while ($i < length($a)); } } keys %{$Revisions{$project}}) {
	print "<a href=\"#$project-$revision\">$revision</a>, ";
    }
    print "\n";
    print "<p>Hosttypes (" . keys(%{$Hosttypes{$project}}) . "): ";
    foreach $hosttype (sort keys %{$Hosttypes{$project}}) {
	print "<a href=\"#$project-$hosttype\">$hosttype</a>, \n";
    }
    print "\n";
    print "<p>Build hosts (" . keys(%{$Hostnames{$project}}) . "): ";
    foreach $hostname (sort keys %{$Hostnames{$project}}) {
	print "<a href=\"#$project-$hostname\">$hostname</a>, \n";
    }
    print "\n";

    foreach $revision (reverse sort { if ($a eq $b) { return 0; } else { my $i = 0; do { my $j = substr ($a, $i, 1); my $k = substr ($b, $i, 1); if ($j != $k) { $j = substr ($a, $i); $k = substr ($b, $i); return $j <=> $k; } $i++; } while ($i < length($a)); } } keys %{$Revisions{$project}}) {
	print "<hr>\n";
	print "<a name=\"$project-$revision\"><h3>Summary for $project $revision</h3></a>\n";
	print "\n";
	print "<table border=1>\n";
	print "<tr>\n";
	print "<td>System</td>\n";
	print "<td>Cross compile?</td>\n";
	print "<td>Build host</td>\n";
	print "<td>Build date</td>\n";
	print "<td>Results</td>\n";
	print "<td>Log</td>\n";
	print "</tr>\n";
	print "\n";
	foreach $file (@Files) {
	    next unless $file =~ m:,project=$project,:;
	    next unless $file =~ m:,revision=$revision,:;


	    my ($Project);
	    my ($Revision);
	    my ($Mode);
	    my ($Hosttype);
	    my ($Buildtype);
	    my ($Hostname);
	    my ($Timestamp);
	    my ($Status);

	    $Mode = $1 if $file =~ m:,mode=([^,]+),:;
	    $Hosttype = $1 if $file =~ m:,hosttype=([^,]+),:;
	    $Buildtype = $1 if $file =~ m:,buildtype=([^,]+),:;
	    $Hostname = $1 if $file =~ m:,hostname=([^,]+),:;
	    $Timestamp = $1 if $file =~ m:,timestamp=([^,]+),:;
	    $Status = $1 if $file =~ m:,status=([^,]+),:;

	    print "<tr>\n";
	    print "<td>$Hosttype</td>\n";
	    if ($Hosttype eq $Buildtype) {
		print "<td>no</td>\n";
	    } else {
		print "<td>yes, from $Buildtype</td>\n";
	    }
	    print "<td>$Hostname</td>\n";
	    print "<td>$Timestamp</td>\n";
	    if ($Status eq "ok") {
		print "<td><font color=green>Success</font></td>\n";
	    } elsif ($Status eq "almost") {
		print "<td><font color=orange>Almost</font></td>\n";
	    } else {
		print "<td><font color=red>Failure</font></td>\n";
	    }
	    print "<td><a href=\"$file\">log</a></td>\n";
	    print "</tr>\n";
	    print "\n";
	}
	print "</table>\n";
	print "\n";
    }
    print "\n";

    foreach $hosttype (sort keys %{$Hosttypes{$project}}) {
	print "<hr>\n";
	print "<a name=\"$project-$hosttype\"><h3>Summary for $project on $hosttype</h3></a>\n";
	print "\n";
	print "<table border=1>\n";
	print "<tr>\n";
	print "<td>Revision</td>\n";
	print "<td>Build host type</td>\n";
	print "<td>Build host</td>\n";
	print "<td>Build date</td>\n";
	print "<td>Results</td>\n";
	print "<td>Log</td>\n";
	print "</tr>\n";
	print "\n";
	foreach $file (@Files) {
	    next unless $file =~ m:,project=$project,:;
	    next unless $file =~ m:,hosttype=$hosttype,:;

	    my ($Project);
	    my ($Revision);
	    my ($Mode);
	    my ($Hosttype);
	    my ($Buildtype);
	    my ($Hostname);
	    my ($Timestamp);
	    my ($Status);

	    $Revision = $1 if $file =~ m:,revision=([^,]+),:;
	    $Mode = $1 if $file =~ m:,mode=([^,]+),:;
	    $Buildtype = $1 if $file =~ m:,buildtype=([^,]+),:;
	    $Hostname = $1 if $file =~ m:,hostname=([^,]+),:;
	    $Timestamp = $1 if $file =~ m:,timestamp=([^,]+),:;
	    $Status = $1 if $file =~ m:,status=([^,]+),:;

	    print "<tr>\n";
	    print "<td>$Revision</td>\n";
	    print "<td>$Buildtype</td>\n";
	    print "<td>$Hostname</td>\n";
	    print "<td>$Timestamp</td>\n";
	    if ($Status eq "ok") {
		print "<td><font color=green>Success</font></td>\n";
	    } elsif ($Status eq "almost") {
		print "<td><font color=orange>Almost</font></td>\n";
	    } else {
		print "<td><font color=red>Failure</font></td>\n";
	    }
	    print "<td><a href=\"$file\">log</a></td>\n";
	    print "</tr>\n";
	    print "\n";
	}
	print "</table>\n";
	print "\n";
    }
    print "\n";

    foreach $hostname (sort keys %{$Hostnames{$project}}) {
	print "<hr>\n";
	print "<a name=\"$project-$hostname\"><h3>Summary for $project built on $hostname</h3></a>\n";
	print "\n";
	print "<table border=1>\n";
	print "<tr>\n";
	print "<td>Version</td>\n";
	print "<td>System</td>\n";
	print "<td>Cross compile?</td>\n";
	print "<td>Build date</td>\n";
	print "<td>Results</td>\n";
	print "<td>Log</td>\n";
	print "</tr>\n";
	print "\n";
	foreach $file (@Files) {
	    next unless $file =~ m:,project=$project,:;
	    next unless $file =~ m:,hostname=$hostname,:;

	    my ($Project);
	    my ($Revision);
	    my ($Mode);
	    my ($Hosttype);
	    my ($Buildtype);
	    my ($Hostname);
	    my ($Timestamp);
	    my ($Status);

	    $Revision = $1 if $file =~ m:,revision=([^,]+),:;
	    $Mode = $1 if $file =~ m:,mode=([^,]+),:;
	    $Hosttype = $1 if $file =~ m:,hosttype=([^,]+),:;
	    $Buildtype = $1 if $file =~ m:,buildtype=([^,]+),:;
	    $Timestamp = $1 if $file =~ m:,timestamp=([^,]+),:;
	    $Status = $1 if $file =~ m:,status=([^,]+),:;

	    print "<tr>\n";
	    print "<td>$Revision</td>\n";
	    print "<td>$Hosttype</td>\n";
	    if ($Hosttype eq $Buildtype) {
		print "<td>no</td>\n";
	    } else {
		print "<td>yes, from $Buildtype</td>\n";
	    }
	    print "<td>$Timestamp</td>\n";
	    if ($Status eq "ok") {
		print "<td><font color=green>Success</font></td>\n";
	    } elsif ($Status eq "almost") {
		print "<td><font color=orange>Almost</font></td>\n";
	    } else {
		print "<td><font color=red>Failure</font></td>\n";
	    }
	    print "<td><a href=\"$file\">log</a></td>\n";
	    print "</tr>\n";
	    print "\n";
	}
	print "</table>\n";
	print "\n";
    }
    print "\n";

}

print "\n";
print "<hr>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<br>\n";
print "<hr>\n";
print "\n";
print "</body>\n";
print "</html>\n";
