#!/usr/bin/perl -w
# check the package list in a chroot against a reference list.
#
# Copyright © 2006 Roger Leigh <rleigh@debian.org>
#
# This program 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 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, see
# <http://www.gnu.org/licenses/>.
#
#######################################################################

use strict;
use warnings;
use locale;
use POSIX qw(locale_h);
use Sbuild::Conf qw($package_checklist);
use Sbuild::Utility qw(setup cleanup shutdown);

package main;

sub usage {
    print STDERR "Usage: $0 <chroot> [--list|--set]\n";
    exit 1;
}

usage() if (@ARGV != 2 ||
	    ($ARGV[1] ne "--list" && $ARGV[1] ne "--set") );

my $chroot = $ARGV[0];
my $cmd = $ARGV[1];

setlocale(LC_COLLATE, "POSIX");
$ENV{'LC_COLLATE'} = "POSIX";

!setup($chroot) or die "Chroot setup failed";
my $chroot_dir = $$Sbuild::Chroot::current{'Location'};
my (@status, @ref, @install, @remove);

if (! open STATUS, "grep-status -F Status -s Package ' installed' '$chroot_dir/var/lib/dpkg/status' | awk '{print \$2}' |" ) {
    print STDERR "Can't read dpkg status file in chroot: $!\n";
    shutdown();
}
while (<STATUS>) {
    chomp;
    push @status, $_;
}
if (! close STATUS) {
    print STDERR "Error reading dpkg status file in chroot: $!\n";
    shutdown();
}
@status = sort @status;
if (!@status) {
    print STDERR "dpkg status file is empty\n";
    shutdown();
}

if ($cmd eq "--set") {
    if (! open WREF, "> $chroot_dir/$package_checklist") {
	print STDERR "Can't write reference status file $chroot_dir/$package_checklist: $!\n";
	shutdown();
    }
    foreach (@status) {
	print WREF "$_\n";
    }
    if (! close WREF) {
	print STDERR "Error writing reference status file: $!\n";
	shutdown();
    }
} else { # --list

    if (! open REF, "< $chroot_dir/$package_checklist") {
	print STDERR "Can't read reference status file $chroot_dir/$package_checklist: $!\n";
	shutdown();
    }
    while (<REF>) {
	chomp;
	push @ref, $_;
    }
    if (! close REF) {
	print STDERR "Error reading reference status file: $!\n";
	shutdown();
    }

    @ref = sort @ref;
    if (!@ref) {
	print STDERR "Reference status file is empty\n";
	shutdown();
    }

    print "DELETE             ADD\n";
    print "======================================\n";
    my $i = 0;
    my $j = 0;

    while ($i < scalar @status && $j < scalar @ref) {

	my $c = $status[$i] cmp $ref[$j];
	if ($c < 0) {
	    # In status, not reference; remove.
	    print "$status[$i]\n";
	    $i++;
	} elsif ($c > 0) {
	    # In reference, not status; install.
	    print "                   $ref[$j]\n";
	    $j++;
	} else {
	    # Identical; skip.
	    $i++; $j++;
	}
    }

# Print any remaining elements
    while ($i < scalar @status) {
	print "$status[$i]\n";
	$i++;
    }
    while ($j < scalar @ref) {
	print "                   $ref[$j]\n";
	$j++;
    }
}

cleanup();
exit 0;
