Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
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