#! /usr/bin/perl
# $Id: updated-packages,v 1.5.2.1 1998/02/12 22:48:45 asm21 Exp $

# get a list of files to install, for whatever reason (ie because they've been requested, because they're already
# installed but have a new version out, or because they're marked as reinst-required). The output is a list of
# TAB-separated fields:
#	package-name filename current-version new-version
# Commandline options are the location of the status file, followed by one or more package files or available-package
# lists. If the same package occurs more than once in the available package file(s), it is guaranteed to only occur once
# in the output, but the filename and new version number may be any of those named in the available files.
    
# (c) 1997 Andy Mortimer.

#use strict;
#use diagnostics;

# deal with arguments
my $status = $ARGV[0];
my $doavailable=0;
if ($status eq '--available') {
    $doavailable=1;
    $status = $ARGV[1];
    shift @ARGV;
}
shift @ARGV;
my @available = @ARGV;

# read in the list of package stati
my %version;
sub procstatus {
    my $statusf=shift;
    my $pkg='';
    my $wantinst;
    my $forceinst;
    my $version;
    
    open (STATUS, $statusf) or die "Cannot open status file $statusf";
    while (<STATUS>) {
	chomp;
	
	if (/^([^ \t]+):[ \t]*(.*)[ \t]*$/) {
	    my $fld=$1;
	    my $val=$2;
	    $fld=lc($fld);
	    if ( $fld eq 'package' ) {
		$pkg=$val;
		$wantinst=0;
		$forceinst=0;
		$version='';
	    } elsif ($pkg ne '') {
		# if the version is already defined, it's set to '' from the status field
		if ($fld eq 'version') {
		    $version=$val;
		} elsif ($fld eq 'status') {
		    # if the package is marked to install, and is not installed right, then we want to do it anyway.
		    # We mark this by setting the version to ''.
		    # NB that if we don't already have it and don't want it, it never gets a version entry at all.
		    # This overrides the version number of the installed package, as we /know/ that we want it.
		    my ($selec,$flag,$stat)=split(/[ \t]+/,$val);
		    if ($selec eq "install" || $flag eq "reinstreq") {
			$wantinst=1;
			if ($flag eq "reinstreq" or $stat ne "installed" or $flag ne "ok") {
			    $forceinst=1;
			}
		    }
		}
	    }
	} elsif ( $_ eq '' and $pkg ne '' ) {
	    if ($wantinst || $doavailable) {
		if ($forceinst) {
		    $version{$pkg} = '';
		} else {
		    $version{$pkg} = $version;
		}
	    }
	    $pkg='';
	}
    }
    close(STATUS) or die "Error closing status file $statusf";
}

print STDERR "Reading current status ...\n";
procstatus($status);

sub dcmpvers {
    my($a, $p, $b) = @_;
    my ($r);
    $r = system("/usr/bin/dpkg", "--compare-versions", "$a", "$p", "$b");
    $r = $r/256;
    if( $r == 0) {
	return 1;
    } if( $r == 1) {
	return 0;
    }
    die "dpkg --compare-versions $a $p $b - failed with $r"
}

my %get;
my %fname;
my %newver;
my %md5sum;

sub procavail {
    my $availf=shift;
    my $fname='';
    my $getme=0;
    my $pkg='';
    my $newver;
    my $md5sum;
    
    open(AVAIL,$availf) or die "Error: cannot open available packages file $availf: $!\n"
	. "Maybe you haven't updated the package list?\n";
  PACKAGE: while (<AVAIL>) {
	chop;
	
	if (/^([^ \t]+):[ \t]*(.*)[ \t]*$/) {
	    my $fld=$1;
	    my $val=$2;
	    $fld=lc($fld);
	    if ( $fld eq 'package' ) {
		$pkg=$val;
		if (!defined($version{$pkg})) {
		    my $inp;
		    while (<AVAIL>) {
			chop;
			if ($_ eq '') {
			    next PACKAGE;
			}
		    }
		    next PACKAGE;
		}
		if ($version{$pkg} eq '') {
		    $getme=1;
		} else {
		    $getme=0;
		}
		$fname='';
		$newver='';
		$md5sum='';
	    } elsif ($fld eq 'filename') {
		$fname=$val;
	    } elsif ($fld eq 'version') {
		$newver=$val;
	    } elsif ($fld eq 'md5sum') {
		$md5sum=$val;
	    }
	} elsif ($_ eq '') {
	    if ($getme ||
		($newver ne $version{$pkg}
		 && dcmpvers($newver,"gt",$version{$pkg}))) {
		$get{$pkg}=1;
		$fname{$pkg}=$fname;
		$newver{$pkg}=$newver;
		$md5sum{$pkg}=$md5sum;
	    }
	    $pkg='';
	}
    }
    close(AVAIL) or die "Error closing available packages file $availf";
}
my $f;
for $f (@available) {
    print STDERR "Processing available packages file $f ...\n";
    procavail($f);
}

my $p;
for $p (sort(keys(%get))) {
    print "$p\t$fname{$p}\t$version{$p}\t$newver{$p}\t$md5sum{$p}\n";
}
