#! /tools/bin/perl

########################################################################
#### Used to execute commands
########################################################################

sub ssh_pipe
{
my $cmd=shift ;

open (G, "$cmd 2>&1 |") || choke("Can't execute $cmd ");
while (<G>) {
	print $_ . "<br> \n" unless (/^Host/);
} # End of while
} # End of ssh_pipe

########################################################################
#### Used to execute commands
########################################################################

sub uSystem
{
my($cmd) = shift(@_);
my($out) = system($cmd);

if ($out != 0) {
	&choke ( "***ERROR: executing $cmd $out \n");
	exit 1;
} # End of if
return;
} # End of uSystem

#########################################################################
#### Used to print out errors if something fails
#########################################################################

sub choke {
my ($reason)=shift;
my $user=shift;

print "<pre> A fatal error has occured:<br>";
print $reason;
print "</pre>";
open (FILE,">>/usr/www/push/var/push20_error_log");
print FILE "choking: $reason for $user\n";
close (FILE);
exit 0;
} # End of choke

###########################################################################
#### Used to get machines
###########################################################################

sub get_machines
{
my $type=shift;
my $location=shift;
my $sth;
my $machine;
my @Machines;

my $query = " select machineid from $type"."_machines where location=\'${location}\' order by machineid";
$sth= $dbh->prepare(qq{ $query } ) || &choke($sth->errstr);
$sth->execute() || &choke ($sth->errstr);
while ($machine= $sth->fetchrow_array()) {
	push(@Machines,$machine);
} # End of while
$sth->finish(); #cleanup
return (@Machines);
} # End of get_machine

########################################################################
#### Used to clear the cache on any target when php is pushed
########################################################################

sub clear_cache
{
my $target=shift;
my $ua= new LWP::UserAgent;
my $request;

print "<b>Clearing cache for $target</b>.<br>";
my ($url)='http://' . ${target} . '.epinions.com/priv/clear_cache.html';
$ua->from("walt\@epinions.com");
$ua->agent("Mozilla/4.6 [en] (X11; I; Linux 2.2.5-15 i686)");

print "Getting $url.<br><br>";
$request = new HTTP::Request('GET', $url);
$request->authorization_basic('federated','amalgamated');
my ($result)=$ua->request($request);
if ($result->is_success) {
        print "Successfully cleared the cache for $target.<br><br>";
} else {
        print "Clearing cache <b>failed:</b><br>";
        print "$target is probably not up <br><br>";
} # End of if
undef ($ua);
undef ($request);
} # End of clear_cache

########################################################################
#### This is useful for doing any kind of loop through an array
########################################################################

sub loop_it
{
$array=shift;
$subroutine=shift;
$arg1=shift;
$arg2=shift;
$arg3=shift;

foreach $temp (@{$array}) {
	&$subroutine($temp) if ((! $arg1) && (! $arg2) && (! $arg3));
	&$subroutine($temp,$arg1) if (($arg1) && (! $arg2) && (! $arg3));
	&$subroutine($temp,$arg1,$arg2) if (($arg1) && ($arg2) && (! $arg3));
	&$subroutine($temp,$arg1,$arg2,$arg3) if (($arg1) && ($arg2) && ($arg3));
} # End of foreach
} # End of loop_it

############################################################################
#### Can be used to restart any webserver or dal_server
############################################################################

sub restart_machine
{
my $machine=shift;
my $type=shift;

if ($type eq "dal") {
$cmd="/usr/www/push/scripts/restart_dal.pl $machine";
print "$cmd<br>";
&ssh_pipe($cmd);
} elsif ($type eq "www") {
$cmd="/usr/www/push/scripts/restart_www.pl $machine";
print "$cmd<br>";
&ssh_pipe($cmd);
} # End of if
} # End of restart_machine

############################################################################
#### Used to convert time on a statted file
############################################################################

sub converttime
{
my $epoch=shift;
my ($sec,$min,$hour,$dom,$mon,$year,$wday,$yday,$isdst)=localtime($epoch);
my $t=sprintf("%02d/%02d/%04d %02d:%02d:%02d\n",$mon+1,$dom,$year+1900,$hour,$min,$sec);
return $t;
} # End of converttime

############################################################################
#### Used to lock things when a push is going on
############################################################################

sub lock
{
if (!$locked) {
	open(LOCK,">/usr/www/push/tmp.lock");
	flock(LOCK,2);
	print LOCK $$."\n";
	$locked=1;
} # End of if
} # End of lock

############################################################################
#### Used to unlock things when a push is not going on
############################################################################

sub unlock
{
if ($locked) {
	close(LOCK);
} # End of if
$locked=0;
} # End of unlock

############################################################################
#### Used to compare cvs versions
############################################################################

sub compare_cvs
{
my $server_version = shift;
my $cvs_version = shift;

if ( $server_version eq "deleted") {
	$server_version =  "<font color='red'><b>deleted</b><br>Needs<br>Update</font>";
	return $server_version ;
} # End of if
if ( $server_version eq "n/a") {
	$server_version =  "<font color='green'><b>n/a</b></font>";
	return $server_version ;
} # End of if

if (! defined $server_version ) {
	$server_version =  "<font color='green'><b>New File</b></font><font color='red'><br>Needs<br>Update</font>";
	#$server_version =  "<font color='green'><b>Never pushed via <br>push tool</b></font>";
	return $server_version ;
} # End of if

my $orig_server_version = $server_version ;
my $orig_cvs_version = $cvs_version ;

# turn cvs' numbering scheme into real numbers to eval
$server_version=~s/^1//;
$cvs_version=~s/^1//;
if (length($server_version)  < length($cvs_version)){
	my $ctemp = length($cvs_version) - length($server_version);
	$server_version= ($server_version / (10 ** $ctemp));
} # End of if

if (($cvs_version > $server_version ) and ($server_version ne "n/a")){
	$server_version = $orig_server_version . "<br><font color='red'<br>Needs<br>Update</font>";
} elsif (($orig_server_version eq "n/a") and ($orig_cvs_version >= 1.1)) {
	$server_version =  "<font color='green'><b>New File</b></font><font color='red'><br>Needs<br>Update</font>";
}else {
	$server_version = $orig_server_version ;
} # End of if
return  $server_version ;
} # End of cvs_compare

############################################################################
#### Used to compare cvs versions
############################################################################

sub get_version
{
my $dbh=shift;
my $filepath=shift;
my $type=shift;
my $sth;

my $query = " select id,$type"."version from filepaths where path=\'${filepath}\' ";
print "<br>$query<br>";
$sth= $dbh->prepare(qq{ $query } ) || &choke($sth->errstr);
$sth->execute() || &choke ($sth->errstr);
my ($fileid,$version)=$sth->fetchrow_array();
return($fileid,$version);
} # End of get_version

#########################################################################
#### Does the actual performing of the push.
#########################################################################

sub perform_push
{
my $dbh=shift;
my $pusher=shift;
my $dest=shift;
my $type=shift;
my $q=shift;
my $web=shift;
my ($start_dir)=`pwd`;
my $comments;
my $commentid;
my $sth;
my $query;

print $q->start_html(-bgcolor => 'white') if (defined $q) ;
if ($web) {
	if ($dest eq 'stage'){
		$comments=$q->param('comments') ;
		if ($comments eq '') {
			$commentid = 1 ; # for "none"
			$comments = "<none>\n</COMMENT>";
		} else {
			$commentid = &addcomment ($comments);
			$comments .= "\n</COMMENT>";
		} # End of if
	} else {
		$commentid = 1; # autopush
	} # End of if
	$query = "select filepaths.id,filepaths.path,queue.version,filepaths.watch from filepaths,queue where queue.username='$pusher' and queue.type='$type' and filepaths.id=queue.filename and queue.dest='$dest'";
}else{
	$comments = "<none>\n</COMMENT>";
	$commentid = &addcomment("autopush for $pusher"); # autopush
	$query = "select filepaths.id,filepaths.path,queue.version,filepaths.watch from filepaths,queue where queue.type='$type' and filepaths.id=queue.filename and queue.dest='$dest'";
} # End of if

if ($web) {
	if (($q->param("dire_confirmation"))[0] ne "on") {
		#&choke("You didn't agree to the required terms and conditions.");
		print"You didn't agree to the required terms and conditions.";
		exit 1;
	} # End of if
	if (($q->param("conftime"))[0] < (time()-1200)) {
		#&choke("You took too long to click on the push button after displaying the confirmation page");
		print"You took too long to click on the push button after displaying the confirmation page";
		exit 1;
	} # End of if
} # End of if
print "<PRE>Beginning push... to $dest be especially alert for errors (which will be <b>bold</b>):\n";

########loop through cart#######################
if ($dest eq "www") {
#	&need_to_qa($pusher);
} # End of if
$sth= $dbh->prepare (qq { $query } ) || die ($sth->errstr);
$sth->execute() || &leave ($sth->errstr);
while (my ($fileid,$filename,$version,$watch) = $sth->fetchrow_array()) {
	if (! $web) {
		$pusher=&getpusher($dbh,$fileid,$type,$dest);
	} # End of if
	&check_rev($fileid,$version,$dest);
	&push_files($filename,$version,$dest);
	&pushhistory($dbh,$fileid,$version,$pusher,time(),$dest,$commentid);
# FFFFFFFFFF
	if ($dest eq "stage") {
		&move_to_push_cart($dbh,$filename,$fileid,$version,$pusher,$dest,$type);
	} elsif ($dest eq "www") {
		&remove_from_push_cart($dbh,$filename,$fileid,$dest,$pusher,$version);
		&remove_from_shopping_cart($dbh,$filename,$dest,$pusher,$type);
#		&send_out_summary;
	} # End of if
#	&watch_mail($watch,$fileid,$version,$dest,$pusher) if ($watch);
	&update_db_version($dbh,$fileid,$version,$dest);
} # End of while
#&clear_cache($dest);
&back_to_top($script,$q);
#####################

} # End of perform_push

#########################################################################
#### Checks to make sure ALL files have been QA'd 
#########################################################################

sub need_to_qa
{
my $pusher=shift;
my $dest="www";
my $query;

$query = "select queue.selfqa,queue.peerqa from queue where queue.username='$pusher' and queue.type='cart' and queue.dest='$dest'";
$sth= $dbh->prepare (qq { $query } ) || die ($sth->errstr);
$sth->execute() || &leave ($sth->errstr);
while (my ($selfqa,$peerqa) = $sth->fetchrow_array()) {
	if (($selfqa eq "0") or ($peerqa eq "0")) {
		print "<br>SELF-$selfqa PEER-$peerqa<br>";
		print "<br><font size=+2 color=red>Things are NOT QA'd.....push has failed please QA....<br><br><br></font>";
		print "<a href=\"/qa20.cgi/?func=check_qa\">QA Page</a>\n";
		exit 1;
	} else {
		print "<br> Things are QA'd.....proceeding....<br>";
	} # End of if
} # End of while
} # End of need_to_qa

#########################################################################
#### Does the actual copying of files.
#########################################################################

sub push_files
{
my $file=shift;
my $rev=shift;
my $dest=shift;
my $destdir;
my $source_dir="/usr/www/push/qa_branch";
my $version_dir="/o/prod/current/www_temp/";

print "DUDHDH<br>";
if ($dest eq "www") {
#	$destdir="bd\@e2www:/usr/$file";
#	$cmd="cd $source_dir; scp -C $file $destdir";
#	print "$cmd <br>";
#	&uSystem($cmd);
#	$destdir="bd\@www21:/o/prod/current/www_2_1_3";
} elsif ($dest eq "stage") {
	$destdir="bd\@stage1:$version_dir".$file;
} # End of if
my $pos=rindex($file,"/");
my $dir=substr($file,0,$pos);
my $cmd="/tools/bin/ssh bd\@stage1 \"cd $version_dir; mkdir -p $dir \" ";
print "$cmd <br>";
&uSystem($cmd);
$cmd="cd $source_dir; scp -C $file $destdir";
print "$cmd <br>";
&uSystem($cmd);
} # End of push_files

#########################################################################
#### Does the actual copying of files.
#########################################################################

sub check_rev
{
my $fileid=shift;
my $rev=shift;
my $dest=shift;
my $revert=shift;

$query = "select $dest"."version from filepaths where id='$fileid'";
$sth= $dbh->prepare (qq { $query } ) || die ($sth->errstr);
$sth->execute() || &leave ($sth->errstr);
my ($db_version) = $sth->fetchrow_array();
print "Cart version - $rev DB version - $db_version<br>";
if (! defined $db_version) {
	print "Adding the new revision $rev to $dest....<br>";
} else {
	my ($trash,$cut_rev)=split(/\./,$rev);
	my ($trash2,$cut_db_version)=split(/\./,$db_version);
	if ($cut_rev eq $cut_db_version) {
		print "The two versions are the same....<br>";
	} elsif (($cut_rev < $cut_db_version) and (! $revert)) {
		print "Trying to push an older version and you are not reverting.....<br>";
	} elsif (($cut_rev < $cut_db_version) and ($revert)) {
		print "Reverting from $db_version back to $rev on $dest....<br>";
	} elsif (($cut_rev > $cut_db_version) and ($revert)) {
		print "Trying to revert a newer version.....<br>";
	} elsif (($cut_rev > $cut_db_version) and (! $revert)) {
		print "Replacing $db_version with $rev on $dest....<br>";
	} # End of if
} # End of if
} # End of check_rev

#########################################################################
#### Moves the files from the stage cart to the push cart
#########################################################################

sub move_to_push_cart
{
my $dbh=shift;
my $filename=shift;
my $fileid=shift;
my $version=shift;
my $pusher=shift;
my $dest=shift;
my $type=shift;

&add_shopping_cart($dbh,$fileid,$version,"www",$pusher,"push","0","0");
&remove_from_shopping_cart($dbh,$filename,$dest,$pusher,$type);
} # End of move_to_push_cart

#########################################################################
#### Moves the files from the stage cart to the push cart
#########################################################################

sub update_db_version
{
my $dbh=shift;
my $fileid=shift;
my $version=shift;
my $dest=shift;
my $update;

if ($version eq "NULL") {
	$update = "update filepaths set $dest"."version=NULL where id='$fileid' ";
} else {
	$update = "update filepaths set $dest"."version='$version' where id='$fileid' ";
} # End of if
print "<br>UP-$update<br>";
$sth= $dbh->prepare (qq { $update } ) || die ($sth->errstr);
$sth->execute() || &leave ($sth->errstr);
} # End of update_db_version

#########################################################################
#### Moves the files from the stage cart to the push cart
#########################################################################

sub watch_mail
{
my $watchlist=shift;
my $fileid=shift;
my $version=shift;
my $dest=shift;
my $uid=shift;
$watchlist="walt,bd";
#my $people='dane@epinions-inc.com,cyndis@epinions-inc.com,walt@epinions-inc.com,davek@epinions-inc.com';
if ($watchlist=~ m/,/) {
	$people=~ s|,|\@epinions-inc.com,|;
} else {
	$people="$watchlist\@epinions-inc.com";
} # End of if
my $people="$watchlist\@epinions-inc.com";
#my $cc='Cc: wmiller@epinions-inc.com';
my $cc='Cc: toryn888@yahoo.com';
my $sendmailexec="/usr/lib/sendmail -t";

print "<br>PEOPLE-$people<br>";
exit 1;
my $query = "select users.userid,filepaths.path,filepaths.$dest" . "version from filepaths,users where users.id='$uid' and filepaths.id='$fileid'";
$sth= $dbh->prepare (qq { $query } ) || die ($sth->errstr);
$sth->execute() || &leave ($sth->errstr);
my ($person,$filename,$db_version) = $sth->fetchrow_array();
open (M, "| $sendmailexec ") || choke ("sendmail failed to launch correctly abort
ing restart of");
print "Someone is watching you......<br>";
print M "To: $watchlist\n${cc}\nSubject: Look out......\n\n";
print M "Warning!!!!!! Warning !!!!!!!\n";
print M "$person just replaced $filename version $db_version with $version on $dest.\n";
print M "Click below for the diff.\n";
close (M);
} # End of watch_mail

#########################################################################
#### Moves the files from the stage cart to the push cart
#########################################################################

sub staged
{
print "<br><hr width=66% align=left>\n";
print "<A NAME=\"staged\"><br>\n";
print "<font size=+2 color=blue>Currently staged files:<br><br></font>";
my $query = "select filepaths.path,queue.version,filepaths.wwwversion,users.userid from filepaths,queue,users where queue.type='push' and filepaths.id=queue.filename and queue.username=users.id";
$sth= $dbh->prepare (qq { $query } ) || die ($sth->errstr);
$sth->execute() || &leave ($sth->errstr);
if ($sth->rows) {
	print "<TABLE width=100%>\n<tr><td><b>Filename</b></td><td><b>Version</b></td><td><b>Pusher</b></td><td></td><td></td></tr>";
	while (my ($file,$version,$www_version,$users) = $sth->fetchrow_array()) {
		$www_version="1.1" if (! $www_version);
		my $pos=rindex($file,"/");
		my $dir=substr($file,0,$pos);
		my $filename=substr($file,$pos+1);
		print "<tr><td align=\"left\">$file</td><td><center>$version $wwwversion</center></td><td><center>$users</td>";
		print "<td><A HREF=\"http://bonsai.epinions.com/cvsview2.cgi?root=&subdir=$dir&files=$filename&command=DIRECTORY\">All Diffs</A></td>";
		print "<td><A HREF=\"http://bonsai.epinions.com/cvsview2.cgi?diff_mode=context&whitespace_mode=show&root=/export&subdir=$dir&command=DIFF_FRAMESET&root=/export&file=$filename&rev1=$version&rev2=$www_version\">CVS Diffs</A></td></tr>";
	} # End of while
	print "</TABLE>\n";
} else {
	print "Nothing, it's empty.\n";
} # End of if
} # End of staged

#########################################################################
#### Moves the files from the stage cart to the push cart
#########################################################################

sub remove_from_push_cart
{
my $dbh=shift;
my $filename=shift;
my $fileid=shift;
my $dest=shift;
my $pusher=shift;
my $version=shift;
my $type="push";
my $sth;

my $query = " select version from queue where type='$type' and filename='$fileid' ";
$sth= $dbh->prepare(qq{ $query } ) || &choke($sth->errstr);
$sth->execute() || &choke ($sth->errstr);
my ($push_version)= $sth->fetchrow_array();
if ($version eq $push_version) {
	print "Removing $filename from the staged cart.....<br>";
	&remove_from_shopping_cart($dbh,$filename,$dest,$pusher,$type);
} # End of if
} # End of remove_from_push_cart

#########################################################################
#### Moves the files from the stage cart to the push cart
#########################################################################

sub getpusher
{
my $dbh=shift;
my $fileid=shift;
my $type=shift;
my $dest=shift;
my $sth;

my $query = " select username from queue where type='$type' and filename='$fileid' and dest='$dest' ";
$sth= $dbh->prepare(qq{ $query } ) || &choke($sth->errstr);
$sth->execute() || &choke ($sth->errstr);
my ($pusher)= $sth->fetchrow_array();
return($pusher);
} # End of getpusher

#########################################################################
#### Moves the files from the stage cart to the push cart
#########################################################################

sub mail_template
{
my $people=shift;
my $cc=shift;
my $subject=shift;
my $content=shift;
my $sendmailexec="/usr/lib/sendmail -t";

open (M, "| $sendmailexec ");
print "Sending mail ..<br>";
print M "To: $people\n${cc}\nSubject: $subject\n\n";
print M "$content";
close (M);
} # End of mail_template

#########################################################################
#### This checks to see if the user is in the database.
#########################################################################

sub check_user
{
my $dbh=shift;
my $user=shift;
my $sth;

my $query = " select id from users where userid=\'${user}\' ";
$sth= $dbh->prepare(qq{ $query } ) || &choke($sth->errstr);
$sth->execute() || &choke ($sth->errstr);
($userid)=$sth->fetchrow_array();
$sth->finish;
if (! $userid) {
        $sth= $dbh->prepare (qq { insert into users values (NULL,'$user', NULL) } ) || die ($sth->errstr);
        $sth->execute() || &leave ($sth->errstr);
        $sth->finish;
} # End of if
return($userid);
} # End of check_user

#########################################################################
#### This finds the size of an array.
#########################################################################

sub array_size
{
my $array=shift;

my $size = $#{$array} + 1 ;
$size > 15 ? $size=15 : $size ;
return($size);
} # End of array_size

1;
