#!/usr/bin/env perl

$tagsets = "tagsets";

$cvs  = 0;
$diff = 0;
$settag = 0;
$deltag = 0;
$setbranch = 0;
$setdevtag = 0;
$module = "";
@tARGV = ();
for (; @ARGV > 0; ) {
    if ($ARGV[0] eq "-diff") {
	$diff = 1;
        shift; next;
    }
    if ($ARGV[0] eq "-tag") {
	$settag = 1;
        shift; next;
    }
    if ($ARGV[0] eq "-branch") {
	$setbranch = 1;
        shift; next;
    }
    if ($ARGV[0] eq "-devtag") {
	$setdevtag = 1;
        shift; next;
    }
    if ($ARGV[0] eq "-deltag") {
	$deltag = 1;
        shift; next;
    }
    if ($ARGV[0] eq "-cvs") {
	$cvs = 1;
        shift; next;
    }
    if ($ARGV[0] eq "-module") {
        shift; 
	$module = $ARGV[0];
        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 ();

if ($diff) { &difflist (); }
if ($settag) { &settags (); }

&package_distribution ();

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

sub difflist {

    for ($i = 0; $i < @cvsname; $i++) {
	# the base component cannot be rdiffed
	print STDERR "--- $cvsname[$i] ---\n";
	if ($cvsname[$i] eq "base") { next; }
	if ($tag[$i] eq "") {
	    &vsystem ("cvs -q rdiff -s -r HEAD $cvsname[$i]");
	} else {
	    &vsystem ("cvs -q rdiff -s -r $tag[$i] $cvsname[$i]");
	}	
	print STDERR "\n\n";
    }
    exit 0;
}

sub settags {
    print STDERR "setting tags\n";
    for ($i = 0; $i < @cvsname; $i++) {
	if (($module ne "") && ($module ne $cvsname[$i])) { next; }
	($do_tag, $do_build, $do_package, $do_update) = $mode[$i] =~ m|(\S)(\S)(\S)(\S)|;
	if ($do_tag eq "N") { 
	    push @remind, $cvsname[$i];
	    next; 
	}
	if ($branchtag[$i] eq "") { die "branch tag missing for $cvsname[$i]\n"; }
	if ($branchver[$i] eq "") { die "branch tag version missing\n"; }
	$tag = "$branchtag[$i]$branchver[$i]";
	if ($setbranch) { 
	    &vsystem ("cvs -q rtag -b $branchtag[$i] $cvsname[$i]");
	    next;
	} 
	if ($setdevtag) {
	    &vsystem ("cvs -q rtag $tag $cvsname[$i]");
	    next;
	}
	&vsystem ("cvs -q rtag -r $branchtag[$i] $tag $cvsname[$i]");
    }
    for ($i = 0; $i < @remind; $i++) {
	print STDERR "remember to set tag for $remind[$i] if needed\n";
    }
    exit 0;
}

sub package_distribution {
    # package distribution into a tarball
    mkdir $distribution;
    chdir $distribution;
    for ($i = 0; $i < @cvsname; $i++) {
	if (($module ne "") && ($module ne $cvsname[$i])) { next; }
	($do_tag, $do_build, $do_package, $do_update) = $mode[$i] =~ m|(\S)(\S)(\S)(\S)|;
	if ($do_package eq "N") { next; }
	if ($tag[$i] eq "HEAD") {
	    &vsystem ("cvs co $cvsname[$i]");
	    if ($status) { die "error running cvs"; }
	} else {
	    &vsystem ("cvs co -r $tag[$i] $cvsname[$i]");
	    if ($status) { die "error running cvs"; }
	}	
    }
    chdir "..";
    if ($cvs) { exit 0; }

    &vsystem ("rm -r `find $distribution -name CVS`");
    if (! -e tarballs) { mkdir "tarballs"; }
    &vsystem ("tar cvzf tarballs/$distribution.tgz  $distribution");
    if ($status) { die "error creating tarball\n"; }
    exit 0;
}

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 "module: $cvsname, branchtag: $branchtag, branchver: $branchver "; 
	print "tag: $do_tag, build: $do_build, package: $do_package, update: $do_update\n";

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

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;
}

