Rev 229 | Blame | Last modification | View Log | RSS feed
######################################################################### Copyright (C) 1998-2007 ERG Limited, All rights reserved## Module name : CCdiff.pl# Module type : Makefile system# Compiler(s) : n/a# Environment(s): JATS. This script is designed to be run under JATS## Description : Make ClearCase difference report suitable for uploading# to Code Stricker.#......................................................................#require 5.6.1;use strict;use warnings;use JatsError;use JatsSystem;use Pod::Usage; # required for help supportuse Getopt::Long;my $VERSION = "1.0.0"; # Update this## Globals - Provided by the JATS environment#my $UNIX = $ENV{'GBE_UNIX'};## Options#my $opt_debug = $ENV{'GBE_DEBUG'}; # Allow global debugmy $opt_verbose = $ENV{'GBE_VERBOSE'}; # Allow global verbosemy $opt_help = 0;my $opt_manual = 0;my $opt_drive = $UNIX ? '/view' : 'o:';my $opt_viewname = 'administration_view';my $opt_outfile;my @opt_vobs;my $opt_new_label;my $opt_old_label;## Globals#my @error_list; # ClearCmd detected errorsmy $UNIX_VOB_PREFIX = '/vobs';my $VOB_SEP = $UNIX ? '/' : '\\';my $view_path;my @view_tags;my %files;my %diffs;## ROOT_VOBS is a list of VOBS too look in first# If a label is not found in these vobs, then the program will# look in all vobs. This list is a hint to speed up searching#my @ROOT_VOBS = qw( /LMOS /DPG_SWBase /DPG_SWCode /ProjectCD /MASS_Dev_Bus/MASS_Dev_Infra /MOS /MASS_Dataman /MASS_Dev /MASS_Dev_Dataman/COTS /GMPTE2005 /GMPTE2005_obe /MPR /MOS );#-------------------------------------------------------------------------------# Function : Mainline Entry Point## Description :## Inputs :### Parse the user options#my $result = GetOptions ("help+" => \$opt_help, # flag, multiple use allowed"manual" => sub{ $opt_help = 3}, # flag, multiple use allowed"verbose+" => \$opt_verbose, # flag, multiple use allowed"output=s" => \$opt_outfile, # String"new=s" => \$opt_new_label, # String"old=s" => \$opt_old_label, # String"drive=s" => \$opt_drive, # String"vob=s" => \@opt_vobs, # String);## UPDATE THE DOCUMENTATION AT THE END OF THIS FILE !!!### Process help and manual options#pod2usage(-verbose => 0, -message => "Version: $VERSION") if ($opt_help == 1 || ! $result );pod2usage(-verbose => 1) if ($opt_help == 2);pod2usage(-verbose => 2) if ($opt_help > 2);## Configure the error reporting process now that we have the user options#ErrorConfig( 'name' => 'CCDIFF','verbose' => $opt_verbose );## Be nice to the user# If we have two options and no labels, then assigne them#if ( ! $opt_new_label && ! $opt_old_label ){Error ("Must provide two labels on command line unless they are provided via -old and -new options")if ( $#ARGV < 1 );$opt_old_label = shift @ARGV;$opt_new_label = shift @ARGV;}## Error check the user arguments#Error ("Need to provide the 'new' label")unless ( $opt_new_label );Error ("Too many command line arguments" )unless ( $#ARGV < 0 );## Generate a default ouput put file name#unless ( $opt_outfile ){if ( $opt_old_label ){$opt_outfile = "${opt_old_label}-${opt_new_label}-diff.txt";}else{$opt_outfile = "${opt_new_label}-diff.txt";}}Verbose ("Outout file: $opt_outfile");## Determine the machine type#Verbose ("Machine Type: UNIX=$UNIX");## Ensure that the 'cleartool' program can be located#Verbose ("Locate clearcase utility in users path");Error ("Cannot locate the 'cleartool' utility in the users PATH")unless ( LocateProgInPath('cleartool', '--All') );## Ensure that the 'administration_view' is availalable# Then start the view, before checking its availability#if ( ClearCmd ( "lsview $opt_viewname" ) ){Error ("Required view not found: $opt_viewname","This is a dynamic view that should exist as it is used by the build system");}if ( ClearCmd ( "startview $opt_viewname" ) ){Error ("Cannot start the required view: $opt_viewname");}$view_path = "$opt_drive/$opt_viewname";$view_path .= $UNIX_VOB_PREFIX if ( $UNIX );if ( ! -d $view_path ){Error ("Cannot locate the required dynamic view: $view_path","The view exits and has been started. It cannot be found");}### Extend the list of ROOT_VOBS with all the known vobs# The initial ROOT_VOBS are treated as a "hint" to assist searching#if ( @opt_vobs ){@ROOT_VOBS = ();foreach my $vob ( @opt_vobs ){$vob = '/' . $vob;$vob =~ s~^$UNIX_VOB_PREFIX~~ if ($UNIX);$vob =~ tr~\\/~/~s;push @ROOT_VOBS, $vob;}}else{my $cmd = "cleartool lsvob -short";open(CMD, "$cmd 2>&1 |") || Error( "can't run command: $!");while (<CMD>){## Filter output from the user#chomp;s~^$UNIX_VOB_PREFIX~~ if ($UNIX);Verbose2("lsvob: $_");tr~\\/~/~s;push @ROOT_VOBS, $_;}close(CMD);}## Ensure the two labels are present - determine the VOB root#my $l1_vob = LocateLabel( $opt_old_label) if $opt_old_label;my $l2_vob = LocateLabel( $opt_new_label);## Locate all files for the two labels#files_from_from_view( $l1_vob, ,$opt_old_label, 1 ) if $opt_old_label;;files_from_from_view( $l2_vob, ,$opt_new_label, 2 );#DebugDumpData ("Files", \%files );## Create a hash of files that are different# The hash key will be the file name# The tag will be the branch that the file is on#foreach my $file ( sort keys %files ){## These files are the same#next if ( $files{$file}{1} && $files{$file}{2} );my $tag = 1;$tag = 2 if $files{$file}{2};## Break path into file and version#$file =~ m~(.*)(@@[^@]*$)~;my ($f,$b) = ($1,$2);$diffs{$f}{$tag} = $file;# print "$file\n";}## Process files that are common, but have changed#my @no_text;my $added = 0;my $deleted = 0;my $diffs = 0;my $funny = 0;open (FO, ">", $opt_outfile) || Error ("Cannot open file: $opt_outfile");foreach my $file ( sort keys %diffs ){my ($hs, $id, $type);## Files are are common#if ( $diffs{$file}{1} && $diffs{$file}{2} ){$type = "different";($hs, $id) = ClearDiff("-serial_format", "-blank_ignore", $diffs{$file}{1}, $diffs{$file}{2});$diffs++ if ( $hs );}elsif ($diffs{$file}{1} ){## File has been deleted#$type = "deleted";Message ("$file has been deleted");($hs, $id) = ClearDiff("-serial_format", $diffs{$file}{1}, element0($diffs{$file}{1}) );$deleted++ if ( $hs );}else{## File has been added#$type = "added";($hs, $id) = ClearDiff("-serial_format", element0($diffs{$file}{2}) , $diffs{$file}{2} );$added++ if ( $hs );}$type = "identical"if ( $id );$file = StripView($file);Message ("$type: $file" );unless ( $hs || $id ){push @no_text, $file;$funny ++;}}close FO;## Warn about problem files#if ( @no_text ){Warning ("The following files did not generate any difference report, although","they are different. They may be binary files:", @no_text);}## Summary information#Information ("Summary Information","Old Label: : " . ( $opt_old_label ? $opt_old_label : '-None-') ,"New Label: : $opt_new_label","Files different : $diffs","Files added : $added","Files deleted : $deleted","Files not in report: $funny","Output file : $opt_outfile",);#DebugDumpData ("Files", \%diffs);exit (0);#-------------------------------------------------------------------------------# Function : files_from_from_view## Description : Determine the list of files/versions in a given view## Inputs : $vpath - Path to the view# $label - Label# $tag - File tag## Returns : Nothing# Populates the %files array#sub files_from_from_view{my ($vpath, $label, $tag) = @_;my $cutlen = length ($vpath );Message("Determine file versions for: $label");## Ensure that the VOB is mounted# The mount command MUST have the correct vob format#my $vob = $vpath;$vob =~ s~^/+~~;$vob = $VOB_SEP . $vob;ClearCmd ("mount $vob" );my $cmd = "cleartool find $opt_drive/$opt_viewname/$vpath -all -follow -type f -element \"lbtype_sub($label)\" -version \"lbtype_sub($label)\" -print";Verbose ("ClearTool: $cmd");open(CMD, "$cmd 2>&1 |") || Error "Can't run command: $!";while (<CMD>){print "Label$tag: $_" if $opt_verbose;my $file = $_;$file =~ s~[\r\n]+$~~;$file =~ tr~\\/~/~s;$files{$file}{$tag} = 1;}close(CMD);Verbose2 "ClearTool Exit Status: $?";}#-------------------------------------------------------------------------------# Function : ClearDiff## Description : Issue a cleartool command# Filter out many of the stupid messages## Inputs : Options and Command line# Options:## Returns : Error code#sub ClearDiff{my $header_seen = 0;my $identical = 0;my $cmd = "cleardiff " . QuoteCommand (@_);Verbose ("ClearDiff: $cmd");open(CMD, "$cmd 2>&1 |") || Error "can't run command: $!";while (<CMD>){$header_seen = 1if ( m~^[*]{32}~ );unless ( $header_seen ){if ( m~^Files are identical~ ){$identical = 1;next;}next;}## Filter output from the user#s~(file [12]: )$view_path/~$1/~i;print FO $_;}close(CMD);## Ensure the section ends with a complete line# An extra line doesn't affect CS parsing, but without it any file# without a trailing \n will kill the header parsing#print FO "\n" if($header_seen);Verbose "ClearDiff Exit Status: $?";return $header_seen, $identical;}#-------------------------------------------------------------------------------# Function : ClearCmd## Description : Execute a cleartool command# Capture error messages only## Inputs : Command to execute## Returns : Exit code# Also the global @error_list#sub ClearCmd{my( $cmd ) = @_;Verbose "cleartool $cmd";@error_list = ();open(CMD, "cleartool $cmd 2>&1 |") || Error "can't run command: $!";while (<CMD>){chomp;Verbose2 ($_);push @error_list, $_ if ( m~Error:~ );}close(CMD);Verbose2 "Exit Status: $?";return $? / 256;}#-------------------------------------------------------------------------------# Function : LocateLabel## Description : Determine the VOBs that conatins the specified label## Inputs : $label - Label to locate## Returns : First VOB that conatins the label#sub LocateLabel{my ($label) = @_;Message ("Locate label in VOB: $label" );Verbose("Ensure Label is found in a VOB");my $found = 0;foreach my $vob ( @ROOT_VOBS ){$vob = $UNIX_VOB_PREFIX . $vob if ( $UNIX );(my $vob_name = $vob) =~ s~/~$VOB_SEP~g;Verbose2 ("Examine label $label in vob: $vob" );my $cmd = "cleartool lstype \"lbtype:$label\@$vob_name\"";open(CMD, "$cmd 2>&1 |") || Error( "can't run command: $!");while (<CMD>){## Filter output from the user#chomp;Verbose2("lstype: $_");next if ( m~Error~ );next unless ( m~label type~ );$found = $vob;last;}close(CMD);last if ( $found );}Error ("Label $label not found in @ROOT_VOBS")unless ( $found );Verbose ("Label $label found in $found");return $found;}#-------------------------------------------------------------------------------# Function : element0## Description : Given a branch version, this function will return the# zero-th element on the branch## ie: /DPG_SWBase/file@@some_branch/12# -> /DPG_SWBase/file@@some_branch/0## Inputs : $element## Returns : as described#sub element0{my ($element) = @_;$element =~ s~/\d+$~/0~;return $element;}#-------------------------------------------------------------------------------# Function : StripView## Description : Strips the view nae from a file## Inputs : $name - A pathname with view name prefix## Returns : The name without the view name#my $StripView_len;sub StripView{my ($name) = @_;## Determine the length to strip off - once#unless ( $StripView_len ){$StripView_len = length($view_path);}return substr ($name, $StripView_len );}#-------------------------------------------------------------------------------# Documentation#=pod=head1 NAMECCdiff - ClearCase Difference Report=head1 SYNOPSISjats CCdiff [options] [[old_label] new-label]Options:-help - brief help message-help -help - Detailed help message-man - Full documentation-old=label - Old label (optional)-new=label - New label (mandatory)-output=file - Output filename-vob=name - Vob for labels-drive=path - Alternate vob location=head1 OPTIONS=over 8=item B<-help>Print a brief help message and exits.=item B<-help -help>Print a detailed help message with an explanation for each option.=item B<-man>Prints the manual page and exits.=item B<-old=label>This option specifies the old, or base, label for the difference report. Thisoption is not required when a new package is being processed.=item B<-new=label>This option specifies the new, or current, label for the difference report. Thislabel is mandatory for the difference report.The old and new labels may be provided on the command line, or via namedoptions, but not both.=item B<-vob=name>This option limits the label search to the specified VOB. This option may beneeded if the labels are to be found in multiple VOBs.This option may be used multiple times. All specified vobs will be searched andthe first one containing the label will be used.=item B<-output=file>This option specifies the output filename. The program will generate an outputfile based on the two source labels.=item B<-drive=path>This option allows the user to provide an alternate location for theadministration vob used by the program. The default location is:=over 8=item * Windows o:=item * Unix /view=back=head1 DESCRIPTIONThis program is the primary tool for creating 'diff' reports to be uploaded toCode Striker.The program will determine the files that are different between the two specifiedlabels. It will determine full pathnames for the files and create a differencereport that is suitable for Code Striker.The program uses a global administration view for the purposes of determiningfile versions. The path names that are generated are full vob-extended pathnames.These may be very long and may not be directly usable under windows.=cut