#!/usr/bin/perl
#
# Lintian reporting harness -- Create and maintain Lintian reports automatically
#
# Copyright (C) 1998 by Christian Schwarz and Richard Braakman
#
# This program is free software.  It is distributed under the terms of
# the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any
# later version.
#
# This program 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 this program.  If not, you can find it on the World Wide
# Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free
# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
# MA 02111-1307, USA.

# read configuration
require './config';

# import perl libraries
require "$LINTIAN_ROOT/lib/read_pkglists.pl";
require "$LINTIAN_ROOT/lib/util.pl";

# turn file buffering off:
$| = 1;

# rotate log files
system("savelog $log_file $changes_file $list_file $html_reports_log >/dev/null") == 0
    or Die("cannot rotate log files");

# create new log file
open(LOG,">$log_file")
    or Die("cannot open log file $log_file for writing: $!");

# wait until dinstall has finished its work...
my $count;
while (-f "$ARCHIVE/Archive_Maintenance_In_Progress") {
    # take a nap for 30 minuts, but don't sleep longer than 12 hours... ;-)
    if ($count++ >= 24) {
	Log("Dinstall doesn't seem to get ready today, so I'm giving up.");
	exit 0;
    }

    # take a nap for 30 minutes...
    Log("Sleeping for 30 minutes...");
    sleep(1800);
}
Log("Dinstall is ready now.");

# export Lintian's configuration
$ENV{'LINTIAN_ROOT'} = $LINTIAN_ROOT;
$ENV{'LINTIAN_CFG'} = $LINTIAN_CFG;
$ENV{'LINTIAN_LAB'} = $LINTIAN_LAB;
$ENV{'LINTIAN_DIST'} = $LINTIAN_DIST;
$ENV{'LINTIAN_UNPACK_LEVEL'} = $LINTIAN_UNPACK_LEVEL;
$ENV{'LINTIAN_ARCH'} = $LINTIAN_ARCH;

# make lintian update its packages files and save output
run("$lintian_cmd -v --setup-lab >$changes_file")
    or Die("cannot run lintian --setup-lab");
Log("");

# check everything or only changes?
if (-f $lintian_log) {
    # only changes

    # read binary packages files
    $pkgfile = "$LINTIAN_LAB/info/binary-packages";
    (-f $pkgfile) or Die("cannot find list of binary packages $pkgfile");
    read_bin_list($pkgfile);
  
    # read source packages files
    $pkgfile = "$LINTIAN_LAB/info/source-packages";
    (-f $pkgfile) or Die("cannot find list of source packages $pkgfile");
    read_src_list($pkgfile);

    # process changes file and create list of packages to process
    Log("Reading changes file...");
    open(IN,$changes_file)
	or Die("cannot open changes file $changes_file for reading: $!");
    open(OUT,">$list_file")
	or Die("cannot open list file $list_file for writing: $!");
    while (<IN>) {
	chop;
    
	if (/^N: Listed (changed|new) (binary|source) package (\S+) (\S+)/o) {
	    my ($type,$binsrc,$pkg,$ver) = ($1,$2,$3,$4);
      
	    Log("$type $binsrc package $pkg $ver");
      
	    if ($binsrc eq 'binary') {
		my $data = $binary_info{$pkg};
		$data or Die("cannot find binary package $pkg in binary-packages file");
		print OUT "b $binary_info{$pkg}->{'package'} $binary_info{$pkg}->{'version'} $LINTIAN_DIST/$binary_info{$pkg}->{'file'}\n";
		$skip_binary{$pkg} = 1;
	    } else {
		my $data = $source_info{$pkg};
		$data or Die("cannot find source package $pkg in source-packages file");
		print OUT "s $source_info{$pkg}->{'source'} $source_info{$pkg}->{'version'} $LINTIAN_DIST/$source_info{$pkg}->{'file'}\n";
		$skip_source{$pkg} = 1;
	    }
	} elsif (/^N: Removed (binary|source) package (\S+)/o) {
	    my ($binsrc,$pkg) = ($1,$2);

	    Log("removed $binsrc package $pkg");
	    run("rm -rf -- \"$LINTIAN_LAB/$binsrc/$pkg\"")
		or Log("could not remove $binsrc package $pkg");
	    if ($binsrc eq 'binary') {
		$skip_binary{$pkg} = 1;
	    } else {
		$skip_source{$pkg} = 1;
	    }
	} elsif (/^N/o) {
	    # ignore other notes
	} else {
	    Log("skipping changes line: $_");
	}
    }
    close(OUT);
    close(IN);
    Log("");

    # update lintian.log
    Log("Updating lintian.log...");
    rename $lintian_log, $old_lintian_log;
    open(IN,$old_lintian_log)
	or Die("cannot open old lintian.log $old_lintian_log for reading: $!");
    open(OUT,">$lintian_log")
	or Die("cannot open lintian.log $lintian_log for writing: $!");
    $copy_mode = 1;
    while (<IN>) {
	if (/^N: Processing (binary|source) package (\S+)/o) {
	    my ($type,$pkg) = ($1,$2);

	    if ($type eq 'binary') {
		$copy_mode = not exists $skip_binary{$pkg};
	    } else {
		$copy_mode = not exists $skip_source{$pkg};
	    }
	}
    
	if ($copy_mode) {
	    print OUT $_;
	}
    }
    print OUT "N: ---end-of-old-lintian-log-file---\n";
    close(OUT);
    close(IN);
    Log("");

    # run Lintian over the newly introduced or changed packages
    Log("Running Lintian over newly introduced and changed packages...");
    $cmd = "$lintian_cmd -I -v -p $list_file -U changelog-file >>$lintian_log 2>&1";
    Log("Executing $cmd");
    $res = (system($cmd) >> 8);
    (($res == 0) or ($res == 1))
	or Die("error executing lintian");
    Log("");
} else {
    # check all packages
    Log("Running Lintian over all packages...");
    $cmd = "$lintian_cmd -I -v -a -U changelog-file >$lintian_log 2>&1";
    Log("Executing $cmd");
    $res = (system($cmd) >> 8);
    (($res == 0) or ($res == 1))
	or Die("error executing lintian");
    Log("");
}

# create html reports
Log("Creating HTML reports...");
run("$html_reports_cmd $lintian_log >$html_reports_log 2>&1")
    or Die("error running $html_reports_cmd");
Log("");

Log("Creating depcheck pages...");
run("$LINTIAN_ROOT/depcheck/deppages.pl >>$html_reports_log 2>&1")
    or Die("error running deppages.pl");
Log("");

# install new html directory
Log("Installing HTML reports...");
rename($HTML_DIR,"$HTML_DIR.old")
    or Die("error renaming $HTML_DIR into $HTML_DIR.old");
rename($HTML_TMP_DIR,$HTML_DIR)
    or Die("error renaming $HTML_TMP_DIR into $HTML_DIR");
run("rm -rf -- \"$HTML_DIR.old\"")
    or Die("error removing $HTML_DIR.old");
Log("");

# ready!!! :-)
Log("Success!!! Lintian is really great! ;-)");
exit 0;

# -------------------------------

sub Log {
    print LOG $_[0],"\n";
}

sub run {
    Log("Executing $_[0]");
    return (system($_[0]) == 0);
}

sub Die {
    Log("fatal error: $_[0]");
    exit 1;
}
