#!/usr/bin/perl

use Cwd;
use strict;
use FileHandle;
use Getopt::Long;

die "Usage:\n$0 <template1> <template2> <template3> ...\n"  if $#ARGV lt 0;

my $PROCESS_ALL = 0;
my $QUIET = 0;
my $BUILD_DIR;

my $EXITCODE = 0;

GetOptions("process-all", \$PROCESS_ALL,
	   "build-dir=s", \$BUILD_DIR,
	   "quiet", \$QUIET);
 
# first, check to make sure that there's a template file, a packing list,
# and an RPMS directory with version numbers in the current directory.
my @templates = @ARGV;
my $outfile = 'release_spec';  # base name for output file
my $listsuffix = undef;
my $packing_list = 'packing_list';  # base packing list for a product
my $RPMS = 'RPMS';
my $SRPMS = 'SRPMS';


sub convert_arch
{
    my $arch = shift;
    $arch =~ s/i.86/i386/;
    return $arch;
}

sub flatten_module
{
    my ($dir, $builddir, $listsuffix) = @_;
    my ($file, %files, @auto, @list, $buildlocale);
    my ($vendor, $service, $vendorname, $xlocalepat);
    my ($major, $minor, $found);
    local *LIST; # this needs to be local 

    my $arch = `uname -m`;
    $arch = convert_arch(`uname -m`);
    chomp($arch);

    my $mod;
    if ($dir =~ /(.*\/+)*([^\/]+)$/) {
      # module is name of dir we are in
      $mod = $2;
    }
	
    # check for local rpms. NOTE: this won't actually make them.
    # this part isn't recursive, so we can re-use them.
    if (open(DEFINES, "$dir/Makefile")) {
	while (<DEFINES>) {
	    if (/^VERSION=(\S+)/) {
		$major = $1;
		next;
	    }

	    if (/^RELEASE=(\S+)/) {
		$minor = $1;
		next;
	    } 

	    if (/^VENDOR=(\S+)/) {
		$vendor = $1;
		next;
	    } 

	    if (/^SERVICE=(\S+)/) {
		$service = $1;
		next;
	    } 

	    if (/^VENDORNAME=(\S+)/) {
		$vendorname = $1;
		next;
	    } 

	    if (/^BUILDARCH=(\S+)/) {
		$arch = $1;
		next;
	    } 

	    if (/^XLOCALEPAT=(.*)/) {
		$xlocalepat = $1;
		next;
	    }

	    if (/^BUILDLOCALE=yes/) {
		$buildlocale = 1;
		next;
	    } 

	    if (/^BUILD(\S+?)=yes/) {
		    $found = lc $1;
		    next if ($found eq 'src');
		    push @auto, 
		    "$vendor-$service-$found-$major-$minor.$arch.rpm:$mod";
		    next;
	    }
	}
	close(DEFINES);

	if ($buildlocale) {
	    my ($locale, @locales);
	    my $localedir = "$dir/locale/$vendorname";
	    $localedir = "$dir/locale" unless -d $localedir;

	    my @xlocalepat = ();

	    # override whatever was in the make file with the environment if set
	    if($ENV{XLOCALEPAT}) {
		@xlocalepat = split(/\s+/, $ENV{XLOCALEPAT});
	    } else {
		@xlocalepat = split(/\s+/, $xlocalepat);
	    }

	    if (opendir(LOCALE, $localedir)) {
		while ($locale = readdir(LOCALE)) {
		    next if /^\./;
		    next if /^CVS/;
		    
		    # just grep @xlocalepat for $locale because if it is there
		    # just go to next entry in LOCALE --pbaltz Fri Jun 23 2000
		    #foreach $locale (@xlocalepat) {
		    #   next if /^$locale/;
		    #	next unless -f "$locale/$service.po";
		    #}
		    next if grep /^$locale/, @xlocalepat;

		    # only include this locale if its po file exists pb 6/23/00
		    next unless -f "$localedir/$locale/$service.po";
		    push @locales, $locale;
		}
		closedir(LOCALE);

		if (@locales) {
		    $found = 'locale';
		    $QUIET || print "found locale package...";
		    foreach $locale (@locales) {
			push @auto, 
			"$vendor-$service-locale-$locale-$major-$minor.$arch.rpm:$mod";
		    }
		}
	    }
	}
	
	# deal with the capstone
	push @auto, "$vendor-$service-capstone-$major-$minor.$arch.rpm:$mod" 
	    if ($found);
    }

    # LIST needs to be local 
    if (not (open(LIST, "$dir/$packing_list.$listsuffix") or
	open(LIST, "$dir/$packing_list"))) {
        print "WARNING: no $dir/$packing_list\n";
	$EXITCODE = 1;
	return @auto;
    }

    # check for any other rpms
    if (opendir(RPMS, "$dir/$RPMS")) {
    	while ($file = readdir(RPMS)) {
		next if $file =~ /^\.\.?$/;
		next if -d $file;
		$file =~ /^(\S+)-\S+-\S+.\S+.rpm$/;
		$files{bin}{$1} = $file;
    	}
    	closedir(RPMS);
    }

    # check for source rpms
    if (opendir(RPMS, "$dir/$SRPMS")) {
    	while ($file = readdir(RPMS)) {
		next if $file =~ /^\.\.?$/;
		next if -d $file;
		$file =~ /^(\S+)-\S+-\S+.\S+.rpm$/;
		$files{src}{$1} = $file;
    	}
    	closedir(RPMS);
    }

    while (<LIST>) {
      if (m/^module: ([^:]+)(?::([^:]+)(?::(\S*))?)?/i) {
	my $modname = $1;
	chomp $modname;
	$QUIET || print "begin module: $modname\n"; 
	my @tmp = flatten_module("$builddir/$modname", $builddir);
	push @list, @tmp if defined(@tmp);
	$QUIET || print "end module: $modname\n";
      } elsif (/^\s*SRPM:\s+(\S+)/) {
	my $srpm = $1;
	if (/:(\S+)/) {
	  $mod = $1;
	}
	if ($srpm =~ /\.rpm$/) {
	  push @list, "$srpm:$mod";
	} elsif ($files{src}{$srpm}) {
	  push @list, "$files{src}{$srpm}:$mod";
	} else {
	  $QUIET || print "WARNING: can't find $srpm version!\n";
	}
      } elsif (/^\s*RPM:\s+(\S+)/) {
	my $rpm = $1;
	if (/:(\S+)/) {
	  # module specified in packing_list
	  $mod = $1;
	} 
	next if $rpm =~ /^$vendor-$service-(?:locale\-[^\-]+|ui|glue|capstone)$/;
	if ($rpm =~ /\.rpm$/) {
	  push @list, "$rpm:$mod";
	} elsif ($files{bin}{$rpm}) {
	  push @list, "$files{bin}{$rpm}:$mod";
	} else {
	  $QUIET || print "WARNING: can't find $rpm version!\n";
	}
      } elsif (! /^[\#\n]/) {
	$QUIET || print "WARNING: unknown line or version: $_\n";
      }
    }
    push @list, @auto;
    return @list;
}

sub products
{
	# assume product template names of form \d+[^\.]*\.tmpl
	# also assume there could be a dir name prepended
	($a =~ /(\d+)[^\.]*\.tmpl$/)[0] <=> ($b =~ /(\d+)[^\.]*\.tmpl$/)[0];
}

# need to sort the product numbers to make sure the base gets built
# up first otherwise release_specs will be missing lots of modules
@templates = sort products @templates;

if (! $BUILD_DIR) {
  $QUIET || print "Enter CVS directory: ";
  $BUILD_DIR = <STDIN>;
  chomp($BUILD_DIR);
}

if ($BUILD_DIR =~ /~(\w+)/) {
    my $dir = (getpwnam($1))[7];
    die "can't find ~$1!\n" unless $dir;
    $BUILD_DIR =~ s/~\w+/$dir/g;
} elsif ($BUILD_DIR =~ /~/) {
    $BUILD_DIR =~ s/~/$ENV{HOME}/g;
}

# build the base list first then for additional templates
# add what is needed to the list and output it's spec file
# base list starts out empty if --process-all arg is give
my @base = $PROCESS_ALL ? () : flatten_module('.', $BUILD_DIR, $listsuffix);

for (my $i = 0; $i <= $#templates; $i++) {
	open(TMPL,  $templates[$i]) or die "Can't open $templates[$i]!\n";
	
	$templates[$i] =~ /(.+[^\.]*)\.tmpl$/;
	open(OUT,  ">$outfile.$1") or die "Can't create $outfile.$1!\n";

	my @files = @base;

	# handle special case of base product, where the list is already built
	# if the --process-all argument it will assume that the release_spec
	# should not be a composite of all available packin_list files
	# but instead each tmpl packing_list part should be treated as a
	# a complete release_spec
	if ($PROCESS_ALL || $i > 0)
	{
		push @files, flatten_module('.', $BUILD_DIR, $1); 
	}
		
	while (<TMPL>) {
	  if (/^\[CORE_RPMS\]/) {
	    foreach my $fileline (@files) {
	      #$fileline =~ /^(.+):(.*\/+)*([^\/]+)$/;
	      $fileline =~ /^(.+):(.+)/;
	      my $rpm = $1;
	      my $section = $2;
	      printf OUT "%-55s", "$rpm";
	      print  OUT  ":$section\n";
	      #print OUT "$fileline\n"
	    }
	  } else {
	    print OUT $_;
	  }
	}
	
	close TMPL;
	close OUT;
}

exit $EXITCODE;


