#!/usr/bin/perl -w
#
# Project Builder main application
#
# $Id$
#
# Copyright B. Cornec 2007
# Provided under the GPL v2

# Syntax: pb [-p project] <action> [<params>...]

use strict;
use Switch;
use Getopt::Std;
use Data::Dumper;
use English;
use Time::localtime qw(localtime);
use POSIX qw(strftime);

use lib qw (lib etc);
use vars qw (%defpkgdir %extpkgdir %version);
use common qw (env_init);
use pb qw (defpkgdir extpkgdir version pb_init);
use distro qw (distro_init);
use cms;

my %opts;					# CLI Options
my $action;					# action to realize
my $test = "FALSE";
my $option = "";
my @pkgs;

getopts('p:t',\%opts);

# Handles project name if any
if (defined $opts{'p'}) {
	$ENV{'PBPROJ'} = env_init($opts{'p'});
} else {
	$ENV{'PBPROJ'} = env_init();
}
# Handles test option
if (defined $opts{'t'}) {
	$test = "TRUE";
	# Works only for SVN
	$option = "-r BASE";
}

# Get Action
$action = shift @ARGV;
die "Syntax: pb [-p project] <action> [<params>...]" if (not defined $action);

print "Project $ENV{'PBPROJ'}\n";
#print "Action: $action - ARGV:".Dumper(\@ARGV);

# Act depending on action
if ($action =~ /^cms2build$/) {
	print "Action: cms2build\n";
	# Get packages list
	if (not defined $ARGV[0]) {
		@pkgs = keys %defpkgdir;
	} elsif ($ARGV[0] =~ /^all$/) {
		@pkgs = keys %defpkgdir;
		push(@pkgs, keys %extpkgdir);
	} else {
		@pkgs = @ARGV;
	}
	print "Packages:\n";
	print Dumper(@pkgs);
	cms_init();

	foreach my $p (@pkgs) {

		my $v;

		if (-f "$ENV{'PBROOT'}/$p/VERSION") {
			open(V,"$ENV{'PBROOT'}/$p/VERSION") || die "Unable to open $ENV{'PBROOT'}/$p/VERSION";
			$v = <V>;
			chomp($v);
			close(V);
		} else {
			$v = $ENV{'PBVER'};
		}

		my $tag;

		if (-f "$ENV{'PBROOT'}/$p/TAG") {
			open(T,"$ENV{'PBROOT'}/$p/TAG") || die "Unable to open $ENV{'PBROOT'}/$p/TAG";
			$tag = <T>;
			chomp($tag);
			close(T);
		} else {
			$tag = $ENV{'PBTAG'};
		}
		print "Management of $p $v-$tag (rev $ENV{'PBREVISION'})\n";
		die "Unable to get env var PBDESTDIR" if (not defined $ENV{'PBDESTDIR'});
		# Clean up dest if necessary
		my $dest = "$ENV{'PBDESTDIR'}/$p-$v";
		pbrm_rf($dest) if (-d $dest);

		# Export CMS tree for the concerned package to dest
		# And generate some additional files
		$OUTPUT_AUTOFLUSH=1;
		print "$ENV{'PBCMSEXP'} of $p...";
		# computes in which dir we have to work
		my $dir = $defpkgdir{$p};
		$dir = $extpkgdir{$p} if (not defined $dir);
		system("$ENV{'PBCMSEXP'} $option $ENV{'PBROOT'}/$dir $dest 1>/dev/null");
		if ($? == -1) {
			print "failed to execute: $!\n";
		} elsif ($? & 127) {
			printf "child died with signal %d, %s coredump\n", ($? & 127),  ($? & 128) ? 'with' : 'without';
		} else {
			print " Done under $dest\n";
		}

		# Creates a REVISION file
		open(R,"> $dest/REVISION") || die "Unable to create $dest/REVISION";
		print R "$ENV{'PBREVISION'}\n";
		close(R);

		# Extract cms log history and store it
		system("$ENV{'PBCMSLOG'} $option $ENV{'PBROOT'}/$dir > $dest/$ENV{'PBCMSLOGFILE'}");
		print "$ENV{'PBCMSLOG'} of $p...";
		if ($? == -1) {
			print "failed to execute: $!\n";
		} elsif ($? & 127) {
			printf "child died with signal %d, %s coredump\n", ($? & 127),  ($? & 128) ? 'with' : 'without';
		} else {
			print " OK\n";
		}
		my @date=(localtime->sec(), localtime->min(), localtime->hour(), localtime->mday(), localtime->mon(), localtime->year(), localtime->wday(), localtime->yday(), localtime->isdst());
		my $pbdate = strftime("%Y-%m-%d", @date);

		open(D,"$ENV{'PBCONF'}/DISTROS") || die "Unable to find $ENV{'PBCONF'}/DISTROS\n";
		while (<D>) {
			my $d = $_;
			my ($dir,$ver) = split(/_/,$d);
			chomp($ver);
			print "Generating build files for $dir ($ver)\n";
			my ($ddir, $dver, $dfam, $dtype, $dsuf) = distro_init($dir,$ver);
			#print Dumper($ddir, $dver, $dfam, $dtype, $dsuf);
			#print "Filtering DDD => $pbdate, TTT => $tag, RRR => $tag$dsuf, VVV => $v\n";

			# Filter build files from the most precise up to the less
			# Filter all files found, keeping the name, and generating in dest
			my @bfiles;
			#print "dir: $ENV{'PBCONF'}/$p\n";
			if (-d "$ENV{'PBCONF'}/$p/$ddir-$dver") {
				opendir(BDIR,"$ENV{'PBCONF'}/$p/$ddir-$dver" || die "Unable to open dir $ENV{'PBCONF'}/$p/$ddir-$dver: $!");
				@bfiles = grep { ! /^\./ && -f "$ENV{'PBCONF'}/$p/$ddir-$dver/$_" } readdir(BDIR);
				closedir(BDIR);
			} elsif (-d "$ENV{'PBCONF'}/$p/$ddir") {
				opendir(BDIR,"$ENV{'PBCONF'}/$p/$ddir" || die "Unable to open dir $ENV{'PBCONF'}/$p/$ddir: $!");
				@bfiles = grep { ! /^\./ && -f "$ENV{'PBCONF'}/$p/$ddir/$_" } readdir(BDIR);
				closedir(BDIR);
			} elsif (-d "$ENV{'PBCONF'}/$p/$dfam") {
				opendir(BDIR,"$ENV{'PBCONF'}/$p/$dfam" || die "Unable to open dir $ENV{'PBCONF'}/$p/$dfam: $!");
				@bfiles = grep { ! /^\./ && -f "$ENV{'PBCONF'}/$p/$dfam/$_" } readdir(BDIR);
				closedir(BDIR);
			} elsif (-d "$ENV{'PBCONF'}/$p/$dtype") {
				opendir(BDIR,"$ENV{'PBCONF'}/$p/$dtype" || die "Unable to open dir $ENV{'PBCONF'}/$p/$dtype: $!");
				@bfiles = grep { ! /^\./ && -f "$ENV{'PBCONF'}/$p/$dtype/$_" } readdir(BDIR);
				closedir(BDIR);
			} else {
				print "No Build Files found for $ddir-$dver\n";
				next;
			}

		}
		close(D);

	}
} else {
	print "'$action' is not available\n";
	print "Available actions are:\n";
	print "    cms2build\n";
}
