| 227 |
dpurdie |
1 |
########################################################################
|
|
|
2 |
# Copyright (C) 1998-2007 ERG Limited, All rights reserved
|
|
|
3 |
#
|
|
|
4 |
# Module name : CCdiff.pl
|
|
|
5 |
# Module type : Makefile system
|
|
|
6 |
# Compiler(s) : n/a
|
|
|
7 |
# Environment(s): JATS. This script is designed to be run under JATS
|
|
|
8 |
#
|
|
|
9 |
# Description : Make ClearCase difference report suitable for uploading
|
| 241 |
dpurdie |
10 |
# to Code Striker.
|
| 227 |
dpurdie |
11 |
#......................................................................#
|
|
|
12 |
|
|
|
13 |
require 5.6.1;
|
|
|
14 |
use strict;
|
|
|
15 |
use warnings;
|
|
|
16 |
use JatsError;
|
|
|
17 |
use JatsSystem;
|
|
|
18 |
use Pod::Usage; # required for help support
|
| 241 |
dpurdie |
19 |
use Cwd;
|
|
|
20 |
|
| 227 |
dpurdie |
21 |
use Getopt::Long;
|
|
|
22 |
|
| 241 |
dpurdie |
23 |
#-------------------------------------------------------------------------------
|
|
|
24 |
#
|
|
|
25 |
# Function Prototypes
|
|
|
26 |
#
|
|
|
27 |
sub prevElement($);
|
|
|
28 |
sub get_newFiles();
|
|
|
29 |
sub get_prev_viewname();
|
|
|
30 |
sub get_workingDirectory();
|
| 227 |
dpurdie |
31 |
|
| 241 |
dpurdie |
32 |
#-------------------------------------------------------------------------------
|
|
|
33 |
#
|
|
|
34 |
# Global variables
|
|
|
35 |
#
|
|
|
36 |
my $VERSION = "1.0.1"; # Update this
|
| 227 |
dpurdie |
37 |
|
| 241 |
dpurdie |
38 |
|
| 227 |
dpurdie |
39 |
#
|
|
|
40 |
# Globals - Provided by the JATS environment
|
|
|
41 |
#
|
|
|
42 |
my $UNIX = $ENV{'GBE_UNIX'};
|
|
|
43 |
|
|
|
44 |
#
|
|
|
45 |
# Options
|
|
|
46 |
#
|
|
|
47 |
my $opt_debug = $ENV{'GBE_DEBUG'}; # Allow global debug
|
|
|
48 |
my $opt_verbose = $ENV{'GBE_VERBOSE'}; # Allow global verbose
|
|
|
49 |
my $opt_help = 0;
|
|
|
50 |
my $opt_manual = 0;
|
|
|
51 |
my $opt_drive = $UNIX ? '/view' : 'o:';
|
|
|
52 |
my $opt_viewname = 'administration_view';
|
|
|
53 |
my $opt_outfile;
|
|
|
54 |
my @opt_vobs;
|
|
|
55 |
my $opt_new_label;
|
|
|
56 |
my $opt_old_label;
|
|
|
57 |
|
|
|
58 |
#
|
|
|
59 |
# Globals
|
|
|
60 |
#
|
|
|
61 |
my @error_list; # ClearCmd detected errors
|
|
|
62 |
my $UNIX_VOB_PREFIX = '/vobs';
|
|
|
63 |
my $VOB_SEP = $UNIX ? '/' : '\\';
|
|
|
64 |
my $view_path;
|
|
|
65 |
my @view_tags;
|
|
|
66 |
my %files;
|
|
|
67 |
my %diffs;
|
| 241 |
dpurdie |
68 |
( my $startDirectory = getcwd() ) =~ s/[\n\r]+$//;
|
| 227 |
dpurdie |
69 |
|
|
|
70 |
#
|
|
|
71 |
# ROOT_VOBS is a list of VOBS too look in first
|
|
|
72 |
# If a label is not found in these vobs, then the program will
|
|
|
73 |
# look in all vobs. This list is a hint to speed up searching
|
|
|
74 |
#
|
|
|
75 |
my @ROOT_VOBS = qw( /LMOS /DPG_SWBase /DPG_SWCode /ProjectCD /MASS_Dev_Bus
|
|
|
76 |
/MASS_Dev_Infra /MOS /MASS_Dataman /MASS_Dev /MASS_Dev_Dataman
|
|
|
77 |
/COTS /GMPTE2005 /GMPTE2005_obe /MPR /MOS );
|
|
|
78 |
|
|
|
79 |
|
|
|
80 |
|
|
|
81 |
#-------------------------------------------------------------------------------
|
|
|
82 |
# Function : Mainline Entry Point
|
|
|
83 |
#
|
|
|
84 |
# Description :
|
|
|
85 |
#
|
|
|
86 |
# Inputs :
|
|
|
87 |
#
|
|
|
88 |
|
|
|
89 |
#
|
|
|
90 |
# Parse the user options
|
|
|
91 |
#
|
|
|
92 |
my $result = GetOptions (
|
|
|
93 |
"help+" => \$opt_help, # flag, multiple use allowed
|
|
|
94 |
"manual" => sub{ $opt_help = 3}, # flag, multiple use allowed
|
|
|
95 |
"verbose+" => \$opt_verbose, # flag, multiple use allowed
|
| 229 |
dpurdie |
96 |
"output=s" => \$opt_outfile, # String
|
| 227 |
dpurdie |
97 |
"new=s" => \$opt_new_label, # String
|
| 229 |
dpurdie |
98 |
"old=s" => \$opt_old_label, # String
|
| 227 |
dpurdie |
99 |
"drive=s" => \$opt_drive, # String
|
|
|
100 |
"vob=s" => \@opt_vobs, # String
|
|
|
101 |
);
|
|
|
102 |
|
|
|
103 |
#
|
|
|
104 |
# UPDATE THE DOCUMENTATION AT THE END OF THIS FILE !!!
|
|
|
105 |
#
|
|
|
106 |
|
|
|
107 |
#
|
|
|
108 |
# Process help and manual options
|
|
|
109 |
#
|
|
|
110 |
pod2usage(-verbose => 0, -message => "Version: $VERSION") if ($opt_help == 1 || ! $result );
|
|
|
111 |
pod2usage(-verbose => 1) if ($opt_help == 2);
|
|
|
112 |
pod2usage(-verbose => 2) if ($opt_help > 2);
|
|
|
113 |
|
|
|
114 |
#
|
|
|
115 |
# Configure the error reporting process now that we have the user options
|
|
|
116 |
#
|
|
|
117 |
ErrorConfig( 'name' => 'CCDIFF',
|
|
|
118 |
'verbose' => $opt_verbose );
|
|
|
119 |
|
|
|
120 |
#
|
|
|
121 |
# Be nice to the user
|
|
|
122 |
# If we have two options and no labels, then assigne them
|
|
|
123 |
#
|
|
|
124 |
if ( ! $opt_new_label && ! $opt_old_label )
|
|
|
125 |
{
|
|
|
126 |
Error ("Must provide two labels on command line unless they are provided via -old and -new options")
|
|
|
127 |
if ( $#ARGV < 1 );
|
|
|
128 |
|
|
|
129 |
$opt_old_label = shift @ARGV;
|
|
|
130 |
$opt_new_label = shift @ARGV;
|
|
|
131 |
}
|
|
|
132 |
|
|
|
133 |
#
|
|
|
134 |
# Error check the user arguments
|
|
|
135 |
#
|
|
|
136 |
Error ("Need to provide the 'new' label")
|
|
|
137 |
unless ( $opt_new_label );
|
|
|
138 |
|
|
|
139 |
Error ("Too many command line arguments" )
|
|
|
140 |
unless ( $#ARGV < 0 );
|
|
|
141 |
|
|
|
142 |
#
|
| 241 |
dpurdie |
143 |
# $workingDirectory is only used if compareWithDirectory == 1, which is
|
|
|
144 |
# only true when user has specified that -new points to a directory
|
|
|
145 |
#
|
|
|
146 |
my ( $workingDirectory, $compareWithDirectory ) = get_workingDirectory ();
|
|
|
147 |
|
|
|
148 |
#
|
| 227 |
dpurdie |
149 |
# Generate a default ouput put file name
|
|
|
150 |
#
|
|
|
151 |
unless ( $opt_outfile )
|
|
|
152 |
{
|
|
|
153 |
if ( $opt_old_label )
|
|
|
154 |
{
|
|
|
155 |
$opt_outfile = "${opt_old_label}-${opt_new_label}-diff.txt";
|
|
|
156 |
}
|
|
|
157 |
else
|
|
|
158 |
{
|
|
|
159 |
$opt_outfile = "${opt_new_label}-diff.txt";
|
|
|
160 |
}
|
|
|
161 |
}
|
| 241 |
dpurdie |
162 |
Verbose ("Output file: $opt_outfile");
|
| 227 |
dpurdie |
163 |
|
|
|
164 |
#
|
|
|
165 |
# Determine the machine type
|
|
|
166 |
#
|
|
|
167 |
Verbose ("Machine Type: UNIX=$UNIX");
|
|
|
168 |
|
|
|
169 |
#
|
|
|
170 |
# Ensure that the 'cleartool' program can be located
|
|
|
171 |
#
|
|
|
172 |
Verbose ("Locate clearcase utility in users path");
|
|
|
173 |
Error ("Cannot locate the 'cleartool' utility in the users PATH")
|
|
|
174 |
unless ( LocateProgInPath('cleartool', '--All') );
|
|
|
175 |
|
|
|
176 |
#
|
|
|
177 |
# Ensure that the 'administration_view' is availalable
|
|
|
178 |
# Then start the view, before checking its availability
|
|
|
179 |
#
|
| 241 |
dpurdie |
180 |
if( ClearCmd('lsview', $opt_viewname) )
|
| 227 |
dpurdie |
181 |
{
|
|
|
182 |
Error ("Required view not found: $opt_viewname",
|
|
|
183 |
"This is a dynamic view that should exist as it is used by the build system"
|
|
|
184 |
);
|
|
|
185 |
}
|
|
|
186 |
|
| 241 |
dpurdie |
187 |
#
|
|
|
188 |
# Under windows if user is comparing with a directory you need knowledge of under
|
|
|
189 |
# what view the command was invoked with
|
|
|
190 |
#
|
|
|
191 |
#my $prev_viewname = "";
|
|
|
192 |
#$prev_viewname = get_prev_viewname() if( $compareWithDirectory && ! $UNIX );
|
|
|
193 |
|
|
|
194 |
if( ClearCmd( 'startview', $opt_viewname) )
|
| 227 |
dpurdie |
195 |
{
|
|
|
196 |
Error ("Cannot start the required view: $opt_viewname");
|
|
|
197 |
}
|
|
|
198 |
|
|
|
199 |
$view_path = "$opt_drive/$opt_viewname";
|
|
|
200 |
$view_path .= $UNIX_VOB_PREFIX if ( $UNIX );
|
|
|
201 |
if ( ! -d $view_path )
|
|
|
202 |
{
|
|
|
203 |
Error ("Cannot locate the required dynamic view: $view_path",
|
|
|
204 |
"The view exits and has been started. It cannot be found"
|
|
|
205 |
);
|
|
|
206 |
}
|
|
|
207 |
|
|
|
208 |
#
|
|
|
209 |
#
|
|
|
210 |
# Extend the list of ROOT_VOBS with all the known vobs
|
|
|
211 |
# The initial ROOT_VOBS are treated as a "hint" to assist searching
|
|
|
212 |
#
|
|
|
213 |
if ( @opt_vobs )
|
|
|
214 |
{
|
|
|
215 |
@ROOT_VOBS = ();
|
|
|
216 |
foreach my $vob ( @opt_vobs )
|
|
|
217 |
{
|
|
|
218 |
$vob = '/' . $vob;
|
|
|
219 |
$vob =~ s~^$UNIX_VOB_PREFIX~~ if ($UNIX);
|
| 241 |
dpurdie |
220 |
$vob =~ tr{\\/}{/}s;
|
| 227 |
dpurdie |
221 |
push @ROOT_VOBS, $vob;
|
|
|
222 |
}
|
|
|
223 |
}
|
|
|
224 |
else
|
|
|
225 |
{
|
|
|
226 |
my $cmd = "cleartool lsvob -short";
|
|
|
227 |
open(CMD, "$cmd 2>&1 |") || Error( "can't run command: $!");
|
|
|
228 |
while (<CMD>)
|
|
|
229 |
{
|
|
|
230 |
#
|
|
|
231 |
# Filter output from the user
|
|
|
232 |
#
|
| 241 |
dpurdie |
233 |
s~[\n\r]+$~~;
|
| 227 |
dpurdie |
234 |
s~^$UNIX_VOB_PREFIX~~ if ($UNIX);
|
|
|
235 |
Verbose2("lsvob: $_");
|
| 241 |
dpurdie |
236 |
tr{\\/}{/}s;
|
| 227 |
dpurdie |
237 |
push @ROOT_VOBS, $_;
|
|
|
238 |
}
|
|
|
239 |
close(CMD);
|
|
|
240 |
}
|
|
|
241 |
|
|
|
242 |
#
|
|
|
243 |
# Ensure the two labels are present - determine the VOB root
|
|
|
244 |
#
|
|
|
245 |
my $l1_vob = LocateLabel( $opt_old_label) if $opt_old_label;
|
|
|
246 |
my $l2_vob = LocateLabel( $opt_new_label);
|
|
|
247 |
|
|
|
248 |
#
|
|
|
249 |
# Locate all files for the two labels
|
|
|
250 |
#
|
| 241 |
dpurdie |
251 |
files_from_view( $l1_vob, $opt_old_label, 1 ) if $opt_old_label;
|
|
|
252 |
files_from_view( $l2_vob, $opt_new_label, 2 );
|
| 227 |
dpurdie |
253 |
|
|
|
254 |
#DebugDumpData ("Files", \%files );
|
|
|
255 |
|
|
|
256 |
#
|
|
|
257 |
# Create a hash of files that are different
|
|
|
258 |
# The hash key will be the file name
|
|
|
259 |
# The tag will be the branch that the file is on
|
|
|
260 |
#
|
|
|
261 |
foreach my $file ( sort keys %files )
|
|
|
262 |
{
|
|
|
263 |
#
|
|
|
264 |
# These files are the same
|
|
|
265 |
#
|
|
|
266 |
next if ( $files{$file}{1} && $files{$file}{2} );
|
| 241 |
dpurdie |
267 |
|
| 227 |
dpurdie |
268 |
my $tag = 1;
|
|
|
269 |
$tag = 2 if $files{$file}{2};
|
| 241 |
dpurdie |
270 |
|
| 227 |
dpurdie |
271 |
#
|
|
|
272 |
# Break path into file and version
|
|
|
273 |
#
|
|
|
274 |
$file =~ m~(.*)(@@[^@]*$)~;
|
|
|
275 |
my ($f,$b) = ($1,$2);
|
| 241 |
dpurdie |
276 |
$diffs{$f}{$tag} = $file;
|
| 227 |
dpurdie |
277 |
}
|
|
|
278 |
|
|
|
279 |
#
|
|
|
280 |
# Process files that are common, but have changed
|
|
|
281 |
#
|
|
|
282 |
my @no_text;
|
|
|
283 |
my $added = 0;
|
|
|
284 |
my $deleted = 0;
|
|
|
285 |
my $diffs = 0;
|
| 241 |
dpurdie |
286 |
my $ifile = 0;
|
|
|
287 |
|
|
|
288 |
open (FO, ">", "$startDirectory/$opt_outfile") || Error ("Cannot open file: $startDirectory/$opt_outfile");
|
|
|
289 |
|
| 227 |
dpurdie |
290 |
foreach my $file ( sort keys %diffs )
|
|
|
291 |
{
|
| 241 |
dpurdie |
292 |
$ifile ++;
|
|
|
293 |
|
|
|
294 |
print "Running ClearDiff on file $ifile/" . scalar(keys %diffs) . " \r";
|
|
|
295 |
|
| 227 |
dpurdie |
296 |
my ($hs, $id, $type);
|
|
|
297 |
#
|
|
|
298 |
# Files are are common
|
|
|
299 |
#
|
|
|
300 |
if ( $diffs{$file}{1} && $diffs{$file}{2} )
|
|
|
301 |
{
|
| 241 |
dpurdie |
302 |
$type = "different";
|
|
|
303 |
($hs, $id) = ClearDiff("-serial_format", "-blank_ignore", $diffs{$file}{1}, $diffs{$file}{2});
|
|
|
304 |
$diffs++ if ( $hs );
|
| 227 |
dpurdie |
305 |
}
|
|
|
306 |
elsif ($diffs{$file}{1} )
|
|
|
307 |
{
|
| 241 |
dpurdie |
308 |
#
|
|
|
309 |
# File has been deleted
|
|
|
310 |
#
|
|
|
311 |
$type = "deleted";
|
|
|
312 |
Verbose ("$file has been deleted");
|
|
|
313 |
($hs, $id) = ClearDiff("-serial_format", $diffs{$file}{1}, element0($diffs{$file}{1}) );
|
|
|
314 |
$deleted++ if ( $hs );
|
| 227 |
dpurdie |
315 |
}
|
|
|
316 |
else
|
|
|
317 |
{
|
| 241 |
dpurdie |
318 |
#
|
|
|
319 |
# File has been added
|
|
|
320 |
#
|
|
|
321 |
$type = "added";
|
|
|
322 |
if( $compareWithDirectory )
|
|
|
323 |
{
|
|
|
324 |
my $cmd = QuoteCommand( 'cleartool', 'dump', $diffs{$file}{2} );
|
|
|
325 |
|
|
|
326 |
open( CMD, "$cmd 2>&1 |") or Error("can't run command: $!");
|
|
|
327 |
<CMD>; # line 1 - blank
|
|
|
328 |
<CMD>; # line 2 - clearcase filename and a code for it
|
|
|
329 |
(my $basefilename = <CMD>) =~ s~[\n\r]+$~~; # line 3 is what we want
|
|
|
330 |
while( <CMD> ){} # Get rid of broken pipe messages
|
|
|
331 |
close( CMD );
|
|
|
332 |
|
|
|
333 |
$basefilename =~ s{@@.*}{}; # strip off the branch/version number
|
|
|
334 |
# $basefilename = "${opt_drive}/${prev_viewname}${basefilename}" if( ! $UNIX );
|
|
|
335 |
|
|
|
336 |
($hs, $id) = ClearDiff("-serial_format", $diffs{$file}{2}, $basefilename );
|
|
|
337 |
$diffs++ if ( $hs );
|
|
|
338 |
}
|
|
|
339 |
else
|
|
|
340 |
{
|
|
|
341 |
($hs, $id) = ClearDiff("-serial_format", element0($diffs{$file}{2}) , $diffs{$file}{2} );
|
|
|
342 |
$added++ if ( $hs );
|
|
|
343 |
}
|
| 227 |
dpurdie |
344 |
}
|
|
|
345 |
|
|
|
346 |
$type = "identical"
|
| 241 |
dpurdie |
347 |
if ( $id );
|
| 227 |
dpurdie |
348 |
$file = StripView($file);
|
| 241 |
dpurdie |
349 |
Verbose ("$type: $file" );
|
|
|
350 |
|
|
|
351 |
push @no_text, $file unless ( $hs || $id );
|
|
|
352 |
}
|
| 227 |
dpurdie |
353 |
|
| 241 |
dpurdie |
354 |
#
|
|
|
355 |
# If comparing with a directory, do additional files that have been
|
|
|
356 |
# added since the label
|
|
|
357 |
#
|
|
|
358 |
if( $compareWithDirectory )
|
|
|
359 |
{
|
|
|
360 |
my @newFiles = get_newFiles();
|
|
|
361 |
|
|
|
362 |
my ($hs, $id);
|
|
|
363 |
my $type = "added";
|
|
|
364 |
|
|
|
365 |
Message ("Going to run cleardiff for new files") if( @newFiles );
|
|
|
366 |
|
|
|
367 |
foreach my $newFile (@newFiles)
|
| 227 |
dpurdie |
368 |
{
|
| 241 |
dpurdie |
369 |
my $prev_element = prevElement($newFile);
|
|
|
370 |
|
|
|
371 |
($hs, $id) = ClearDiff("-serial_format", $prev_element, $newFile );
|
|
|
372 |
$added++ if ( $hs );
|
|
|
373 |
|
|
|
374 |
$type = "identical" if ( $id );
|
|
|
375 |
$newFile = StripView($newFile);
|
|
|
376 |
Verbose ("$type: $newFile" );
|
|
|
377 |
|
|
|
378 |
push @no_text, $newFile unless ( $hs || $id );
|
| 227 |
dpurdie |
379 |
}
|
|
|
380 |
}
|
|
|
381 |
|
|
|
382 |
#
|
|
|
383 |
# Warn about problem files
|
|
|
384 |
#
|
|
|
385 |
if ( @no_text )
|
|
|
386 |
{
|
|
|
387 |
Warning ("The following files did not generate any difference report, although",
|
|
|
388 |
"they are different. They may be binary files:", @no_text);
|
|
|
389 |
}
|
|
|
390 |
|
|
|
391 |
#
|
|
|
392 |
# Summary information
|
|
|
393 |
#
|
|
|
394 |
Information ("Summary Information",
|
|
|
395 |
"Old Label: : " . ( $opt_old_label ? $opt_old_label : '-None-') ,
|
|
|
396 |
"New Label: : $opt_new_label",
|
|
|
397 |
"Files different : $diffs",
|
|
|
398 |
"Files added : $added",
|
|
|
399 |
"Files deleted : $deleted",
|
| 241 |
dpurdie |
400 |
"Files not in report: " . scalar(@no_text),
|
|
|
401 |
"Output file : $startDirectory/$opt_outfile",
|
| 227 |
dpurdie |
402 |
);
|
|
|
403 |
|
|
|
404 |
|
|
|
405 |
#DebugDumpData ("Files", \%diffs);
|
|
|
406 |
|
| 241 |
dpurdie |
407 |
close FO;
|
| 227 |
dpurdie |
408 |
exit (0);
|
|
|
409 |
|
|
|
410 |
#-------------------------------------------------------------------------------
|
| 241 |
dpurdie |
411 |
# Function : get_workingDirectory
|
| 227 |
dpurdie |
412 |
#
|
| 241 |
dpurdie |
413 |
# Description : Works out the working directory that should be used if the
|
|
|
414 |
# user has specified that the 'new' label is really a directory
|
|
|
415 |
#
|
|
|
416 |
#
|
|
|
417 |
# Inputs :
|
|
|
418 |
#
|
|
|
419 |
# Returns : $workingDirectory - The directory to compare with
|
|
|
420 |
# $compareWithDirectory - 1 (true) if the user has specified that
|
|
|
421 |
# a directory is to be compared
|
|
|
422 |
#
|
|
|
423 |
sub get_workingDirectory()
|
|
|
424 |
{
|
|
|
425 |
return ("", 0) if( $opt_new_label !~ m/^dir=/ && $opt_new_label !~ m/^current/ );
|
|
|
426 |
|
|
|
427 |
my $workingDirectory = "";
|
|
|
428 |
|
|
|
429 |
$workingDirectory = $startDirectory
|
|
|
430 |
if ( $opt_new_label eq 'current' || $opt_new_label eq "dir=current" );
|
|
|
431 |
|
|
|
432 |
if ( $opt_new_label =~ m~^dir=(.+)~ || $opt_new_label =~ m~^current=(.+)~ )
|
|
|
433 |
{
|
|
|
434 |
my $wdir = $1;
|
|
|
435 |
|
|
|
436 |
if( ! $UNIX && $wdir =~ m~^.:~ ) # on windows, directory has been specified as a full drive path
|
|
|
437 |
{
|
|
|
438 |
$workingDirectory = $wdir;
|
|
|
439 |
}
|
|
|
440 |
elsif( $wdir =~ m~^/~ || ($wdir =~ m~^\\~ && ! $UNIX) ) # Full path on the current drive
|
|
|
441 |
{
|
|
|
442 |
$workingDirectory = $wdir;
|
|
|
443 |
}
|
|
|
444 |
else # Relative path
|
|
|
445 |
{
|
|
|
446 |
$workingDirectory = "$startDirectory/$wdir";
|
|
|
447 |
}
|
|
|
448 |
}
|
|
|
449 |
|
|
|
450 |
Verbose ("working directory: '$workingDirectory'");
|
|
|
451 |
|
|
|
452 |
Error("Could not find the directory '$workingDirectory'")
|
|
|
453 |
unless( -d $workingDirectory );
|
|
|
454 |
|
|
|
455 |
chdir $workingDirectory or Error ("Could not chdir into '$workingDirectory'");
|
|
|
456 |
|
|
|
457 |
# We go through the same algorithm in many parts as the
|
|
|
458 |
# no-minus-old algorithm, so to minimise code changes we just
|
|
|
459 |
# treat it the same with the addition of the '$compareWithDirectory' flag
|
|
|
460 |
# to execute additional code.
|
|
|
461 |
$opt_new_label = $opt_old_label;
|
|
|
462 |
$opt_old_label = "";
|
|
|
463 |
|
|
|
464 |
return( $workingDirectory, 1);
|
|
|
465 |
}
|
|
|
466 |
|
|
|
467 |
|
|
|
468 |
#-------------------------------------------------------------------------------
|
|
|
469 |
# Function : prevElement
|
|
|
470 |
#
|
|
|
471 |
# Description : Works out the element that should be compared with the
|
|
|
472 |
# file in the working directory.
|
|
|
473 |
#
|
|
|
474 |
#
|
|
|
475 |
# Inputs : $newFile - File found by cleartool ls'ing the
|
|
|
476 |
# working directory
|
|
|
477 |
#
|
|
|
478 |
# Returns : $prevElement - the element to cleardiff on
|
|
|
479 |
#
|
|
|
480 |
sub prevElement($)
|
|
|
481 |
{
|
|
|
482 |
my ( $newFile ) = @_;
|
|
|
483 |
|
|
|
484 |
my $cmd = qq(cleartool find $newFile -directory -version "{lbtype($opt_new_label)}" -print);
|
|
|
485 |
|
|
|
486 |
Verbose ("Cmd: '$cmd'");
|
|
|
487 |
|
|
|
488 |
my $ret = "${newFile}@@/main/0";
|
|
|
489 |
|
|
|
490 |
open( CMD, "$cmd 2>&1 |") or Error("can't run command: $!");
|
|
|
491 |
while( <CMD> )
|
|
|
492 |
{
|
|
|
493 |
s~[\n\r]+$~~;
|
|
|
494 |
next if( m/Error:/ || m/Warning:/ );
|
|
|
495 |
($ret = $_) =~ s{//}{/}g;
|
|
|
496 |
$ret =~ s{vobs/vobs/}{vobs/}g;
|
|
|
497 |
last;
|
|
|
498 |
}
|
|
|
499 |
while( <CMD> ){} # Get rid of broken pipe messages
|
|
|
500 |
close( CMD );
|
|
|
501 |
|
|
|
502 |
return $ret;
|
|
|
503 |
}
|
|
|
504 |
|
|
|
505 |
#-------------------------------------------------------------------------------
|
|
|
506 |
# Function : get_newFiles
|
|
|
507 |
#
|
|
|
508 |
# Description : Calls 'cleartool ls -recurse' to get a list of clearcase
|
|
|
509 |
# objects in the working directory that have been
|
|
|
510 |
# checked in to clearcase only after the label was made
|
|
|
511 |
#
|
|
|
512 |
# Inputs :
|
|
|
513 |
#
|
|
|
514 |
# Returns : @newFiles - an array of files
|
|
|
515 |
#
|
|
|
516 |
sub get_newFiles()
|
|
|
517 |
{
|
|
|
518 |
Message ("Determine clearcase file versions for: $workingDirectory");
|
|
|
519 |
|
|
|
520 |
# Step 1: get list of files that are in the directory and in clearcase
|
|
|
521 |
my @candFiles = ();
|
|
|
522 |
{
|
|
|
523 |
my $cmd = QuoteCommand( 'cleartool', 'ls', '-recurse', $workingDirectory);
|
|
|
524 |
open( CMD, "$cmd 2>& 1 |") or Error("can't run command: $!");
|
|
|
525 |
|
|
|
526 |
while( <CMD> )
|
|
|
527 |
{
|
|
|
528 |
# Each line will be of the form (e.g.):
|
|
|
529 |
# ./LIB/JatsMakeConfig.pm@@/main/4 Rule: core_devl_2.73.2000.cr
|
|
|
530 |
|
|
|
531 |
s~[\n\r]+$~~;
|
|
|
532 |
next if( ! m/Rule:/ ); # We only want clearcase files - these will show with what rule
|
|
|
533 |
# they are in our view via some text like m/Rule: .*/.
|
|
|
534 |
|
|
|
535 |
(my $firstWord = $_) =~ s/^(\S+).*/$1/;
|
|
|
536 |
my ( $candFile, $candFileVersion) = split(/@@/, $firstWord);
|
|
|
537 |
|
|
|
538 |
push @candFiles, $candFile;
|
|
|
539 |
}
|
|
|
540 |
close( CMD );
|
|
|
541 |
}
|
|
|
542 |
|
|
|
543 |
my @newFiles = ();
|
|
|
544 |
|
|
|
545 |
# Step 2: See whether each candidate file is in the 'old' label
|
|
|
546 |
# If not, then it is a new file that has been added since the label was created
|
|
|
547 |
my $icandFile = 0;
|
|
|
548 |
foreach my $candFile (@candFiles)
|
|
|
549 |
{
|
|
|
550 |
$icandFile ++;
|
|
|
551 |
|
|
|
552 |
print "Running cleartool find on file $icandFile/" . scalar(@candFiles) . " \r";
|
|
|
553 |
|
|
|
554 |
my $isPartOfLabel = 0;
|
|
|
555 |
|
|
|
556 |
# This command will return no output if file is not part of label, else
|
|
|
557 |
# some output if it is part of the label. This provides an simple way of
|
|
|
558 |
# determining if the file is a new file that has been added since the label was created
|
|
|
559 |
my $cmd = qq(cleartool find $candFile -directory -version "{lbtype($opt_new_label)}" -print);
|
|
|
560 |
|
|
|
561 |
Verbose ("Cmd: '$cmd'");
|
|
|
562 |
open( CMD, "$cmd 2>& 1 |") or Error("can't run command: $!");
|
|
|
563 |
$isPartOfLabel = 1 if( <CMD> );
|
|
|
564 |
while( <CMD> ){} # Get rid of broken pipe messages
|
|
|
565 |
close( CMD );
|
|
|
566 |
|
|
|
567 |
push @newFiles, $candFile if( ! $isPartOfLabel );
|
|
|
568 |
}
|
|
|
569 |
|
|
|
570 |
return @newFiles;
|
|
|
571 |
}
|
|
|
572 |
|
|
|
573 |
#-------------------------------------------------------------------------------
|
|
|
574 |
# Function : get_prev_viewname
|
|
|
575 |
#
|
|
|
576 |
# Description : Works out the view in use when CCdiff.pl is invoked.
|
|
|
577 |
#
|
|
|
578 |
# Inputs :
|
|
|
579 |
#
|
|
|
580 |
# Returns : $prev_viewname
|
|
|
581 |
#
|
|
|
582 |
sub get_prev_viewname()
|
|
|
583 |
{
|
|
|
584 |
my $cmd = "cleartool pwv";
|
|
|
585 |
|
|
|
586 |
open( CMD, "$cmd 2>&1 |") or Error("can't run command: $!");
|
|
|
587 |
(my $firstline = <CMD>) =~ s~[\n\r]+$~~;
|
|
|
588 |
while( <CMD> ){} # Get rid of broken pipe messages
|
|
|
589 |
close( CMD );
|
|
|
590 |
|
|
|
591 |
if( $firstline !~ /^Working directory view: / || $firstline =~ / NONE / )
|
|
|
592 |
{
|
|
|
593 |
Error ("Cannot determine current view name",
|
|
|
594 |
"Path may not be a clearcase view");
|
|
|
595 |
}
|
|
|
596 |
|
|
|
597 |
(my $prev_viewname = $firstline) =~ s/^Working directory view: (\S+).*/$1/;
|
|
|
598 |
|
|
|
599 |
Verbose ("Previous viewname: '$prev_viewname'");
|
|
|
600 |
return $prev_viewname;
|
|
|
601 |
}
|
|
|
602 |
|
|
|
603 |
|
|
|
604 |
#-------------------------------------------------------------------------------
|
|
|
605 |
# Function : files_from_view
|
|
|
606 |
#
|
| 227 |
dpurdie |
607 |
# Description : Determine the list of files/versions in a given view
|
|
|
608 |
#
|
|
|
609 |
# Inputs : $vpath - Path to the view
|
| 229 |
dpurdie |
610 |
# $label - Label
|
| 227 |
dpurdie |
611 |
# $tag - File tag
|
|
|
612 |
#
|
|
|
613 |
# Returns : Nothing
|
|
|
614 |
# Populates the %files array
|
|
|
615 |
#
|
|
|
616 |
|
| 241 |
dpurdie |
617 |
sub files_from_view
|
| 227 |
dpurdie |
618 |
{
|
|
|
619 |
my ($vpath, $label, $tag) = @_;
|
|
|
620 |
my $cutlen = length ($vpath );
|
| 241 |
dpurdie |
621 |
Message ("Determine file versions for label: $label");
|
| 227 |
dpurdie |
622 |
|
|
|
623 |
#
|
|
|
624 |
# Ensure that the VOB is mounted
|
|
|
625 |
# The mount command MUST have the correct vob format
|
|
|
626 |
#
|
|
|
627 |
my $vob = $vpath;
|
|
|
628 |
$vob =~ s~^/+~~;
|
|
|
629 |
$vob = $VOB_SEP . $vob;
|
| 241 |
dpurdie |
630 |
ClearCmd ('mount',$vob);
|
| 227 |
dpurdie |
631 |
|
| 241 |
dpurdie |
632 |
my $cmd = qq(cleartool find "$opt_drive/$opt_viewname/$vpath" -all -follow -type f -element "lbtype_sub($label)" -version "lbtype_sub($label)" -print);
|
|
|
633 |
Verbose ("ClearTool: $cmd");
|
| 227 |
dpurdie |
634 |
|
|
|
635 |
open(CMD, "$cmd 2>&1 |") || Error "Can't run command: $!";
|
|
|
636 |
while (<CMD>)
|
|
|
637 |
{
|
| 241 |
dpurdie |
638 |
Verbose( "Label$tag: $_");
|
| 227 |
dpurdie |
639 |
my $file = $_;
|
| 241 |
dpurdie |
640 |
$file =~ s~[\n\r]+$~~;
|
|
|
641 |
$file =~ tr{\\/}{/}s;
|
| 227 |
dpurdie |
642 |
$files{$file}{$tag} = 1;
|
|
|
643 |
}
|
|
|
644 |
close(CMD);
|
| 241 |
dpurdie |
645 |
Verbose2 ("ClearTool Exit Status: $?");
|
|
|
646 |
|
|
|
647 |
Message ("There are " . scalar(keys %files) . " files in label $label");
|
| 227 |
dpurdie |
648 |
}
|
|
|
649 |
|
|
|
650 |
#-------------------------------------------------------------------------------
|
|
|
651 |
# Function : ClearDiff
|
|
|
652 |
#
|
|
|
653 |
# Description : Issue a cleartool command
|
|
|
654 |
# Filter out many of the stupid messages
|
|
|
655 |
#
|
|
|
656 |
# Inputs : Options and Command line
|
|
|
657 |
# Options:
|
|
|
658 |
#
|
|
|
659 |
# Returns : Error code
|
|
|
660 |
#
|
|
|
661 |
sub ClearDiff
|
|
|
662 |
{
|
|
|
663 |
my $header_seen = 0;
|
|
|
664 |
my $identical = 0;
|
| 241 |
dpurdie |
665 |
my $cmd = QuoteCommand("cleardiff", @_);
|
| 227 |
dpurdie |
666 |
|
| 241 |
dpurdie |
667 |
Verbose ("ClearDiff: $cmd");
|
|
|
668 |
|
| 227 |
dpurdie |
669 |
open(CMD, "$cmd 2>&1 |") || Error "can't run command: $!";
|
| 241 |
dpurdie |
670 |
|
| 227 |
dpurdie |
671 |
while (<CMD>)
|
|
|
672 |
{
|
|
|
673 |
$header_seen = 1
|
|
|
674 |
if ( m~^[*]{32}~ );
|
|
|
675 |
unless ( $header_seen )
|
|
|
676 |
{
|
| 241 |
dpurdie |
677 |
$identical = 1 if ( m~^Files are identical~ );
|
| 227 |
dpurdie |
678 |
next;
|
|
|
679 |
}
|
|
|
680 |
|
|
|
681 |
#
|
|
|
682 |
# Filter output from the user
|
|
|
683 |
#
|
|
|
684 |
s~(file [12]: )$view_path/~$1/~i;
|
|
|
685 |
print FO $_;
|
|
|
686 |
}
|
|
|
687 |
close(CMD);
|
|
|
688 |
|
|
|
689 |
#
|
|
|
690 |
# Ensure the section ends with a complete line
|
|
|
691 |
# An extra line doesn't affect CS parsing, but without it any file
|
|
|
692 |
# without a trailing \n will kill the header parsing
|
|
|
693 |
#
|
|
|
694 |
print FO "\n" if($header_seen);
|
|
|
695 |
|
| 241 |
dpurdie |
696 |
Verbose ("ClearDiff Exit Status: $?");
|
| 227 |
dpurdie |
697 |
|
|
|
698 |
return $header_seen, $identical;
|
|
|
699 |
}
|
|
|
700 |
|
|
|
701 |
#-------------------------------------------------------------------------------
|
|
|
702 |
# Function : ClearCmd
|
|
|
703 |
#
|
|
|
704 |
# Description : Execute a cleartool command
|
|
|
705 |
# Capture error messages only
|
|
|
706 |
#
|
|
|
707 |
# Inputs : Command to execute
|
|
|
708 |
#
|
|
|
709 |
# Returns : Exit code
|
|
|
710 |
# Also the global @error_list
|
|
|
711 |
#
|
|
|
712 |
sub ClearCmd
|
|
|
713 |
{
|
| 241 |
dpurdie |
714 |
my $cmd = QuoteCommand( @_ );
|
|
|
715 |
|
|
|
716 |
Verbose ("cleartool $cmd");
|
| 227 |
dpurdie |
717 |
|
| 241 |
dpurdie |
718 |
@error_list = ();
|
|
|
719 |
open(CMD, "cleartool $cmd 2>&1 |") || Error "can't run command: $!";
|
|
|
720 |
while (<CMD>)
|
|
|
721 |
{
|
|
|
722 |
s~[\n\r]+$~~;
|
|
|
723 |
Verbose2 ($_);
|
|
|
724 |
push @error_list, $_ if ( m~Error:~ );
|
|
|
725 |
}
|
|
|
726 |
close(CMD);
|
| 227 |
dpurdie |
727 |
|
| 241 |
dpurdie |
728 |
Verbose2 ("Exit Status: $?");
|
|
|
729 |
return ($?) / 256;
|
| 227 |
dpurdie |
730 |
}
|
|
|
731 |
|
|
|
732 |
#-------------------------------------------------------------------------------
|
|
|
733 |
# Function : LocateLabel
|
|
|
734 |
#
|
| 241 |
dpurdie |
735 |
# Description : Determine the VOBs that contains the specified label
|
| 227 |
dpurdie |
736 |
#
|
|
|
737 |
# Inputs : $label - Label to locate
|
|
|
738 |
#
|
| 241 |
dpurdie |
739 |
# Returns : First VOB that contains the label
|
| 227 |
dpurdie |
740 |
#
|
|
|
741 |
sub LocateLabel
|
|
|
742 |
{
|
|
|
743 |
my ($label) = @_;
|
|
|
744 |
|
|
|
745 |
Message ("Locate label in VOB: $label" );
|
| 241 |
dpurdie |
746 |
Verbose ("Ensure Label is found in a VOB");
|
| 227 |
dpurdie |
747 |
my $found = 0;
|
|
|
748 |
foreach my $vob ( @ROOT_VOBS )
|
|
|
749 |
{
|
| 241 |
dpurdie |
750 |
$vob = $UNIX_VOB_PREFIX . $vob if ( $UNIX && $vob !~ m~^${UNIX_VOB_PREFIX}~ );
|
| 227 |
dpurdie |
751 |
(my $vob_name = $vob) =~ s~/~$VOB_SEP~g;
|
|
|
752 |
|
|
|
753 |
Verbose2 ("Examine label $label in vob: $vob" );
|
|
|
754 |
|
|
|
755 |
my $cmd = "cleartool lstype \"lbtype:$label\@$vob_name\"";
|
|
|
756 |
open(CMD, "$cmd 2>&1 |") || Error( "can't run command: $!");
|
|
|
757 |
while (<CMD>)
|
|
|
758 |
{
|
|
|
759 |
#
|
|
|
760 |
# Filter output from the user
|
|
|
761 |
#
|
| 241 |
dpurdie |
762 |
s~[\n\r]+$~~;
|
|
|
763 |
Verbose2 ("lstype: $_");
|
| 227 |
dpurdie |
764 |
next if ( m~Error~ );
|
|
|
765 |
next unless ( m~label type~ );
|
|
|
766 |
$found = $vob;
|
|
|
767 |
last;
|
|
|
768 |
}
|
| 241 |
dpurdie |
769 |
while( <CMD> ){} # Get rid of broken pipe messages
|
| 227 |
dpurdie |
770 |
close(CMD);
|
|
|
771 |
last if ( $found );
|
|
|
772 |
}
|
|
|
773 |
|
|
|
774 |
Error ("Label $label not found in @ROOT_VOBS")
|
|
|
775 |
unless ( $found );
|
|
|
776 |
|
|
|
777 |
Verbose ("Label $label found in $found");
|
|
|
778 |
return $found;
|
|
|
779 |
}
|
|
|
780 |
|
|
|
781 |
|
|
|
782 |
#-------------------------------------------------------------------------------
|
|
|
783 |
# Function : element0
|
|
|
784 |
#
|
|
|
785 |
# Description : Given a branch version, this function will return the
|
|
|
786 |
# zero-th element on the branch
|
|
|
787 |
#
|
|
|
788 |
# ie: /DPG_SWBase/file@@some_branch/12
|
|
|
789 |
# -> /DPG_SWBase/file@@some_branch/0
|
|
|
790 |
#
|
|
|
791 |
# Inputs : $element
|
|
|
792 |
#
|
|
|
793 |
# Returns : as described
|
|
|
794 |
#
|
|
|
795 |
sub element0
|
|
|
796 |
{
|
|
|
797 |
my ($element) = @_;
|
| 241 |
dpurdie |
798 |
$element =~ s{/\d+$}{/0};
|
| 227 |
dpurdie |
799 |
return $element;
|
|
|
800 |
}
|
|
|
801 |
|
|
|
802 |
#-------------------------------------------------------------------------------
|
|
|
803 |
# Function : StripView
|
|
|
804 |
#
|
|
|
805 |
# Description : Strips the view nae from a file
|
|
|
806 |
#
|
|
|
807 |
# Inputs : $name - A pathname with view name prefix
|
|
|
808 |
#
|
|
|
809 |
# Returns : The name without the view name
|
|
|
810 |
#
|
|
|
811 |
my $StripView_len;
|
|
|
812 |
sub StripView
|
|
|
813 |
{
|
|
|
814 |
my ($name) = @_;
|
|
|
815 |
|
|
|
816 |
#
|
|
|
817 |
# Determine the length to strip off - once
|
|
|
818 |
#
|
|
|
819 |
unless ( $StripView_len )
|
|
|
820 |
{
|
|
|
821 |
$StripView_len = length($view_path);
|
|
|
822 |
}
|
|
|
823 |
|
|
|
824 |
return substr ($name, $StripView_len );
|
|
|
825 |
}
|
|
|
826 |
|
|
|
827 |
|
|
|
828 |
#-------------------------------------------------------------------------------
|
|
|
829 |
# Documentation
|
|
|
830 |
#
|
|
|
831 |
|
|
|
832 |
=pod
|
|
|
833 |
|
|
|
834 |
=head1 NAME
|
|
|
835 |
|
|
|
836 |
CCdiff - ClearCase Difference Report
|
|
|
837 |
|
|
|
838 |
=head1 SYNOPSIS
|
|
|
839 |
|
|
|
840 |
jats CCdiff [options] [[old_label] new-label]
|
|
|
841 |
|
|
|
842 |
Options:
|
|
|
843 |
-help - brief help message
|
|
|
844 |
-help -help - Detailed help message
|
|
|
845 |
-man - Full documentation
|
|
|
846 |
-old=label - Old label (optional)
|
| 241 |
dpurdie |
847 |
-new=label - New label (or dir=path) (mandatory)
|
| 227 |
dpurdie |
848 |
-output=file - Output filename
|
|
|
849 |
-vob=name - Vob for labels
|
|
|
850 |
-drive=path - Alternate vob location
|
|
|
851 |
|
|
|
852 |
=head1 OPTIONS
|
|
|
853 |
|
|
|
854 |
=over 8
|
|
|
855 |
|
|
|
856 |
=item B<-help>
|
|
|
857 |
|
|
|
858 |
Print a brief help message and exits.
|
|
|
859 |
|
|
|
860 |
=item B<-help -help>
|
|
|
861 |
|
|
|
862 |
Print a detailed help message with an explanation for each option.
|
|
|
863 |
|
|
|
864 |
=item B<-man>
|
|
|
865 |
|
|
|
866 |
Prints the manual page and exits.
|
|
|
867 |
|
|
|
868 |
=item B<-old=label>
|
|
|
869 |
|
|
|
870 |
This option specifies the old, or base, label for the difference report. This
|
|
|
871 |
option is not required when a new package is being processed.
|
|
|
872 |
|
|
|
873 |
=item B<-new=label>
|
|
|
874 |
|
|
|
875 |
This option specifies the new, or current, label for the difference report. This
|
|
|
876 |
label is mandatory for the difference report.
|
|
|
877 |
|
| 241 |
dpurdie |
878 |
The label may be of the form dir=path to force the utility to use a
|
|
|
879 |
local view or path. You may also use '-new=current', or -new=current=path,
|
|
|
880 |
as in jats CCbc2.
|
|
|
881 |
|
| 227 |
dpurdie |
882 |
The old and new labels may be provided on the command line, or via named
|
|
|
883 |
options, but not both.
|
|
|
884 |
|
|
|
885 |
=item B<-vob=name>
|
|
|
886 |
|
|
|
887 |
This option limits the label search to the specified VOB. This option may be
|
|
|
888 |
needed if the labels are to be found in multiple VOBs.
|
|
|
889 |
|
|
|
890 |
This option may be used multiple times. All specified vobs will be searched and
|
|
|
891 |
the first one containing the label will be used.
|
|
|
892 |
|
|
|
893 |
=item B<-output=file>
|
|
|
894 |
|
|
|
895 |
This option specifies the output filename. The program will generate an output
|
|
|
896 |
file based on the two source labels.
|
|
|
897 |
|
|
|
898 |
=item B<-drive=path>
|
|
|
899 |
|
|
|
900 |
This option allows the user to provide an alternate location for the
|
|
|
901 |
administration vob used by the program. The default location is:
|
|
|
902 |
|
|
|
903 |
=over 8
|
|
|
904 |
|
|
|
905 |
=item * Windows o:
|
|
|
906 |
|
|
|
907 |
=item * Unix /view
|
|
|
908 |
|
|
|
909 |
=back
|
|
|
910 |
|
|
|
911 |
=head1 DESCRIPTION
|
|
|
912 |
|
|
|
913 |
This program is the primary tool for creating 'diff' reports to be uploaded to
|
|
|
914 |
Code Striker.
|
|
|
915 |
|
|
|
916 |
The program will determine the files that are different between the two specified
|
|
|
917 |
labels. It will determine full pathnames for the files and create a difference
|
|
|
918 |
report that is suitable for Code Striker.
|
|
|
919 |
|
|
|
920 |
The program uses a global administration view for the purposes of determining
|
|
|
921 |
file versions. The path names that are generated are full vob-extended pathnames.
|
|
|
922 |
These may be very long and may not be directly usable under windows.
|
|
|
923 |
|
|
|
924 |
=cut
|
|
|
925 |
|