#!/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, $Html);
my ($OutDir) = ".";
my ($Project, $Revision, $Mode, $Hostname, $Hosttype,
    $Buildtype, $Timestamp, $Status);
GetOptions ('help|usage|h' => \$PrintHelp,
	    'version|V'    => \$PrintVersion,
	    'verbose|v'    => \$Verbose,
	    'html'         => \$Html,
	    'abort|a'      => \$Abort,
	    'dry-run|n'    => \$DryRun,
	    'outdir|o=s'   => \$OutDir,
	    'p|project=s'  => \$Project,
	    'revision=s'   => \$Revision,
	    'mode=s'       => \$Mode,
	    'Hosttype=s'   => \$Hosttype,
	    'Buildtype=s'  => \$Buildtype,
	    'Hostname=s'   => \$Hostname,
	    'Timestamp=s'  => \$Timestamp,
	    'Status=s'     => \$Status);

# Handle --help.
if ($PrintHelp) {
    print "Usage: $0 [OPTION]... [FILE]...\n";
    print "\n";
    print "Read and parse build logs to find project name, revision, build mode,\n";
    print "build host type, build type (for cross compile builds), hostname, and\n";
    print "timestamp, then produce a file (named depending on the extracted\n";
    print "parameters) with the build log.\n";
    print "\n";
    print "Mandatory arguments to long options are mandatory for short options too.\n";
    print "\n";
    print "      --abort             Abort if guessing values fail.\n";
    print "                          With the exceptions of build mode\n";
    print "                          (falls back to 'default') and\n";
    print "                          the status (falls back to 'fail').\n";
    print "  -n, --dry-run           Just parse, don't write file.\n";
    print "      --html              Create HTML output instead of text.\n";
    print "                          Need Emacs and htmlize.el.\n";
    print "  -o, --outdir=DIR        Create files in specified directory.\n";
    print "\n";
    print "For use when autobuild fail to guess the values properly:\n";
    print "  -p, --project=STRING    Specify project name.\n";
    print "      --revision=STRING   Specify project revision.\n";
    print "      --mode=STRING       Specify build mode (typically 'default').\n";
    print "      --hosttype=STRING   Specify host type (e.g., i686-pc-linux-gnu).\n";
    print "      --buildtype=STRING  Specify build type (e.g., m68k-uclinux-elf).\n";
    print "                          Different from hosttype for cross compiles.\n";
    print "      --hostname=STRING   Specify name of host log was created on.\n";
    print "      --timestamp=STRING  Specify when build was made.\n";
    print "                          Any date format will work, but\n";
    print "                          'YYYY-MM-DDTHH:MM:SS' is recommended.\n";
    print "      --status=STRING     Outcome of build.\n";
    print "                          Any string will work, but \"ok\" and\n";
    print "                          \"fail\" are recommended for the two\n";
    print "                          basic outcomes.\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 "autobuild (autobuild) 1.1\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;
}

# Declarations.
my ($tmpfile) = "$OutDir/.autobuild.$$";

# Always clean up in case of failure.
sub END { unlink $tmpfile; }

# Core.
open OUT, "> $tmpfile" or die "Can't open temporary file: $!";

while (<>) {
    if (m,\r\n$,) {
	chop; chop;
	$_ = $_ . "\n";
    }

    # These override everything.
    $Project = $1 if m,autobuild project... (.*),;
    $Revision = $1 if m,autobuild revision... (.*),;
    $Mode = $1 if m,autobuild mode... (.*),;
    $Hostname = $1 if m,autobuild hostname... (.*),;
    $Hosttype = $1 if m,autobuild hosttype... (.*),;
    $Buildtype = $1 if m,autobuild buildtype... (.*),;
    $Timestamp = $1 if m,autobuild timestamp... (.*),;

    # GNU Autoconf host/build output.
    $Hosttype = $1 if !$Hosttype && m,checking host system type... ([a-z0-9_.-]+),;
    $Buildtype = $1 if !$Buildtype && m,checking build system type... ([a-z0-9_.-]+),;

    # Automake self test output.
    $Status = "ok" if !$Status && m,All [0-9]+ tests passed,;
    $Status = "almost" if !$Status && m,[0-9]+ of [0-9]+ tests failed,;

    # Works for GNU make.
    $Project = $1 if !$Project && m,make\[[0-9]+\]: Entering directory `.*/([a-z]+)-[0-9.]+/.*',;
    $Revision = $1 if !$Revision && m,make\[[0-9]+\]: Entering directory `.*/[a-z]+-([0-9.]+)/.*',;

    # Telnet string.
    $Hostname = $1 if !$Hostname && m,Trying (.*)\.\.\.,;
    $Hostname = $1 if !$Hostname && m,Connected to (.*)\.,;

    # SSH string.
    $Hostname = $1 if !$Hostname && m,Connection to (.*) closed.,;

    # If output mention a tar.gz archive.
    $Project = $1 if !$Project && m,/([a-z]+)-[0-9.]+.tar.gz,;
    $Revision = $1 if !$Revision && m,/[a-z]+-([0-9.]+).tar.gz,;

    print OUT $_;

    if (eof) {
	if (!$Abort) {
	    $Project = "unknown" if !$Project;
	    $Revision = "0" if !$Revision;
	    $Hostname = "unknown" if !$Hostname;
	    $Hosttype = "unknown" if !$Hosttype;
	    $Buildtype = "unknown" if !$Buildtype;
	    $Timestamp = "unknown" if !$Timestamp;
	}
	$Mode = "default" if !$Mode;
	$Status = "fail" if !$Status;

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

	close OUT;

	die "Could not guess all required values" .
	    ($Verbose ? "" : " (use -v to print values)")."\n"
	    if $Abort && (!$Project || !$Revision || !$Hostname || !$Hosttype
			  || !$Buildtype || !$Timestamp || !$Status);

	if (!$DryRun) {
	    my ($outbase, $outfile) = "$OutDir/autobuild,project=$Project,revision=$Revision,mode=$Mode,hosttype=$Hosttype,buildtype=$Buildtype,hostname=$Hostname,timestamp=$Timestamp,status=$Status,log";
	    if ($Html) {
		$outfile = $outbase . ".html";
		system ("emacs --eval '(let ((htmlize-before-hook (lambda () (compilation-mode) (font-lock-fontify-buffer)))) (htmlize-file \"$tmpfile\" \"$outfile\") (kill-emacs))'");
	    } else {
		$outfile = $outbase . ".txt";
		rename $tmpfile, $outfile;
	    }
	    print "$outfile\n";
	}

	open OUT, "> $tmpfile" or die "Can't open temporary file: $!";
	undef $Project;
	undef $Revision;
	undef $Mode;
	undef $Hostname;
	undef $Hosttype;
	undef $Buildtype;
	undef $Timestamp;
	undef $Status;
    }
}
