Subversion Repositories DevTools

Rev

Blame | Last modification | View Log | RSS feed

###############################################################################
# CLASS Clearcase::Cmd
# Base Class for executing clearcase commands and allowing results to be proceesed.
# 
# The class should be instantiated, the Clearcase Command and Arguements set and
# then the CCexecute should be called to execute the command.  By default this 
# class will then simply just print the result to the console if no derived class
# overrides the CCProcess method.
# Dereived Classes should override the CCProcess member, which is called by CCexecute
# after the Clearcase command has been executed, to process the output of the 
# command as required.
#
# By convention all members/methods that begin with an '_' are private.
# 
###############################################################################

package Clearcase::Cmd;

use strict;
use Cwd;
use DeployUtils::Logger;
use IO::File;
use File::Temp qw /mktemp/;
use File::Spec qw /tmpdir/;

#==============================================================================
#   Constructor
#==============================================================================
sub new
{
    my $obclass = shift;
    my $class = ref($obclass) || $obclass;

    LogDebug("ClearCase::Cmd::new Instantiating new object of class $class");
    bless my $self = {
        _CWD             => Cwd::cwd,
        _CLEARTOOL       => ( $^O eq "solaris" ) ? "/usr/atria/bin/cleartool" : "cleartool",
        _CMD             => "",
        _ARGS            => "",
        _TMPNAME         => "",
        _CMDOUTPUT       => new IO::File,
        _PROCESSOUTPUT   => 1,
        _ABORTONERROR    => 1
    } => ( $class );
    return($self);
}   # new


#==============================================================================
#   DESTROY ( Desctructor )
#==============================================================================
sub DESTROY
{
    my $self = shift;

    $self->reset();
}   # DESTROY


#==============================================================================
#   reset
# Closes the filehandle and removes the temp file if any
#==============================================================================
sub reset
{
    my $self = shift;

    $self->{_CMDOUTPUT}->close if ( defined($self->{_CMDOUTPUT}) && defined($self->{_CMDOUTPUT}->fileno()) );
    unlink($self->{_TMPNAME}) if ( $self->{_TMPNAME} ne "" && -f $self->{_TMPNAME} );
}   # reset


###############################################################################
# Set/Get member methods.
# The following functions allow callers to set/get internal members.
###############################################################################

#==============================================================================
#   CCcwd accessor method returns CWD
#==============================================================================
sub CCcwd
{
    my $self = shift;
    return $self->{_CWD};
}   # CCcwd


#==============================================================================
#   CCcmd accessor sets & returns the Clearcase command
#==============================================================================
sub CCcmd
{
    my $self = shift;
    if ( @_ )
    {
        # if we are setting the command then we need to make sure the object is reset in case its a new cmd
        $self->reset();
        $self->{_CMD} = shift;
        $self->{_ARGS} = "";
        LogDebug("ClearCase::Cmd::CCcmd Set CC Command to $self->{_CMD}");
    }
    return $self->{_CMD};
}   # cc_cmd


#==============================================================================
#   CCargs accessor sets & returns the Clearcase command arguements
#==============================================================================
sub CCargs
{
    my $self = shift;
    if ( @_ )
    {
        $self->{_ARGS} = shift;
        LogDebug("ClearCase::Cmd::CCargs Set CC Args to $self->{_ARGS}");
    }
    return $self->{_ARGS};
}   # cc_args


#==============================================================================
#   CCaddArgs accessor appends arsg to existing args list
#==============================================================================
sub CCaddArgs
{
    my $self = shift;
    foreach my $i ( @_ )
    {
        $self->{_ARGS} .= " " . $i;
    }
    LogDebug("ClearCase::Cmd::CCaddArgs Set CC Args to $self->{_ARGS}");
    return $self->{_ARGS};
}   # cc_args


#==============================================================================
#   processOutput
# Sets the processOutput flag to 1 or 0.  If 1 clearcase commands are redirected
# to a file for processing by CCProcess, otherwise 0 does not redirection or processing.
#==============================================================================
sub processOutput
{
    my $self = shift;
    if ( @_ )
    {
        my $val = shift;
        $self->{_PROCESSOUTPUT} = ( $val == 0 ) ? 0 : 1;
        LogDebug("ClearCase::Cmd::processOutput Set to $self->{_PROCESSOUTPUT}");
    }
    return $self->{_PROCESSOUTPUT};

}   # processOutput


#==============================================================================
#   abortOnError
# Sets the abortOnError flag to 1 or 0.  If 0 then CCexecute ignores errors and 
# returns the error code, if 1 then errors are reported & script terminates
#==============================================================================
sub abortOnError
{
    my $self = shift;
    if ( @_ )
    {
        my $val = shift;
        $self->{_ABORTONERROR} = ( $val == 0 ) ? 0 : 1;
        LogDebug("ClearCase::Cmd::abortOnError Set to $self->{_ABORTONERROR}");
    }
    return $self->{_ABORTONERROR};

}   # abortOnError


#==============================================================================
#   CCexecute executes cleartool cmd with args and stores resulting output in
#   IO::File handle in self
#==============================================================================
sub CCexecute
{
    my $self = shift;
    my $retval;

    if ( $self->{_CMD} eq "" )
    {
        LogError("ClearCase::Cmd::CCexecute No Command to execute");
    }

    if ( $self->{_PROCESSOUTPUT} )
    {
        $self->{_TMPNAME} = File::Spec->tmpdir() . "/" . mktemp("CCCmdXXXXX");
        LogDebug("ClearCase::Cmd::CCexecute Executing cmd \"$self->{_CLEARTOOL} $self->{_CMD} $self->{_ARGS} > $self->{_TMPNAME}\".");
        $retval = system("$self->{_CLEARTOOL} $self->{_CMD} $self->{_ARGS} > $self->{_TMPNAME}") >> 8;
    }
    else
    {
        LogDebug("ClearCase::Cmd::CCexecute Executing cmd \"$self->{_CLEARTOOL} $self->{_CMD} $self->{_ARGS}\".");
        $retval = system("$self->{_CLEARTOOL} $self->{_CMD} $self->{_ARGS}") >> 8;
    }

    if ( $retval != 0 )
    {
        unlink($self->{_TMPNAME}) if ( $self->{_TMPNAME} ne "" && -f $self->{_TMPNAME} );
        LogError("ClearCase::Cmd::CCexecute Cmd Execution Failed with error $retval") if ( $self->{_ABORTONERROR} );
        LogError("-x", "ClearCase::Cmd::CCexecute Cmd Execution Failed with error $retval");
    }
    
    if ( $self->{_PROCESSOUTPUT} )
    {
        $self->{_CMDOUTPUT}->open("<$self->{_TMPNAME}") || LogError("ClearCase::Cmd::CCexecute Cannot open clearcase command results file");

        # Calls processData member to process result.
        # default version in this class simply prints the result to std out.
    
        $self->CCprocess();
    }
            
    return $retval;
}   # cc_exec


#==============================================================================
#   CCprocess processes the output from the execute command.
#   This is the default version that just simply dumps the output from the 
#   clearcase command executed to console
#   Any Derived classes can override this and either do nothing or process output 
#   as required.
#   It is a function called by the CCexecute method and should not be
#   called externally
#==============================================================================
sub CCprocess
{
    my $self = shift;
    my $line;
    while ( $line = $self->{_CMDOUTPUT}->getline() )
    {
        print $line;
    }
}   # CCprocess


#==============================================================================
#   getline retunrs the next line from the IO File class using its getline method
#==============================================================================
sub getline
{
    my $self = shift;
    
    return $self->{_CMDOUTPUT}->getline();
}   # getline


#==============================================================================
#   dumpSelf, debugging member to dump selfs hash
#==============================================================================
sub dumpSelf
{
    use Data::Dumper;

    my $self = shift;

    print Data::Dumper->Dump([$self], [ref($self)]);
}   # dumpSelf
1;