#!/usr/bin/perl

# Author: Kevin K.M. Chiu
# Copyright 2001, Cobalt Networks.  All rights reserved.
# $Id: makePkg 3 2003-07-17 15:19:15Z will $

# This script is used by module.mk to make a PKG file from a module.
#
# There is no need to specify RPM fields in <module>/pkg_packing_list.
# All RPMs under <module>/as_rpms are automatically included in the final
# packing_list.

# 2012-08-07 (mstauber): Added optional sorting of RPMs. Not perfect yet, 
#			 but it is a start.

use strict;
use Cwd;
use Getopt::Std;

# get options
getopts('a:l:n:r:s:v:');
use vars qw($opt_a $opt_l $opt_n $opt_r $opt_s $opt_v);

# commands
my $cp = '/bin/cp';
my $mkdir = '/bin/mkdir';
my $msgfmt = '/usr/bin/msgfmt';
my $rm = '/bin/rm';
my $tar = '/bin/tar';

# this is the root of the module
my $moduleDir = cwd();

# path constants
my $redhatRpmsDir = '/usr/src/redhat/RPMS';
my $tmpDir = '/tmp';
my $tmpTarDir = "$tmpDir/pkg$$";
my $origPackingList = "$moduleDir/pkg_packing_list";

# read parameters
my @locales = split /\s/, $opt_l;
my $vendor = $opt_v;
my $service = $opt_s;
my $version = $opt_n;
my $release = $opt_r;
my $arch = $opt_a;

# crucial parameters must exist
if($vendor eq '' || $service eq '' || $version eq '' || $release eq '') {
    die "ERROR: Insufficient parameters to $0";
}

# packing list must exist
if(! -f $origPackingList) {
    die "ERROR: $origPackingList does not exist";
}

# make the tar directory
`$mkdir -p $tmpTarDir`;

# copy the whole scripts directory if it exists
if(-d "$moduleDir/scripts") {
    `$cp -r $moduleDir/scripts $tmpTarDir`;
}

# copy the whole scripts directory if it exists
if(-d "$moduleDir/scripts") {
    `$cp -r $moduleDir/scripts $tmpTarDir`;
}

# copy the whole pkginfo directory if it exists
if(-d "$moduleDir/pkginfo") {
    `$cp -r $moduleDir/pkginfo $tmpTarDir`;

    # locale directory will be handled later separately, so we clean it up here
    my $tarLocaleDir = "$tmpTarDir/pkginfo/locale";
    if(-d $tarLocaleDir) {
	`rm -r $tarLocaleDir`;
    }
}

# compile .po files if they exist
# we compile all the .po files instead of following the locale list supplied
# as script parameter because that list is for the data in the PKG, but we're
# dealing with the meta data of the PKG here.
my $localeDir = "$moduleDir/pkginfo/locale";
if(-d $localeDir) {
    # read all the locales
    opendir(DIR, $localeDir)
	|| die "ERROR: Cannot open directory $localeDir";
    my @pkgLocales = readdir(DIR);
    closedir(DIR);

    # remove hidden files
    @pkgLocales = grep !/^\./, @pkgLocales;

    # loop through all the locales
    my $pkgLocale;
    foreach $pkgLocale (@pkgLocales) {
	my $poDir = "$localeDir/$pkgLocale";

	# get all .po files
	opendir(DIR, $poDir);
	my @poFiles = readdir(DIR);
	closedir(DIR);

	# filter out hidden files or non-.po files
	@poFiles = grep /^[^\.].+\.po$/i, @poFiles;

	# compile all the .po files
	my $poFile;
	foreach $poFile (@poFiles) {
	    # get .mo file name
	    my $moFile = $poFile;
	    $moFile =~ s/\.po$/.mo/i;

	    `$mkdir -p $tmpTarDir/pkginfo/locale/$pkgLocale`;
	    `$msgfmt -o $tmpTarDir/pkginfo/locale/$pkgLocale/$moFile $poDir/$poFile`;
	}
    }
}

# the list of RPMs in the PKG
my @rpms = ();

# include RPMs under as_rpms directory
my $rpmsDir = "$moduleDir/as_rpms";
if(-d $rpmsDir) {
    opendir(DIR, $rpmsDir)
	|| die "ERROR: Cannot open directory $rpmsDir";
    @rpms = readdir(DIR);
    closedir(DIR);

    # filter away hidden files or non-rpm files
    @rpms = grep /^[^\.].+\.rpm$/i, @rpms;

    # make directory to hold RPMs
    if($#rpms >= 0) {
	`$mkdir -p $tmpTarDir/RPMS`;
    }

    # copy RPMs to the directory
    my $rpm;
    foreach $rpm (@rpms) {
	`$cp $rpmsDir/$rpm $tmpTarDir/RPMS/`;
    }
}

# build the packing list
open(IN, $origPackingList)
    || die "ERROR: Cannot open file $origPackingList";
open(OUT, ">$tmpTarDir/packing_list")
    || die "ERROR: Cannot open file $tmpTarDir/packing_list";
my $line;
while($line = <IN>) {
    # discard all the RPM fields
    if($line =~ /^\s*RPM:\s+(.*)$/) {
	next;
    }

    if (!-f "/usr/sausalito/devel/.pkgsort") {
      # Dump list of RPMs into a sorted fashion:
      # put in RPM list before the end
      if($line =~ /^\s*\[\/Package\]/) {
        my $inrpms = `/usr/sausalito/bin/rpmsorter.sh $rpmsDir`;
        @rpms = split /\s+/, $inrpms;
	my $rpm;
	foreach $rpm (@rpms) {
	    print OUT "RPM: $rpm\n";
	}
      }
    }
    else {
      ### Start: Sort very basically
      # Sort RPMs in a fashion that doesn't resolve dependencies yet, but at least maintain
      # the bare neccessities: locate, ui, glue and capstone get installed in that order.
      # But only after anything else has been installed.
      if($line =~ /^\s*\[\/Package\]/) {
	my %HoA = ('capstone' => [], 'locale' => [], 'glue' => [], 'ui' => [], 'other' => []);
	my $line;
	my $i;
	foreach $line (@rpms) {
            my $rpmname = $line;
            if ($rpmname =~ m/-capstone-/g) {
                push(@{$HoA{'capstone'}}, $rpmname);
            }
            elsif ($rpmname =~ m/-locale-/g) {
                push(@{$HoA{'locale'}}, $rpmname);
            }
            elsif ($rpmname =~ m/-glue-/g) {
                push(@{$HoA{'glue'}}, $rpmname);
            }
            elsif ($rpmname =~ m/-ui-/g) {
                push(@{$HoA{'ui'}}, $rpmname);
            }
            elsif ($rpmname =~ m/\.rpm/g) {
                push(@{$HoA{'other'}}, $rpmname);
            }
	}

	$i = 0;
	foreach $line (@{$HoA{'other'}}) {
	  print OUT "RPM: " . $HoA{'other'}->[$i] . "\n"; 
	  $i++;
	}
	$i = 0;
	foreach $line (@{$HoA{'locale'}}) {
	  print OUT "RPM: " . $HoA{'locale'}->[$i] . "\n"; 
	  $i++;
	}
	$i = 0;
	foreach $line (@{$HoA{'locale'}}) {
	  print OUT "RPM: " . $HoA{'locale'}->[$i] . "\n"; 
	  $i++;
	}
	$i = 0;
	foreach $line (@{$HoA{'ui'}}) {
	  print OUT "RPM: " . $HoA{'ui'}->[$i] . "\n"; 
	  $i++;
	}
	$i = 0;
	foreach $line (@{$HoA{'glue'}}) {
	  print OUT "RPM: " . $HoA{'glue'}->[$i] . "\n"; 
	  $i++;
	}
	$i = 0;
	foreach $line (@{$HoA{'capstone'}}) {
	  print OUT "RPM: " . $HoA{'capstone'}->[$i] . "\n"; 
	  $i++;
	}
      }
    }
    ### End: Sort

    # print to target
    print OUT $line;
}
close(IN);
close(OUT);

# tar up the PKG
`cd $tmpTarDir; $tar --exclude '.svn' -czf $moduleDir/$vendor-$service-$version-$release.pkg .`;

# clean up
`$rm -r $tmpTarDir`;

exit;
