#! /usr/bin/perl -w
##**************************************************************
##
## Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
## University of Wisconsin-Madison, WI.
## 
## Licensed under the Apache License, Version 2.0 (the "License"); you
## may not use this file except in compliance with the License.  You may
## obtain a copy of the License at
## 
##    http://www.apache.org/licenses/LICENSE-2.0
## 
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
##**************************************************************


##*****************************************************************
## Removes a previous installation.
##
## Author: Joe Meehean
## Date: 6/21/03
##*****************************************************************

#***
# Uses
#***
use strict;
use Getopt::Long;
use File::Basename;
#***
# Constant Static Variables
#***
my $USAGE = 
    "Usage: cleanup_release [-help] <install_log>\n";

#  log entry headers
my $INSTALL_ENTRY_HDR = 101;
my $WARNING_ENTRY_HDR = 201;
my $ERROR_ENTRY_HDR = 301;
my $REMOVE_ENTRY_HDR = 501;

#***
# Non-Constant Static Variables
#***
my $install_log_path = 0;
my $install_log_name = 0;
my $help = 0;

#***
# Main Function
#***

#Process command-line arguments
GetOptions('-help'=>\$help,);

die $USAGE if (@ARGV < 1 || $help);
$install_log_path = shift @ARGV;

# Move to the same directory as the install log
my $base_dir = dirname($install_log_path);
$install_log_name = basename($install_log_path);
chdir $base_dir or die "Cannot chdir to $base_dir: $!";

# Extract Info from Log
my @logEntries = &ExtractFromLog();

# Create set of files to remove from extracted info
my @removals = &CreateRemovalPlan(@logEntries);

# Perform removals according to plan
my $success = &PerformRemovals(@removals);

# If the uninstall was a success
# remove the installation log
unlink $install_log_name if( $success );

# Return success or failure
exit !$success;

#DONE

#*********************************************************************
# Creates an ordered list of entries from the install log
#*********************************************************************
sub ExtractFromLog(){
    
    # open the log
    open INSTALL_LOG_FD, "< $install_log_name"
	or die "Cannot open $install_log_name: $!";

    # populate a list with entries
    my @entries = ();
    while( <INSTALL_LOG_FD> ){
	chomp($_);
	push @entries, $_ if ($_);
    }

    # close the log
    close INSTALL_LOG_FD;

    return @entries;
}

#*********************************************************************
# Creates an ordered list of files to be removed given the list of 
# entries from the install log
#*********************************************************************
sub CreateRemovalPlan(){
    my @entries = @_;   #name the parameters

    # Reverse the list (process last to first)
    my @reverseLog = reverse @entries;
    
    # Create a hash to store removes
    my %removeHash = ();
    
    # Create a list of files to remove
    my @removalPlan = ();

    # For each entry in the reversed install log
    foreach my $entry( @reverseLog ){

	#parse the entry
	my $header = 0;
	my $body = 0;
	if( $entry =~ m|(\d+)\t(.+)| ){
	    $header = $1;
	    $body = $2;
	} else{
	    die "FAILURE: Entry [$entry] is malformed";
	}
	
	#switch on the type of entry
	if( $header == $INSTALL_ENTRY_HDR ){
	    # Add a file to the remove list 
	    # if we haven't already processed a remove for it
	    if( !exists $removeHash{$body} ){
		push @removalPlan, $body;
	    } else{
		# the remove entry is used up
		delete $removeHash{$body};
	    }
	} elsif( $header == $WARNING_ENTRY_HDR ){
	    # do nothing
	} elsif( $header == $ERROR_ENTRY_HDR ){
	    # do nothing yet
	} elsif( $header == $REMOVE_ENTRY_HDR ){
	    # Make note of the removal
	    $removeHash{$body} = 1;
	} else{
	    warn "WARNING: Did not recognize entry header [$header]";
	}    
    }

    return @removalPlan;
}

sub PerformRemovals(){
    my @removalPlan = @_;  # name the parameters

    my $overall_success = 1;

    # Open the install log to perform updates as we uninstall
    open INSTALL_LOG_FD, ">> $install_log_name"
	or die "Cannot open $install_log_name: $!";

    # Remove each file in the plan
    foreach my $file(@removalPlan){
	my $success = 0;
	my $errMsg = 'BigProblem';
	
	# attempt to delete the file
	if( -d $file ){
	    $success = rmdir $file;
	    $errMsg = $!;
	} else{
	    $success = unlink $file;
	    $errMsg = $!;
	}
		
	# determine status
	if( $success ){
	    #  Update the install log for each removal
	    print INSTALL_LOG_FD $REMOVE_ENTRY_HDR, "\t", $file, "\n";
	} else{
	    # print warning to log and terminal
	    $overall_success = 0;
	    my $warning_msg = "Could not remove $file: $errMsg";
	    print INSTALL_LOG_FD $WARNING_ENTRY_HDR, "\t", $warning_msg, "\n";
	    warn "WARNING: $warning_msg" ;
	}
    }

    # return a success variable
    return $overall_success;
}
