#!/usr/bin/perl -w

use strict;
use warnings;

use Getopt::Long;
use Parallel::ForkManager;
use File::Path qw(make_path remove_tree);
use File::Basename;

my $NUMBERS_SPEC=1;
my $EGREPARG;
my $aptconfig='/etc/apt/apt.conf.SS';
my $TMPDIR=$ENV{'TMPDIR'};
my $verbose;
my $help;

my $result = GetOptions (
    'quiet'=> sub {$verbose=0},
    "verbose+"  => \$verbose,
    "e|egrep=s"  => \$EGREPARG,
    "apt-config=s"  => \$aptconfig,
    "help"  => \$help,
    "tmpdir=s"  => \$TMPDIR,
    "j|jobs=s"  => \$NUMBERS_SPEC,
);

my ($MAX_PROCESSES,@numbers);
if ($NUMBERS_SPEC=~/^\d+$/) {
    $MAX_PROCESSES=$NUMBERS_SPEC;
    @numbers=1 .. $MAX_PROCESSES;
} elsif ($NUMBERS_SPEC=~/^(\d+):(\d+)$/) {
    my $min=$1;
    my $max=$2;
    die "invalid job specification $NUMBERS_SPEC" if $min>$max;
    $MAX_PROCESSES=$max-$min+1;
    @numbers=$min .. $max;
}else {
    die "invalid job specification $NUMBERS_SPEC";
}
my $pm = new Parallel::ForkManager($MAX_PROCESSES);

$pm->run_on_finish(\&retrieve_hasher_number);

make_path(qw/success/);
foreach my $rpm (@ARGV) {
    #while(@numbers==0) {sleep 1;};
    # Forks and returns the pid for the child:
    my $pid = $pm->start();
    my $number=shift @numbers;
    die "Oops: no numbers in pool" unless defined $number;
    next if $pid;
    my $hasherdir="$TMPDIR/hasher$number";
    if (not -d $hasherdir) {
	system (qw/mkdir -p/,"$hasherdir/chroot");
	system ('chgrp -R `whoami`_a'.$number." $hasherdir/chroot");
    }
    my $baserpm=basename($rpm);
    if (not -e $rpm) {
	make_path(qw/missing/);
	system('touch',"missing/$baserpm.log");
    } else {
	my $hshB="hsh --apt-config=$aptconfig --mountpoints=/proc --number=$number $hasherdir";
	if (not $EGREPARG or system("rpmquery --requires -p $rpm | egrep '$EGREPARG' >/dev/null")==0) {
	    print "$number: rebuilding $rpm\n";
	    if (system ("$hshB $rpm > hsh.log.$number".' 2>&1')==0) {
		`mv hsh.log.$number success/${baserpm}.log`;
	    } else {
		make_path(qw/success failure failure.name/);
		my $name=`rpmquery --queryformat '%{NAME}\n' -p $rpm`;
		chomp $name;
		`touch failure.name/$name`;
		`mv hsh.log.$number failure/${baserpm}.log`;
		print " FAILED:$number: $rpm\n";
	    }
	}
	`rm -f $hasherdir/repo/SRPMS.hasher/*.src.rpm $hasherdir/repo/x86_64/RPMS.hasher/*.rpm`;
    }
    $pm->finish(0, \$number); # Terminates the child process
}
$pm->wait_all_children;
$pm->DESTROY;

foreach my $number (@numbers) {
    my $hasherdir="$TMPDIR/hasher$number";
    system ('hsh-rmchroot',$hasherdir) if -d "$hasherdir/chroot";
    system (qw/rm -rf/,$hasherdir);
}

sub retrieve_hasher_number {
    my (undef,undef,$id,undef,undef,$ref)=@_;
    push @numbers,$$ref;
}

__END__
