#!/usr/bin/env perl

$tagsets = "tagsets";

$version = "";
$clean = 0;
$rebuild = 0;
$optimize = 0;
$start = "";
$stop = "";

@tARGV = ();
for (; @ARGV > 0; ) {
    if ($ARGV[0] eq "-version") {
	$version = $ARGV[1];
        shift; shift; next;
    }
    if ($ARGV[0] eq "-clean") {
	$clean = 1;
        shift; next;
    }
    if ($ARGV[0] eq "-rebuild") {
	$rebuild = 1;
        shift; next;
    }
    if ($ARGV[0] eq "-optimize") {
	$optimize = 1;
        shift; next;
    }
    if ($ARGV[0] eq "-only") {
	$start = $ARGV[1];
	$stop = $ARGV[1];
        shift; shift; next;
    }
    if ($ARGV[0] eq "-start") {
	$stop = $ARGV[1];
        shift; shift; next;
    }
    if ($ARGV[0] eq "-stop") {
	$stop = $ARGV[1];
        shift; shift; next;
    }
    if ($ARGV[0] eq "-list") {
	&list_distributions ();
    }
    if ($ARGV[0] eq "-h")     { &usage (); }
    if ($ARGV[0] eq "-help")  { &usage (); }
    if ($ARGV[0] eq "--help") { &usage (); }
    @tARGV = (@tARGV, $ARGV[0]);
    shift;
}
@ARGV = @tARGV;

if ( @ARGV != 1) { &usage (); }

$distribution = $ARGV[0];
&load_distfile ();

&build_distribution ();
exit 0;

sub build_distribution {
    
    # use psconfig.sh to set needed build aliases

    # set the psconfig version:
    if ("$version" eq "") {
	$version = $ENV{'PSVERSION'};
    }
    if ("$version" eq "") {
	$version = "default";
    }

    $psconfigure = `csh psconfig.sh --psconfigure $version`;
    $psautogen   = `csh psconfig.sh --psautogen $version`;
    $psperlbuild = `csh psconfig.sh --psperlbuild $version`;

    print "psconfigure: $psconfigure\n";
    print "psautogen: $psautogen\n";
    print "psperlbuild: $psperlbuild\n";

    $psopts = "";
    if ($optimize) { $psopts = "$psopts --enable-optimize"; }

    $homedir = `pwd`; chomp $homedir;

    for ($i = 0; $i < @cvsname; $i++) {
	if (($start ne "") && ($start ne $cvsname[$i])) { next; }
	($do_tag, $do_build, $do_package, $do_update) = $mode[$i] =~ m|(\S)(\S)(\S)(\S)|;
	if ($do_build eq "N") { next; }

	$workdir = "../$cvsname[$i]";
	chdir $workdir;
	
	print "\n ***** building $cvsname[$i] ***** \n";

	# how do we build this component?
	# - autogen.sh : configure : make : make install
	# - configure : make : make install
	# - make : make install
	# - perl Build.PL : ./Build : ./Build install
 
	if (-e "Build.PL") {
	    print $PERL5LIB;

	    vsystem ("$psperlbuild");
	    if ($?) { &failure($cvsname[$i], "failure in perl Build.PL"); }

	    vsystem ("./Build");
	    if ($?) { &failure($cvsname[$i], "failure in Build"); }

	    vsystem ("./Build install");
	    if ($?) { &failure($cvsname[$i], "failure in Build install"); }
	    
	    next;
	}

	if ($rebuild && $clean) {
	    if (-e "configure") { unlink "Makefile"; }
	    if (-e "configure.ac" && -e "autogen.sh") { unlink "configure"; }
	}
	$rebuild_this = $rebuild;

	# set a local variable for this loop on rebuild;
	if (! -e "Makefile") { $rebuild_this = 1; }

	#  run autogen
	$skip_configure = 0;
	if ($rebuild_this && ! -e "configure" && -e "autogen.sh") {
	    $skip_configure = 1;
	    vsystem ("$psautogen $psopts");
	    if ($?) { &failure($cvsname[$i], "failure in psautogen"); }
	}

	if ($rebuild_this && -e "configure" && !$skip_configure) {
	    vsystem ("$psconfigure $psopts");
	    if ($?) { &failure($cvsname[$i], "failure in psconfigure"); }
	}

	if (! -e "Makefile") { &failure($cvsname[$i], "missing makefile"); }

	if ($clean) { 
	    vsystem ("make clean");
	    if ($?) { &failure($cvsname[$i], "failure in make clean"); }
	}

	vsystem ("make");
	if ($?) { &failure($cvsname[$i], "failure in make"); }

	vsystem ("make install");
	if ($?) { &failure($cvsname[$i], "failure in make install"); }

      success:
	chdir $homedir;
	if (($stop ne "") && ($stop eq $cvsname[$i])) { last; }
    }

    exit 0;
}

sub vsystem {
    print STDERR "@_\n";
    $status = system ("@_");
    $status;
}

sub list_distributions {
    vsystem ("ls $tagsets/*.dst");
    exit 2;
}

sub load_distfile {
    # open and read the distribution file
    # results go into @cvsname, @branchtag, @branchver, @mode
    $file = "$tagsets/$ARGV[0].dst";
    open (FILE, $file) || die "ERROR: can't open distribution file $file\n";
    @list = <FILE>;
    close (FILE);

    @mode = ();
    @cvsname = ();
    @branchtag = ();
    @branchver = ();

    foreach $line (@list) {
	chop $line;
	if ($line =~ m|^\s*$|) { next; }
	if ($line =~ m|^\s*\#|) { next; }

	($mode, $cvsname, $branchtag, $branchver) = split (" ", $line);
	
	if ($cvsname eq "") { die "missing module name\n"; }

	($do_tag, $do_build, $do_package, $do_update) = $mode =~ m|(\S)(\S)(\S)(\S)|;
	if (($do_tag ne "Y") && ($do_tag ne "N")) { die "invalid tag option $do_tag\n"; }
	if (($do_build ne "Y") && ($do_build ne "N")) { die "invalid tag option $do_build\n"; }
	if (($do_package ne "Y") && ($do_package ne "N")) { die "invalid tag option $do_package\n"; }
	if (($do_update ne "Y") && ($do_update ne "N")) { die "invalid tag option $do_update\n"; }
	
	print "tag: $do_tag, build: $do_build, package: $do_package, update: $do_update ";
	print "module: $cvsname, branchtag: $branchtag, branchver: $branchver \n"; 

	push @mode, $mode;
	push @cvsname, $cvsname;
	push @branchtag, $branchtag;
	push @branchver, $branchver;
    }
}

sub failure {
    die "problem building $_[0] : $_[1]\n";
}

sub usage {
    print STDERR "USAGE: mkdist -list\n";
    print STDERR "     : list valid distributions \n\n";
    print STDERR "USAGE: mkdist (distribution) [-cvs]\n";
    print STDERR "     : make a distribution tarball\n";
    print STDERR "     : -cvs  : only check out the cvs tree, don't make a tarball\n\n";
    print STDERR "USAGE: mkdist -diff (group) (version)\n";
    print STDERR "     : show the difference between the distribution and current tree\n\n";
    exit 2;
}

