############################################################################### # CLASS Clearcase::FindCmd # This class inherits from the CCCmpdProc and executes the cleartool command # "find" with specified args # # It overrides the CCProcess member to process the resultant output from the find # command and store information about all files/dirs in and below the pwd. # # It uses the CCIgnore class to determine if a file should be ignored or included # in the processing of the cmd output. # # It stores as a result of the command for each file/dir # NAME = The full path of the file (as defined by CCCmdProc) # VERSION = ############################################################################### package Clearcase::FindCmd; use strict; use Cwd qw/ abs_path /; use DeployUtils::Logger; use Clearcase::IgnoreList; use Clearcase::CmdProc; use vars qw( @ISA ); @ISA = qw( Clearcase::CmdProc ); my $StateCheckedIn = "CHECKEDIN"; my $StateCheckedOut = "CHECKEDOUT"; #============================================================================== # Constructor #============================================================================== sub new { my $obclass = shift; my $class = ref($obclass) || $obclass; my $dir = shift; my $args = shift; LogDebug("Clearcase::FindCmd::new Instantiating new object of class $class"); # if no dir of dir is "." the get full absolute path, abs_path returns patch with "/" regardless of platform $dir = abs_path(".") if ( ! defined($dir) || $dir eq "." ); $args = "" if ( ! defined($args) ); $args .= " -print" if ( $args !~ /-print/ ); # Call base class's constructor my $self = $class->SUPER::new(); # Add this class's data to the class object $self->{_FINDDIR} = $dir; $self->{_FINDARGS} = $args; bless($self, $class); # set Clearcase command and arg $self->CCcmd("find $dir"); $self->CCargs("$args"); return $self; } # new #============================================================================== # CCprocess overrides base class's CCProcess to process result #============================================================================== sub CCprocess { my $self = shift; my $line; my ($name, $version, $state ) = ( "", "", "" ); my $dirRE = $self->{_FINDDIR}; # if dirRE starts with a drive letter then its a dynamic view and the find reports file names without # the drive letter, so lets remove it from the RE #$dirRE =~ s|^[a-zA-Z]:||; # Change the search RE for the findDir so that all occurances of "/" in path are changed to "[/\\]" # to match either type of path separator $dirRE =~ s|/|\[/\\\\\]|g; NEXTLINE: while ( $line = $self->getline() ) { chomp $line ; $line =~ s/\r//g; # remove carraige returns # ignore blank lines next NEXTLINE if ( $line =~ /^\s*$/ ); # Files Found can be above the supplied dir if -all is used so lets remove files that dont start with Dir if ( $line !~ m|^$dirRE| ) { LogDebug("Clearcase::FindCmd::CCprocess Ignoring following Line as it is above current path"); LogDebug("$line"); next NEXTLINE; } # if line contains 2 sets of @@ then its probably a removed file that is traced back to a parent # its format is dir@@branch/filename@@branch/version if ( $line =~ /^(.*)\@\@(.*)\@\@(.*)$/ ) { my $dir = $1; $name = $2; $version = $3; # get last part of name which is the file name with the dir separator $name =~ s|^.*([/\\\\][^/\\\\])|$1|; # now prepend dir to name $name = $dir . $name; # See if Checked out state if ( $version =~ /CHECKEDOUT$/ ) { $state = $StateCheckedOut; } else { $state = $StateCheckedIn; } } elsif ( $line =~ /^(.*)\@\@(.*)$/ ) { # got the file name, & rest of line $name = $1; $version = $2; # See if Checked out state if ( $version =~ /CHECKEDOUT$/ ) { $state = $StateCheckedOut; } else { $state = $StateCheckedIn; } } else { LogError("-x", "Clearcase::FindCmd::CCprocess Unknown Input Line as follows"); LogError("$line"); } # Remove findDir from path if find dir is same as pwd, makes it less clutered $name =~ s|$dirRE|\.| if ( $self->CCcwd() =~ m|^$dirRE| ); # Add name to file list and set it as current element $self->addToFileList($name); # now add other elements, the index is remembered in the base class $self->updateCurrentFile("STATE", $state, "VERSION", $version); } } # process #============================================================================== # printResult prints out the result of the ls command in a formatted output #============================================================================== sub printResult { } # printResult #============================================================================== # getDiffListFrom # Compares this objects file list to object passed into. It assumes the object passed # is the from object and this object is the to object and compares them. # Any item in this and not in from is new and vice versa. # it returns a reference to a hash that is keyed by name and contains hash elements # NEW & OLD that contain the version strings from the comparison #============================================================================== sub getDiffListFrom { my $self = shift; my $from = shift; my %diff; my ( $thisElement, $thatElement ); my $name; LogError("FindCmd::getDiffFrom: Argument must be a FindCmd object") if ( ref($from) ne "Clearcase::FindCmd" ); # loop through this objects elements and find them in from object. # if not found in from then its a new object, otherwise if versions are different then element has changed $thisElement = $self->getFirstElement(); while( defined($thisElement) ) { $name = $thisElement->{NAME}; $thatElement = $from->findName($name); if ( defined($thatElement) ) { if ( $thisElement->{VERSION} ne $thatElement->{VERSION} ) { $diff{$name}{NEW} = $thisElement->{VERSION}; $diff{$name}{OLD} = $thatElement->{VERSION}; } } else { $diff{$name}{NEW} = $thisElement->{VERSION}; $diff{$name}{OLD} = ""; } $thisElement = $self->getNextElement(); } # loop through that objects elements and find them in this object. # Only want to find ones that dont exist in this one which means they have been removed $thatElement = $from->getFirstElement(); while( defined($thatElement) ) { $name = $thatElement->{NAME}; $thisElement = $self->findName($name); if ( !defined($thisElement) ) { $diff{$name}{OLD} = $thatElement->{VERSION}; $diff{$name}{NEW} = ""; } $thatElement = $from->getNextElement(); } #print Data::Dumper->Dump([ \%diff ], [ "Diff" ]); return \%diff; } # getDiffListFrom 1;