#!/usr/bin/perl -w
# vim: nowrap ts=4
# apt-mkpkglist -- create consistent package list with resolved dependencies
# Copyright 2001 Roland Bauerschmidt <rb@debian.org>, GPL
# with lots of help from Brenden O'Dea over mail and IRC...

use strict;
use AptPkg::Config '$_config';
use AptPkg::System '$_system';
use AptPkg::Cache;

(my $self = $0) =~ s#.*/##;
$_config->init();
$_system = $_config->system or die 'system';
$_config->{quiet} = 2;

my @ARGV = $_config->parse_cmdline([
		[ 'v', 'verbose', 'verbose' ],
		[ 'R', 'recommends', 'recommends' ],
		[ 'S', 'suggests', 'suggests' ],
	], @ARGV);

my $input = shift(@ARGV) or die "$self: no input file given\n";
my $output = shift(@ARGV) or die "$self: no output file given\n";
open(IN, "<$input");
open(OUT, ">$output");

my @packages;
my @virtual;
my $cache = AptPkg::Cache->new(0);

foreach(<IN>)
{
	chomp();
	$_ =~ s/ *\#.*//;
	next if($_ eq "");
	push_package($_);
}

foreach(@packages) {
	print OUT $_."\n";
}

sub push_package {
	my $pkg = shift;
	dprintf("processing package %s\n", $pkg);
	if(in_array($pkg, @packages)) {
		dprintf("  already satisfied\n");
		return;
	}
	my @depends;
	
	# for real package we get all the dependencies for later recursion.
	if(defined($cache->{$pkg}{VersionList})) {
		# add all the packages this package depends on into an array, since
		# those dependencies will also have to be satisfied. This is
		# recursive.
		if($cache->{$pkg}{VersionList}[0]{DependsList}) {
			foreach(@{$cache->{$pkg}{VersionList}[0]{DependsList}}) {
				if($_->{DepType} eq "Depends" || $_->{DepType} eq "PreDepends" ||
					$_->{DepType} eq "Recommends" && $_config->get_bool('recommends') ||
					$_->{DepType} eq "Suggests" && $_config->get_bool('suggests')) {
						dprintf("  %s %s\n", lc($_->{DepType}),
							$_->{TargetPkg}->{Name});
						push(@depends, $_->{TargetPkg}{Name});
				}
			}
		}
		# push all the packages this package provides into an array, so we
		# don't need to add any other packages later if dependencies on
		# virtual packages are already satisfied through this package
		if($cache->{$pkg}{ProvidesList}) {
			foreach(@{$cache->{$pkg}{ProvidesList}}) {
				push(@virtual, $_->{Name});
			}
		}
		push(@packages, $pkg);
	# for virtual packages check if dependency is already satisfied,
	# otherwise add a package to satisfy the dependency
	} elsif(!in_array($pkg, @virtual) && defined($cache->{$pkg}{ProvidesList})) {
		dprintf("  virtual package provided by %s\n",
			$cache->{$pkg}->{ProvidesList}[0]{OwnerPkg}{Name});
		# since the code for selecting package with highest priority
		# is not there yet, just take the first one
		push(@depends, $cache->{$pkg}->{ProvidesList}[0]{OwnerPkg}{Name});
		# choose package with highest priority should be done here later
		# it'd be nice if it could be done like this, but it can't
		# need to do this with VerFile
		#my $highest;
		#foreach(@{$cache->{$_}{ProvidesList}}) {
			#print "reverse provides: ".$_->{OwnerPkg}{Name}."\n";
			#push(@depends, $_->{OwnerPkg}{Name});
			#if($highest->{Priority} < $_->{OwnerPkg}{Priority}) {
			#	$highest = $_->{OwnerPkg};
			#}
		#}
		#push(@depends, $highest->{Name});
	}
	
	foreach(@depends) {
		push_package($_) if(!in_array($_, @packages));
	}
}

sub in_array
{
	my $key = shift;
	foreach(@_) {
		return(1) if($key eq $_);
	}
	return(0);
}

sub dprintf
{
	printf(@_) if $_config->get_bool("verbose");
}

