#!/usr/bin/perl -wT --

#
#
# G N O K I I
#
# A Linux/Unix toolset and driver for the mobile phones.
#
# This file is part of gnokii.
#
# Gnokii is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Gnokii is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gnokii; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# Copyright (C) 2007-2008   Jari Turkia
#
# Nightly build monitoring utility.
#
#

use MIME::Lite;
use Date::Format;
use strict;
use utf8;

my $buildDir = $ENV {HOME}."/httpdocs/gnokii";
my $recipients = "-missing-";
my @ignoredDirs = ();
my @dirs = ("Fedora10", "RHEL5", "SuSE11.0", "SuSE11.1", "Windows/Win32", "Windows/Win64");

# Avoid warnings due to taint-mode
$ENV {"PATH"} = "/bin:/sbin:/usr/bin";

#
# Functions
#

#
# CheckDir
#
# Check a single directory for build success.
# IN:
# - The directory to be checked
# - Reference to files-array, if any attachments will be made
#
# OUT:
# - 0 for success, 1 for failure
#

sub CheckDir ($\@)
{
	my ($dirToCheck, $files) = @_;

	# Confirm that the directory does exist
	if (! -e $dirToCheck || ! -d $dirToCheck) {
		# Return a failure
		return 1;
	}

	# Gather all possible fail-logs.
	# Example files
	# fail-0.6.20cvs-20071021.log
	# BuildLog-0.6.20cvs-20071021.html
	opendir (DIR, $dirToCheck) or
		die "Cannot read dirToCheck. $!";
	my @files = grep { -f "$dirToCheck/$_" } readdir (DIR);
	closedir (DIR);

	# Check for failures
	my @fails = grep { /^fail-/ } @files;
	my @buildLogs = grep { /^BuildLog-/ } @files;

	# If no failures found but buildLogs are, investigate further.
	if ($#fails < 0 && $#buildLogs == 0) {
		# Check buildLog version
		my $buildLogVersion = "";
		if ($buildLogs [0] =~ /^BuildLog-([0-9.]+[^-]*-\d+)/) {
			$buildLogVersion = $1;
		}

		# Check compiled version
		my $compiledVersion = "";
		foreach (@files) {
			if (/^gnokii-([0-9.]+[^-]*-\d+)/) {
				$compiledVersion = $1;
				last;
			}
		}

		if ($buildLogVersion ne $compiledVersion) {
			@fails = @buildLogs;
		}
	}

	return 0 if ($#fails < 0);

	# Store failure files
	my $dirName = $dirToCheck;
	$dirName =~ s:^.*/::;

	# Store failure files to be attached into a message
	foreach my $aFail (@fails) {
		# Change .log into .txt
		my $failName = $aFail;
		$failName =~ s/\.log/.txt/;

		push (@$files, "$dirToCheck/$aFail");
		push (@$files, "$dirName-$failName");
	}

	return 1;
}

#
# Begin script
#

	# Today's date
	my @lt = localtime (time);
	my $now = strftime ("%e.%L.%Y", @lt);

	# Prepare MIME-mail
	my $msg = MIME::Lite->new (
		"From"	=> "root",
		"To"	=> $recipients,
		"Subject"	=> "Gnokii compile report $now"
	);

	if ($#dirs == -1) {
		# Gather directories to be checked
		opendir (DIR, $buildDir) or
			die "Cannot read buildDir. $!";
		@dirs = sort (grep { !/^\./ && -d "$buildDir/$_" } readdir (DIR));
		closedir (DIR);
	}

	# Iterate directories
	my $checkCnt = 1 + $#dirs;
	my $failCnt = 0;
	my @files;
	my $msgBody = qq{ Gnokii CVS nightly build report for $now. };
	$msgBody .= "\n\n";
	
	foreach my $aDir (@dirs) {
		my $isIgnored = 0;
		foreach my $anIgnoredDir (@ignoredDirs) {
			if ($aDir eq $anIgnoredDir) {
				$isIgnored = 1;
				--$checkCnt;
				last;
			}
		}
		next if ($isIgnored);
print "Checking: $buildDir/$aDir\n";
		my $stat = CheckDir ("$buildDir/$aDir", @files);

		my $mStr = "";
		if (-e "$buildDir/$aDir" && -d "$buildDir/$aDir") {
			my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
				$atime, $mtime, $ctime, $blksize, $blocks) =
				stat ("$buildDir/$aDir");
			my @mLt = localtime ($mtime);
			$mStr = strftime ("%e.%L.%Y", @mLt);
		} else {
			$mStr = "never";
		}

		$msgBody .= sprintf ("%-14s compiled %10s: ", $aDir, $mStr);
		
		if ($now ne $mStr) {
			++$failCnt;
			
			$msgBody .= "not compiled!\n";
#print "$aDir not compiled!\n";
		} elsif ($stat) {		
#print "$aDir failed!\n";
			++$failCnt;
			
			$msgBody .= "failed!\n";
		} else {
			$msgBody .= "Ok\n";
		}
	}
	$msgBody .= "\n Status: $failCnt out of $checkCnt failed.\n";

	# Send report if there is a reason to.
	if ($failCnt) {
		$msg->data ($msgBody);
	
		# Attach all failures to a message
		while (@files) {
			my $filePath = shift (@files);
			my $fileName = shift (@files);
#			my $fileName = pop (@files);
#			my $filePath = pop (@files);
			my $type = "text/plain";
			$type = "text/html" if ($filePath =~ /\.html$/);
#warn "Attaching $fileName ($type)";

			$msg->attach ("Type"		=> $type,
					"Path"		=> $filePath,
					"Filename"	=> $fileName,
					"Disposition"	=> "attachment"
			);
		}
	
		$msg->send ();
		
		exit (1);
	}
	
	exit (0);
