#!/usr/bin/perl -w

=head1 NAME

dh_stardeps - calculates GNU Smalltalk archives (.star) dependencies

=cut

use strict;
use File::Find;
use Debian::Debhelper::Dh_Lib;

=head1 SYNOPSIS

B<dh_stardeps> [S<I<debhelper options>>]

=head1 DESCRIPTION

dh_stardeps is a debhelper program that is responsible for generating the
${gst:Depends} substitutions and adding them to substvars files.

The program wil look at .star files in your package, and will use the
dependency information generated by dh_makestarlibs to compute the
${gst:Depends} variable.

=cut

init();

verbose_print("Loading starlibs...");
my %starlibdata;

open(STARLIBS, "cat /var/lib/dpkg/info/*.starlibs debian/*/DEBIAN/starlibs 2> /dev/null |");

while (<STARLIBS>) {
    /(\S+)\s+(\w.*)\n?/;
    $starlibdata{$1} = $2;
}

close(STARLIBS);

verbose_print("Loading shlibs...");
my %shlibdata;

open(SHLIBS, "cat /var/lib/dpkg/info/*.shlibs debian/shlibs.local debian/*/DEBIAN/shlibs 2> /dev/null |");

while (<SHLIBS>) {
    /(\S+)\s+(\S+)\s+(\w.*)\n?/;
    $shlibdata{$1} = $3;
}

close(SHLIBS);

foreach my $package (@{$dh{DOPACKAGES}}) {
    my $tmp = tmpdir($package);
    my @depends = ();

    # for idempotency
    delsubstvar($package, "gst:Depends");

    find(sub {
	     return unless -f && !-l && /\.star$/;
	     my $file = $_;
	     push(@depends, resolve_starlib_ref($package, $file));
	 }, $tmp
    );

    @depends = unique(@depends);

    addsubstvar($package, "gst:Depends", join(", ", @depends));
}

sub resolve_starlib_ref {
    my $package = shift;
    my $star_file = shift;
    my @deps = ();
    my $in_test = 0;

    open(PACKAGEXML, "unzip -p $star_file package.xml |");

    while(<PACKAGEXML>) {
	chomp;

	if (/<test>/) {
	    $in_test = 1;
	} elsif (/<\/test>/) {
	    $in_test = 0;
	}

	# Handle prereq packages -- but not for tests
	elsif (/<prereq>(\S+)<\/prereq>/ and not $in_test) {
	    my $dep = $starlibdata{$1};

	    if ($dep) {
		if ($dep !~ m/^$package(?:\s+.+)?$/) {
		    push(@deps, $dep);
		}
	    } else {
		error("Unknown dependency \"$1\" in \"$star_file\"!");
	    }

	# Package with unit tests; depends on SUnit. This dependency might
	# already be captured, but we'll remove duplicates later.
	} elsif (/<sunit>/) {
	    if (exists($starlibdata{"SUnit"})) {
		# Only if this is not the package containing SUnit already
		if ($starlibdata{"SUnit"} !~ m/^$package(?:\s+.+)?$/) {
		    push(@deps, $starlibdata{"SUnit"});
		}
	    } else {
		warning("Unable to store SUnit dependency for \"$star_file\"");
	    }

	# Package that loads a library at runtime, with dlopen()
	} elsif (/<library>(\S+)<\/library>/) {
	    my $lib = $shlibdata{$1};

	    if ($lib) {
		push(@deps, $lib);
	    } else {
		error("Unknown library dependency \"$1\" in \"$star_file\"!");
	    }
	}
    }

    close(PACKAGEXML);

    return @deps;
}

sub unique {
    my %seen = ();
    return grep(!$seen{$_}++, @_);
}

=head1 SEE ALSO

L<debhelper(7)>

=head1 AUTHOR

Thomas Girard <thomas.g.girard@free.fr>, heavily based on code from
Mirco Bauer <meebey@meebey.net> and Eduard Bloch <blade@debian.org>
for dh_clideps.

=cut
