#!/usr/bin/perl

use Dpkg::Version qw(version_compare);
use Getopt::Long;

GetOptions('old=s' => \my $oldreleasefile,
	   'old-sec=s' => \my $oldsecreleasefile, 
	   'new=s' => \my $newreleasefile,
	   'new-sec=s'=> \my $newsecreleasefile,
	   'debug' => \my $debug,
	   'info' => \my $info,
	   'stats' => \my $stats,
    );

if (
    $oldreleasefile eq "" ||
    $oldsecreleasefile eq "" ||
    $newreleasefile eq "" ||
    $newsecreleasefile eq ""
    ) {
    print "Usage: checkversions.pl [optional options] -old <file> -old-sec <file> -new <file> -new-sec <file>\n";
    print "Optional options:\n";
    print "   --debug           Print debugging information\n";
    print " <file> refers to a path to an apt packages file. It can either be a binary packages file for binary package comparison or a source packages file for source packages comparison.\n";
    print "   -old <file>       Packages file for the older release.\n";
    print "   -old-sec <file>   Packages file for the older security updates.\n";
    print "   -new <file>       Packages file for the newer release.\n";
    print "   -new-sec <file>   Packages file for the newer security updates.\n";
    exit 1;
}

sub parsereleasefile {
    my ($file) = @_;
    my %packlist = ();
    open F, $file;
    my $line;
    my $pack = "";
    my $ver = "";
    while ($line = <F>) {
	if ($line =~ /^Package: (\S+)/) {
	    $pack = $1;
	}
	if ($line =~ /^Version: (\S+)/) {
	    $ver = $1;
	}
	if ($line =~ /^\s*$/) {
	    if ($pack ne "" && $ver ne "") {
		$packlist{$pack} = $ver;
	    }
	    $pack = "";
	    $ver = "";
	}
    }
    # To handle the case of last entry.
    if ($pack ne "" && $ver ne "") {
	$packlist{$pack} = $ver;
    }
    close F;
    return %packlist;
}

sub mergepackagestruct {
    my $ref0 = shift @_;
    my @refs = @_;
    my %merged = %$ref0;
    my $ref;
    foreach $ref (@refs) {
	my %refhash = %$ref;
	my $pack;
	foreach $pack (keys %refhash) {
	    my $vern = $refhash{$pack};
	    my $verm = $merged{$pack};
	    if ("$verm" eq "") {
		$merged{$pack} = $vern;
		print "INFO: $pack new\n" if ($info);
	    }
	    elsif (&version_compare($vern,$verm) > 0) {
		print "INFO: $pack $vern newer than $verm so merging\n" if ($info);
		$merged{$pack} = $vern;
	    }
	    # Else do nothing
	}
    }
    return %merged;
}

sub findolderinnew {
    my ($oldr, $newr) = @_;
    my %old = %$oldr;
    my %new = %$newr;
    my $pack;
    foreach $pack (keys %new) {
	my $over = $old{$pack};
	my $nver = $new{$pack};
	print "DEBUG: $pack old = $over new = $nver\n" if ($debug);
	if ("$over" ne "") {
	    if (&version_compare($over,$nver) > 0) {
		print "$pack: $over newer than $nver\n";
	    }
	}
    }
}

sub printpackages {
    my ($ref) = @_;
    my %struct = %$ref;
    my $pack = "";
    foreach $pack (keys %struct) {
	print "$pack: $struct{$pack}\n";
    }
}

    
my %old = &parsereleasefile($oldreleasefile);
my %oldsec = &parsereleasefile($oldsecreleasefile);
my %new = &parsereleasefile($newreleasefile);
my %newsec = &parsereleasefile($newsecreleasefile);
my %oldm = &mergepackagestruct(\%old, \%oldsec);
my %newm = &mergepackagestruct(\%new, \%newsec);
if ($stats) {
    print "Statistics:\n";
    print "old: ".(keys %old)."\n";
    print "old-sec: ".(keys %oldsec)."\n";
    print "new: ".(keys %new)."\n";
    print "new-sec: ".(keys %newsec)."\n";
    print "old merged: ".(keys %oldm)."\n";
    print "new merged: ".(keys %newm)."\n";
}

my %err1 = &findolderinnew(\%oldm, \%newm);

1;
