#!/usr/bin/perl -w

use strict;
use warnings;
use File::Basename;
use File::Temp qw(tempfile);

use Test::Repocop::ExternalTest;
my $_local_debug=0;

my $report_undefined_symbols=0;
my $report_build_environment=0;
my $report_rpmsodiff=0;
my $report_unpackaged_files=1;
my $report_packaged_both=1;
my $report_needs_epoch=1;
my $report_non_strict_dependency=1;

my $unpackaged_files_catchphrase=qr'^warning: Installed \(but unpackaged\) file\(s\) found:';


my ($log,$arch)=@ARGV;
my $pkgid=basename($log);
$pkgid=~s/-\d+:/-/;
my $quoted_pkgid=qr"\Q$pkgid";

$arch='testarch' if not $arch and $_local_debug;
die "usage: $0 /path/to/log/file <build arch>" if not $arch;

open(my $fh, '<', $log) or die "can't open $log: $!";
$_=<$fh>;
my @build_environment;
while ($_ and not /Installing $quoted_pkgid\.src.rpm$/) {
    if (/<\d+>\w+ \d+ \d\d:\d\d:\d\d rpmi: (\S+) installed/) {
	push @build_environment, $1;
    }
    $_=<$fh>;
    while (s/^(?:warn|echo)//){};
}
/Installing $quoted_pkgid/ || die "Invalid log ($arch) - not found: Installing $pkgid\n";

### ECHO COLLECT BR: ENVIRONMENT
&report_test('collect',$pkgid,'beehive-log-build-environment-'.$arch, join("\n",@build_environment)."\n") if $report_build_environment and @build_environment;

my @undefined_symbols;
my @unpackaged_files;
my @packaged_both;
my @needs_epoch;
my @non_strict_dependency;

sub warnings_handler {
    local $_=$_[0];
    # '^warning: [^ ]* dependency on [^ ]* needs Epoch'
    # warning: brazil-javadoc: dependency on brazil needs Epoch
    if (m!^warning: ([^ ]* dependency on [^ ]* needs Epoch)\s*$!) {
	push @needs_epoch, "$1\n";
    } elsif (m!^warning: ([^\s:]+): non-strict dependency on (\S+)!) {
	push @non_strict_dependency, [$1, $2];
    ## ^verify-elf: WARNING: ...so: undefined symbol: ...
    } elsif (/^verify-elf: WARNING: \.?([^\s:]+): undefined symbol: (\S+)/) {
	push @undefined_symbols, "$1: $2\n";
    }
}

while ($_ and not m/^Executing\(\%install\):/ and not m/^Processing files:/) { $_=<$fh> }
if (m/^Executing\(\%install\):/) {

    while ($_ and not m!^\+ /usr/lib/rpm/brp-alt! and not m!$unpackaged_files_catchphrase! and not m!^Wrote:!) { $_=<$fh>;s/^.*\000//; }
}

    # might not exist: see maven-1 log
    #m!^\+ /usr/lib/rpm/brp-alt! || die "Invalid log - not found: /usr/lib/rpm/brp-alt\n";

#Cleaning files in /usr/src/tmp/FlightGear-data-buildroot (skip)
#Compressing files in /usr/src/tmp/FlightGear-data-buildroot (none)
#brp-verify_elf: ELF verification disabled

    # can be missing, as above
    #while ($_ and not m!^Verifying and fixing files!) { $_=<$fh> }
    #m!^Verifying and fixing files! || die "Invalid log - not found: Verifying and fixing files\n";


while ($_ and not m!$unpackaged_files_catchphrase! and not m!^Wrote:!) { 
    $_=<$fh>;
    &warnings_handler($_);
}
if (m!$unpackaged_files_catchphrase!) {
    while ($_ and not m!^Wrote:!) { 
	### ^warning: Installed (but unpackaged) file(s) found:
	if (/^warning: Installed \(but unpackaged\) file\(s\) found:/) {
	    $_=<$fh>;
	    while ($_ and s!^    /!/!) {
		push @unpackaged_files, $_;
		$_=<$fh>;
	    }
	}

        ### warning: file ... is packaged into both ...
#warning: file /etc/slurm/slurm.key is packaged into both slurm-master and slurm-slave
	if (m!^warning: file (.+) is packaged into both \S+ and \S+\s*$!) {
	    my $multifile=$1;
	    push @packaged_both, $_ unless $multifile=~m!(?:license|eclipse/about_files|readme|notice|release-note)!i;
	}
    }
    #while ($_ and not m!^Wrote:!) { $_=<$fh> }
}
m!^Wrote:! || die "Invalid log - not found: Wrote:\n";

while ($_ and not m!^--- !) { $_=<$fh> }
# noarch/no .so logs does not have a sodiff
if ($_ and m!^--- !) {
    my @rpmsodiff;
    my $is_nonempty_diff=0;
    while ($_) { 
	$is_nonempty_diff=1 unless m!^\+\+\+ ! or m!^--- ! or m!^\@\@! or m!^ ! 
	    or m![-+]Requires: rpmlib\(! or m![-+]Requires: libc.so.6\GLIBC_!;
	push @rpmsodiff, $_;
	$_=<$fh>;
    }
    ### COLLECT RPM DIFF
    &report_test('experimental',$pkgid,'beehive-log-rpmsodiff-'.$arch,
		     'rpmsodiff is not empty. Looks like you should rebuild your package'."\n".
		     join('',@rpmsodiff)
	    ) if $is_nonempty_diff and $report_rpmsodiff;

}
close($fh);

&report_test('info',$pkgid,'beehive-log-unpackaged-files-found-'.$arch,
	     'warning: Installed (but unpackaged) file(s) found:'."\n".
	     join('',@unpackaged_files)) if $report_unpackaged_files and @unpackaged_files;
&report_test('experimental',$pkgid,'beehive-log-multiply-packaged-files-'.$arch,
	     join('',@packaged_both)) if @packaged_both and $report_packaged_both;
&report_test('experimental',$pkgid,'beehive-log-verify-elf-'.$arch,
	     'werify-elf: warning: undefined symbols found:'."\n".
	     join('',@undefined_symbols)) if $report_undefined_symbols and @undefined_symbols;
&report_test('info',$pkgid,'beehive-log-dependency-needs-epoch-'.$arch,
	     join('',@needs_epoch)) if $report_needs_epoch and @needs_epoch;
if ($report_non_strict_dependency and @non_strict_dependency) {
    &report_test('info',$pkgid,'beehive-log-non-strict-dependency-'.$arch,
		 join("\n",map{join (': non-strict dependency on ', @$_)} @non_strict_dependency));
    &collect_data($pkgid,'beehive-log-non-strict-dependency-'.$arch,
		 join("\n",map{join ("\t", @$_)} @non_strict_dependency));
}

sub report_test_dev {
    my ($testlevel,$pkgid,$testname,@message)=@_;
    print 'repocop-test-'.$testlevel,' (',$testname,'):',$pkgid,"\n";
    print @message;
}

sub report_test {
    my ($testlevel,$pkgid,$testname,@message)=@_;
    if ($_local_debug) {
	print join("\t",$testlevel,$pkgid,$testname,@message),"\n";
    } else {
	&Test::Repocop::ExternalTest::test([-status=>$testlevel,-pkgkey=>"$pkgid.src",-test=>$testname],@message);
    }
}

sub collect_data {
    my ($pkgid,$dbname,@message)=@_;
    if ($_local_debug) {
	print $pkgid,join("\t",$dbname,@message),"\n";
    } else {
	&Test::Repocop::ExternalTest::collect([-pkgkey=>"$pkgid.src",-test=>$dbname],@message);
    }
}

__END__
