#!/usr/bin/perl -w
#
# Grab a module from CPAN and sock it into an RPM using cpanflute2
#
use strict;
use CPAN;
use File::Path;
use File::Copy;
use Config;
use Getopt::Long;

my $debug = 0;
my $dist = "";
my $release = 1;

# Pick up RPM settings
# these depend on you having a sane (ish) rpmmacros file
my $srpmdir = `/bin/rpm --eval \%_srcrpmdir`;
my $rpmdir = `/bin/rpm --eval \%_rpmdir`;
my $email = `/bin/rpm --eval \%packager`;
my $name = "";
chomp( $srpmdir );
chomp( $rpmdir );
chomp( $email );

GetOptions( "debug!" => \$debug,
            "name=s" => \$name );
if ( $name ) {
    $name = "--name $name";
}

my $wanted = shift or die "tell me what you want\n";

my $cpanflute2 = "";
for my $candidate ( "/usr/bin/cpanflute2",
                    $Config{sitebin} . "/cpanflute2",
                    "/home/waider/perl/bin/cpanflute2",
                    "/usr/lib/rpm/cpanflute2" ) {
    if ( -x $candidate ) {
        $cpanflute2 = $candidate;
    }
}

die "No CPANFLUTE2 found... install RPM::Specfile!\n" unless $cpanflute2;

my $topdir = "/var/tmp/cpan";

# figure out what our distro is, approximately.
if ( !$dist ) {
    if ( -f "/etc/redhat-release" ) {
        my $p = `/bin/rpm -qf /etc/redhat-release`;
        if ( `grep Enterprise /etc/redhat-release 2>/dev/null` ) {
            $dist = "el";
        } elsif ( `grep Fedora /etc/redhat-release 2>/dev/null` ) {
            $dist = "fc";
        } else {
            $dist = "rh";
        }
        $dist .= `rpm -q --queryformat "\%{VERSION}" $p`;
        $dist =~ s/(S|C)(erver|lient)/$1/;
    } else {
        $dist = "nodist";
    }
}

$release .= ".$dist";

# hardcoded to modules for now, and only one of, thanks.
my $filename = "";
if ( $wanted =~ m@/@ ) {
    $filename = $wanted;
    CPAN::Shell->get( $wanted );
} else {
    my $obj = CPAN::Shell->expand( "Module", $wanted );

    if ( !defined( $obj )) {
        print "No idea what that is, mate\n";
        exit( 1 );
    }

    $filename = $obj->cpan_file;

    # now fetch it
    CPAN::Shell->get( $obj );
}

my $tarfile = $CPAN::Config->{keep_source_where} . "/authors/id/$filename";

if ( ! -f $tarfile ) {
    print "Can't find the module file!\n";
    exit( 1 );
}

# sample command
# /usr/lib/rpm/cpanflute2 --noarch --buildall --email="Waider <waider@doolin.com>" --release 1 --test RPM-Specfile-1.17.tar.gz

# we should check the arch, if possible
# email should come from .rpmmacros, possibly output dir also should
# allow for optional arguments, to control testing for example
[ ! -d "$topdir" ] and mkdir "$topdir", 0755;

# Instead of any smart processing we'll bluntly build an i386 version,
# see if it has any i386 data, and if it hasn't then we'll rebuild it
# as a noarch package.
my $noarch = "";

ARCHBUILD:
print STDERR "Doing " . ( $noarch ? "noarch" : "i386" ) . " compilation...\n";
my $compiler = "$cpanflute2 $name --buildall --release $release $noarch --outdir $topdir --email \"$email\" \"$tarfile\" 2>&1 ";
open( COMPILER, "$compiler|" ) or die "can't fork: $!";
my $compilation = "";
while ( my $line = <COMPILER> ) {
    $compilation .= $line;
    print $line;
}
close( COMPILER ) or die "bad $cpanflute2: $! $?";
print STDERR "done.\n";

if ( open( BL, ">/var/tmp/cpan-build.log" )) {
    print BL $compilation;
    close( BL );
}

# check for useless "debuginfo" file(s)
my @files;
if ( opendir( CP, "$topdir" )) {
    my $arch = 0;
    for my $file ( grep /\.rpm$/, readdir( CP )) {
        my $files = `/usr/bin/rpm2cpio "$topdir/$file" | /bin/cpio -t --quiet 2>/dev/null`;
        if ( !$files ) {
            print "Nuking useless $file\n";
            unlink( "$topdir/$file" );
        } else {
            # XXX all the world's i386
            if ( $files =~ /i386/ ) {
                print "Found architecture-specific files in $file\n";
                $arch = 1;
            }
        }
    }

    if ( !$arch and !$noarch ) {
        print "No architecture-specific files found, rebuilding as a noarch package.\n";
        $noarch = "--noarch";
        goto ARCHBUILD;
    }

    # now fetch the list of files
    rewinddir( CP );

    for my $file ( grep /\.rpm$/, readdir( CP )) {
        if ( $file =~ /\.src\.rpm$/ ) {
            [ ! -d "$srpmdir" ] and
              mkpath $srpmdir, 0, 0755;
            move( "$topdir/$file", "$srpmdir/$file" ) or
              die "$topdir/$file: $!";
            push @files, "$srpmdir/$file";
        } elsif ( $file =~ /\.([^.]+)\.rpm/ ) {
            my $a = $1;

            if ( $a ne "noarch" and $noarch ) {
                unlink( "$topdir/$file" );
                next;
            }

            [ ! -d "$rpmdir/$a" ] and
              mkpath "$rpmdir/$a", 0, 0755;
            move( "$topdir/$file", "$rpmdir/$a/$file" ) or
              die "$topdir/$file: $!";
            push @files, "$rpmdir/$a/$file";
        } else {
            warn "don't know what to do with $file\n";
        }
    }
}

if ( @files ) {
    print "built: \n\t" . join( "\n\t", @files ) . "\n";
    unlink "/var/tmp/cpan-build.log";
} else {
    print "Build failed, check /var/tmp/cpan-build.log for errors\n";
    print "build command was $compiler\n";
}
