#!/usr/bin/perl

#
# $Id: gendistrib,v 1.15 2004/01/05 21:51:31 othauvin Exp $
#

#- Copyright (C) 1999 MandrakeSoft (fpons@mandrakesoft.com)
#-
#- 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, 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, write to the Free Software
#- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

use strict;
use URPM;
use URPM::Build;
use Getopt::Long;

my $urpm = new URPM;
my ($noclean, $nohdlists, $nobasefiles, $nooutput, $dontdie, $nochkdep, $rootdistrib, @root, @hdlists) = (0, 0, 0, 0);
my $headers_dir = (-d "$ENV{HOME}/tmp" ? "$ENV{HOME}/tmp" : $ENV{TMPDIR} || "/tmp") . "/.build_hdlist";

sub usage {
	print <<EOF;
Usage $0 [options] dir [dir...]
First dir should be the top level of distro
Options:
  --help              print this message and exit
  --headersdir dir    put temporary files in dir
  -s                  silent mode
  --nochkdep          do not find missing dependancies
  --nobadrpm          do not stop on bad rpm
  --noclean           keep cache files

EOF
}

my %urpmfiles;

GetOptions(
	'help|h' => sub { usage(); exit },
	'noclean' => \$noclean,
	'distrib=s' => \$rootdistrib,
	'headersdir=s' => \$headers_dir,
	'fermetagueule|s' => \$nooutput,
	'nochkdep' => \$nochkdep,
	'nobadrpm' => \$dontdie,
	'depslist=s' => \$urpmfiles{depslist},
	'provides=s' => \$urpmfiles{provides},
	'compss=s' => \$urpmfiles{compss},
	'hdlists=s' => \$urpmfiles{hdlists},
);

@root = grep { $_ } ($rootdistrib, @ARGV);

@root > 0 or do { usage(); exit 1 };

my $root = $root[0];

my %default_urpmfiles = (
	depslist =>  "$root/Mandrake/base/depslist.ordered",
	provides => "$root/Mandrake/base/provides",
	compss =>   "$root/Mandrake/base/compss",
	hdlists =>  "$root/Mandrake/base/hdlists",
	version =>  "$root/VERSION",
	md5sum =>   "$root/Mandrake/base/MD5SUM",	
);

while (my ($k, $v) = each(%default_urpmfiles)) {
	$urpmfiles{$k} ||= $v;
}

open F, $urpmfiles{hdlists} or die "unable to open $urpmfiles{hdlists}";
foreach (<F>) {
    chomp;
    s/\s*#.*$//;
    /^\s*$/ and next;
    m/^\s*(?:noauto:)?(hdlist\S*\.cz2?)\s+(\S+)\s*(.*)$/ or die "invalid hdlist description \"$_\" in hdlists file";

    push @hdlists, { synthesis => "$root/Mandrake/base/synthesis.$1", hdlist => "$root/Mandrake/base/$1", dir => $2, descr => $3 };
}
close F;

sub clean_cache {
    system($ENV{LD_LOADER} ? $ENV{LD_LOADER} : @{[]}, "rm", "-rf", $headers_dir) unless $noclean;
}

clean_cache();

foreach (0..$#hdlists) {
    my $e = $hdlists[$_];
    my $r;

    #- try to find the right repository where can be found the directory
    #- listed in the hdlist file.
    #- if the number of root is equal the number of medium, assume a medium
    #- foreach root, else try to find a valid root containing the medium.
    $r ||= $root[0];
    if (scalar(@hdlists) == scalar(@root)) {
	$r = $root[$_];
    } else {
	foreach (@root) {
	    -d "$_/$e->{dir}" and $r = $_, last;
	}
    }

    #- fake build of architecture dependent directory.
    my @files;
    if ($e->{dir} =~ /%{ARCH}/) {
	foreach my $arch (qw(i686 i586 i486 i386 k8 k7 k6 amd64 amd32 x86_64 x86_32 ia64 ia32
                             ppc sparc sparc32 sparc64 alpha noarch)) {
	    my $dir = $e->{dir};
	    $dir =~ s|%{ARCH}|$arch|g;
	    push @files, glob("$r/$dir/*.$arch.rpm");
	}
    } else {
	push @files, glob("$r/$e->{dir}/*.rpm");
    }
    @files or die "unable to find rpm files in $e->{dir}\n";

    print STDERR "parsing rpm files in directory $r/$e->{dir}\n" unless $nooutput;
    my @headers = $urpm->parse_rpms_build_headers(dir  => $headers_dir, rpms => \@files,
    						dontdie => $dontdie, silent => $nooutput);
    $e->{headers} = \@headers;
}

#- clean everything to start second pass.
print STDERR "clean data for second pass\n" unless $nooutput;
$urpm->unresolved_provides_clean;

foreach (0..$#hdlists) {
    my $e = $hdlists[$_];

    print STDERR "parsing headers for $e->{descr}\n" unless $nooutput;
    my ($start, $end) = $urpm->parse_headers(dir     => $headers_dir,
					     headers => $e->{headers},
				             dontdie => $dontdie,
					     silent  => $nooutput);

    print STDERR "computing deps\n" unless $nooutput;
    $urpm->compute_deps;

    print STDERR "building hdlist for medium \"$e->{descr}\"\n" unless $nooutput;
    $urpm->build_hdlist(start  => $start,
			end    => $end,
			dir    => $headers_dir,
			hdlist => $e->{hdlist},
			ratio  => 9);

    print STDERR "building synthesis for medium \"$e->{descr}\n" unless $nooutput;
    $urpm->build_synthesis(start     => $start,
			   end       => $end,
			   synthesis => $e->{synthesis});
}

clean_cache();

print STDERR "building base files\n" unless $nooutput;
$urpm->build_base_files(depslist => $urpmfiles{depslist},
			provides => $urpmfiles{provides},
			compss   => $urpmfiles{compss});

#- safety cleaning
unlink $urpmfiles{md5sum};

#- check if there are NOTFOUND in dependancy, check if they are in other medium, warn the user.
if (! $nochkdep) {
    foreach (0 .. $#{$urpm->{depslist}}) {
        my $pkg = $urpm->{depslist}[$_];

        foreach (split " ", $urpm->{deps}[$_]) {
	    /NOTFOUND_(.*)/ or next;
	    print STDERR $pkg->fullname . " requires [$1] which\n";
	    if ($urpm->{provides}{$1}) {
	        print STDERR "  is available on packages not listed in this medium or previous medium:\n";
	        foreach (keys %{$urpm->{provides}{$1}}) {
		    my $dep_pkg = $urpm->{depslist}[$_];
		    print STDERR "    " . $dep_pkg->fullname . "\n";
	        }
	    } else {
	        print STDERR "  is not available in any medium listed\n";
	        if (/NOTFOUND_(\D*)(\d+[\.\-\d]*)?(.*)?\.so\./) {
		    my $re = (quotemeta $1) . '(\d+[\.\-\d]*)' . (!$2 && "?") . '\.so\.';
		    foreach (keys %{$urpm->{provides}}) {
		        /$re/ or next;
		        print STDERR "  but a similar provides is available as [$_], need rebuild ?\n";
		    }
	        }
            }
        }
    }
}