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
10
#                 to Code Stricker.
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
19
use Getopt::Long;
20
 
21
my $VERSION = "1.0.0";                      # Update this
22
 
23
 
24
#
25
#   Globals - Provided by the JATS environment
26
#
27
my $UNIX            = $ENV{'GBE_UNIX'};
28
 
29
#
30
#   Options
31
#
32
my $opt_debug   = $ENV{'GBE_DEBUG'};        # Allow global debug
33
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
34
my $opt_help = 0;
35
my $opt_manual = 0;
36
my $opt_drive = $UNIX ? '/view' : 'o:';
37
my $opt_viewname = 'administration_view';
38
my $opt_outfile;
39
my @opt_vobs;
40
my $opt_new_label;
41
my $opt_old_label;
42
 
43
#
44
#   Globals
45
#
46
my @error_list;                             # ClearCmd detected errors
47
my $UNIX_VOB_PREFIX = '/vobs';
48
my $VOB_SEP         = $UNIX ? '/' : '\\';
49
my $view_path;
50
my @view_tags;
51
my %files;
52
my %diffs;
53
 
54
#
55
#   ROOT_VOBS is a list of VOBS too look in first
56
#   If a label is not found in these vobs, then the program will
57
#   look in all vobs. This list is a hint to speed up searching
58
#
59
my @ROOT_VOBS = qw( /LMOS /DPG_SWBase /DPG_SWCode /ProjectCD /MASS_Dev_Bus
60
                    /MASS_Dev_Infra /MOS /MASS_Dataman /MASS_Dev /MASS_Dev_Dataman
61
                    /COTS /GMPTE2005 /GMPTE2005_obe /MPR /MOS );
62
 
63
 
64
 
65
#-------------------------------------------------------------------------------
66
# Function        : Mainline Entry Point
67
#
68
# Description     :
69
#
70
# Inputs          :
71
#
72
 
73
#
74
#   Parse the user options
75
#
76
my $result = GetOptions (
77
                "help+"         => \$opt_help,              # flag, multiple use allowed
78
                "manual"        => sub{ $opt_help = 3},     # flag, multiple use allowed
79
                "verbose+"      => \$opt_verbose,           # flag, multiple use allowed
229 dpurdie 80
                "output=s"      => \$opt_outfile,           # String
227 dpurdie 81
                "new=s"         => \$opt_new_label,         # String
229 dpurdie 82
                "old=s"         => \$opt_old_label,         # String
227 dpurdie 83
                "drive=s"       => \$opt_drive,             # String
84
                "vob=s"         => \@opt_vobs,              # String
85
                );
86
 
87
                #
88
                #   UPDATE THE DOCUMENTATION AT THE END OF THIS FILE !!!
89
                #
90
 
91
#
92
#   Process help and manual options
93
#
94
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result );
95
pod2usage(-verbose => 1)  if ($opt_help == 2);
96
pod2usage(-verbose => 2)  if ($opt_help > 2);
97
 
98
#
99
#   Configure the error reporting process now that we have the user options
100
#
101
ErrorConfig( 'name'    => 'CCDIFF',
102
             'verbose' => $opt_verbose );
103
 
104
#
105
#   Be nice to the user
106
#   If we have two options and no labels, then assigne them
107
#
108
if ( ! $opt_new_label && ! $opt_old_label )
109
{
110
    Error ("Must provide two labels on command line unless they are provided via -old and -new options")
111
         if ( $#ARGV < 1 );
112
 
113
    $opt_old_label = shift @ARGV;
114
    $opt_new_label = shift @ARGV;
115
}
116
 
117
#
118
#   Error check the user arguments
119
#
120
 
121
Error ("Need to provide the 'new' label")
122
    unless ( $opt_new_label );
123
 
124
Error ("Too many command line arguments" )
125
    unless ( $#ARGV < 0 );
126
 
127
#
128
#   Generate a default ouput put file name
129
#
130
unless ( $opt_outfile )
131
{
132
    if ( $opt_old_label )
133
    {
134
        $opt_outfile = "${opt_old_label}-${opt_new_label}-diff.txt";
135
    }
136
    else
137
    {
138
        $opt_outfile = "${opt_new_label}-diff.txt";
139
    }
140
}
141
Verbose ("Outout file: $opt_outfile");
142
 
143
#
144
#   Determine the machine type
145
#
146
Verbose ("Machine Type: UNIX=$UNIX");
147
 
148
#
149
#   Ensure that the 'cleartool' program can be located
150
#
151
Verbose ("Locate clearcase utility in users path");
152
Error ("Cannot locate the 'cleartool' utility in the users PATH")
153
    unless ( LocateProgInPath('cleartool', '--All') );
154
 
155
#
156
#   Ensure that the 'administration_view' is availalable
157
#   Then start the view, before checking its availability
158
#
159
if ( ClearCmd ( "lsview $opt_viewname" ) )
160
{
161
    Error ("Required view not found: $opt_viewname",
162
           "This is a dynamic view that should exist as it is used by the build system"
163
          );
164
}
165
 
166
if ( ClearCmd ( "startview $opt_viewname" ) )
167
{
168
    Error ("Cannot start the required view: $opt_viewname");
169
}
170
 
171
$view_path = "$opt_drive/$opt_viewname";
172
$view_path .= $UNIX_VOB_PREFIX if ( $UNIX );
173
if ( ! -d $view_path  )
174
{
175
    Error ("Cannot locate the required dynamic view: $view_path",
176
            "The view exits and has been started. It cannot be found"
177
          );
178
}
179
 
180
#
181
#
182
#   Extend the list of ROOT_VOBS with all the known vobs
183
#   The initial ROOT_VOBS are treated as a "hint" to assist searching
184
#
185
if ( @opt_vobs )
186
{
187
    @ROOT_VOBS = ();
188
    foreach my $vob ( @opt_vobs )
189
    {
190
        $vob = '/' . $vob;
191
        $vob =~ s~^$UNIX_VOB_PREFIX~~ if ($UNIX);
192
        $vob =~ tr~\\/~/~s;
193
        push @ROOT_VOBS, $vob;
194
    }
195
}
196
else
197
{
198
    my $cmd = "cleartool lsvob -short";
199
    open(CMD, "$cmd 2>&1 |") || Error( "can't run command: $!");
200
    while (<CMD>)
201
    {
202
        #
203
        #   Filter output from the user
204
        #
205
        chomp;
206
        s~^$UNIX_VOB_PREFIX~~ if ($UNIX);
207
        Verbose2("lsvob: $_");
208
        tr~\\/~/~s;
209
        push @ROOT_VOBS, $_;
210
    }
211
    close(CMD);
212
}
213
 
214
#
215
#   Ensure the two labels are present - determine the VOB root
216
#
217
my $l1_vob = LocateLabel( $opt_old_label) if $opt_old_label;
218
my $l2_vob = LocateLabel( $opt_new_label);
219
 
220
#
221
#   Locate all files for the two labels
222
#
223
files_from_from_view( $l1_vob, ,$opt_old_label, 1 ) if $opt_old_label;;
224
files_from_from_view( $l2_vob, ,$opt_new_label, 2 );
225
 
226
#DebugDumpData ("Files", \%files );
227
 
228
#
229
#   Create a hash of files that are different
230
#   The hash key will be the file name
231
#   The tag will be the branch that the file is on
232
#
233
foreach my $file ( sort keys %files )
234
{
235
    #
236
    #   These files are the same
237
    #
238
    next if ( $files{$file}{1} && $files{$file}{2} );
239
 
240
    my $tag = 1;
241
    $tag = 2 if $files{$file}{2};
242
 
243
    #
244
    #   Break path into file and version
245
    #
246
    $file =~ m~(.*)(@@[^@]*$)~;
247
    my ($f,$b) = ($1,$2);
248
    $diffs{$f}{$tag} = $file;
249
 
250
#    print "$file\n";
251
}
252
 
253
#
254
#   Process files that are common, but have changed
255
#
256
my @no_text;
257
my $added = 0;
258
my $deleted = 0;
259
my $diffs = 0;
260
my $funny = 0;
261
open (FO, ">", $opt_outfile) || Error ("Cannot open file: $opt_outfile");
262
foreach my $file ( sort keys %diffs )
263
{
264
    my ($hs, $id, $type);
265
    #
266
    #   Files are are common
267
    #
268
    if ( $diffs{$file}{1} && $diffs{$file}{2} )
269
    {
270
        $type = "different";
233 dpurdie 271
        ($hs, $id) = ClearDiff("-serial_format", "-blank_ignore", $diffs{$file}{1}, $diffs{$file}{2});
227 dpurdie 272
        $diffs++ if ( $hs );
273
    }
274
    elsif ($diffs{$file}{1} )
275
    {
276
        #
277
        #   File has been deleted
278
        #
279
        $type = "deleted";
280
        Message ("$file has been deleted");
281
        ($hs, $id) = ClearDiff("-serial_format", $diffs{$file}{1}, element0($diffs{$file}{1}) );
282
        $deleted++ if ( $hs );
283
    }
284
    else
285
    {
286
        #
287
        #   File has been added
288
        #
289
        $type = "added";
290
        ($hs, $id) = ClearDiff("-serial_format", element0($diffs{$file}{2}) , $diffs{$file}{2} );
291
        $added++ if ( $hs );
292
    }
293
 
294
    $type = "identical"
295
        if ( $id  );
296
    $file = StripView($file);
297
    Message ("$type: $file" );
298
 
299
    unless ( $hs || $id )
300
    {
301
        push @no_text, $file;
302
        $funny ++;
303
    }
304
}
305
close FO;
306
 
307
#
308
#   Warn about problem files
309
#
310
if ( @no_text )
311
{
312
    Warning ("The following files did not generate any difference report, although",
313
             "they are different. They may be binary files:", @no_text);
314
}
315
 
316
#
317
#   Summary information
318
#
319
Information ("Summary Information",
320
             "Old Label:         : " . ( $opt_old_label ? $opt_old_label : '-None-') ,
321
             "New Label:         : $opt_new_label",
322
             "Files different    : $diffs",
323
             "Files added        : $added",
324
             "Files deleted      : $deleted",
325
             "Files not in report: $funny",
326
             "Output file        : $opt_outfile",
327
             );
328
 
329
 
330
#DebugDumpData ("Files", \%diffs);
331
 
332
exit (0);
333
 
334
#-------------------------------------------------------------------------------
335
# Function        : files_from_from_view
336
#
337
# Description     : Determine the list of files/versions in a given view
338
#
339
# Inputs          : $vpath          - Path to the view
229 dpurdie 340
#                   $label          - Label
227 dpurdie 341
#                   $tag            - File tag
342
#
343
# Returns         : Nothing
344
#                   Populates the %files array
345
#
346
 
347
sub files_from_from_view
348
{
349
    my ($vpath, $label, $tag) = @_;
350
    my $cutlen = length ($vpath );
351
    Message("Determine file versions for: $label");
352
 
353
    #
354
    #   Ensure that the VOB is mounted
355
    #   The mount command MUST have the correct vob format
356
    #
357
    my $vob = $vpath;
358
    $vob =~ s~^/+~~;
359
    $vob = $VOB_SEP . $vob;
360
    ClearCmd ("mount $vob" );
361
 
362
 
363
    my $cmd = "cleartool find $opt_drive/$opt_viewname/$vpath -all -follow -type f -element \"lbtype_sub($label)\" -version \"lbtype_sub($label)\" -print";
364
    Verbose ("ClearTool: $cmd");
365
    open(CMD, "$cmd 2>&1 |") || Error "Can't run command: $!";
366
    while (<CMD>)
367
    {
368
        print "Label$tag: $_" if $opt_verbose;
369
        my $file = $_;
370
        $file =~ s~[\r\n]+$~~;
371
        $file =~ tr~\\/~/~s;
372
        $files{$file}{$tag} = 1;
373
    }
374
    close(CMD);
375
    Verbose2 "ClearTool Exit Status: $?";
376
}
377
 
378
#-------------------------------------------------------------------------------
379
# Function        : ClearDiff
380
#
381
# Description     : Issue a cleartool command
382
#                   Filter out many of the stupid messages
383
#
384
# Inputs          : Options and Command line
385
#                   Options:
386
#
387
# Returns         : Error code
388
#
389
sub ClearDiff
390
{
391
    my $header_seen = 0;
392
    my $identical = 0;
393
    my $cmd = "cleardiff " . QuoteCommand (@_);
394
 
395
    Verbose ("ClearDiff: $cmd");
396
    open(CMD, "$cmd 2>&1 |") || Error "can't run command: $!";
397
    while (<CMD>)
398
    {
399
        $header_seen = 1
400
            if ( m~^[*]{32}~ );
401
        unless ( $header_seen )
402
        {
403
            if ( m~^Files are identical~ )
404
            {
405
                $identical = 1;
406
                next;
407
            }
408
            next;
409
        }
410
 
411
        #
412
        #   Filter output from the user
413
        #
414
        s~(file [12]: )$view_path/~$1/~i;
415
        print FO $_;
416
    }
417
    close(CMD);
418
 
419
    #
420
    #   Ensure the section ends with a complete line
421
    #   An extra line doesn't affect CS parsing, but without it any file
422
    #   without a trailing \n will kill the header parsing
423
    #
424
    print FO "\n" if($header_seen);
425
 
426
    Verbose "ClearDiff Exit Status: $?";
427
 
428
    return $header_seen, $identical;
429
}
430
 
431
#-------------------------------------------------------------------------------
432
# Function        : ClearCmd
433
#
434
# Description     : Execute a cleartool command
435
#                   Capture error messages only
436
#
437
# Inputs          : Command to execute
438
#
439
# Returns         : Exit code
440
#                   Also the global @error_list
441
#
442
sub ClearCmd
443
{
444
    my( $cmd ) = @_;
445
    Verbose "cleartool $cmd";
446
 
447
        @error_list = ();
448
        open(CMD, "cleartool $cmd  2>&1 |")    || Error "can't run command: $!";
449
        while (<CMD>)
450
        {
451
            chomp;
452
            Verbose2 ($_);
453
            push @error_list, $_ if ( m~Error:~ );
454
        }
455
        close(CMD);
456
 
457
    Verbose2 "Exit Status: $?";
458
    return $? / 256;
459
}
460
 
461
#-------------------------------------------------------------------------------
462
# Function        : LocateLabel
463
#
464
# Description     : Determine the VOBs that conatins the specified label
465
#
466
# Inputs          : $label  - Label to locate
467
#
468
# Returns         : First VOB that conatins the label
469
#
470
sub LocateLabel
471
{
472
    my ($label) = @_;
473
 
474
    Message ("Locate label in VOB: $label" );
475
    Verbose("Ensure Label is found in a VOB");
476
    my $found = 0;
477
    foreach my $vob ( @ROOT_VOBS )
478
    {
479
        $vob = $UNIX_VOB_PREFIX . $vob if ( $UNIX );
480
        (my $vob_name = $vob) =~ s~/~$VOB_SEP~g;
481
 
482
        Verbose2 ("Examine label $label in vob: $vob" );
483
 
484
        my $cmd = "cleartool lstype \"lbtype:$label\@$vob_name\"";
485
        open(CMD, "$cmd 2>&1 |") || Error( "can't run command: $!");
486
        while (<CMD>)
487
        {
488
            #
489
            #   Filter output from the user
490
            #
491
            chomp;
492
            Verbose2("lstype: $_");
493
            next if ( m~Error~ );
494
            next unless ( m~label type~ );
495
            $found = $vob;
496
            last;
497
        }
498
        close(CMD);
499
        last if ( $found );
500
    }
501
 
502
    Error ("Label $label not found in @ROOT_VOBS")
503
        unless ( $found );
504
 
505
    Verbose ("Label $label found in $found");
506
    return $found;
507
}
508
 
509
 
510
#-------------------------------------------------------------------------------
511
# Function        : element0
512
#
513
# Description     : Given a branch version, this function will return the
514
#                   zero-th element on the branch
515
#
516
#                   ie: /DPG_SWBase/file@@some_branch/12
517
#                   ->  /DPG_SWBase/file@@some_branch/0
518
#
519
# Inputs          : $element
520
#
521
# Returns         : as described
522
#
523
sub element0
524
{
525
    my ($element) = @_;
526
    $element =~ s~/\d+$~/0~;
527
    return $element;
528
}
529
 
530
#-------------------------------------------------------------------------------
531
# Function        : StripView
532
#
533
# Description     : Strips the view nae from a file
534
#
535
# Inputs          : $name       - A pathname with view name prefix
536
#
537
# Returns         : The name without the view name
538
#
539
my $StripView_len;
540
sub StripView
541
{
542
    my ($name) = @_;
543
 
544
    #
545
    #   Determine the length to strip off - once
546
    #
547
    unless ( $StripView_len )
548
    {
549
        $StripView_len = length($view_path);
550
    }
551
 
552
    return substr ($name, $StripView_len );
553
}
554
 
555
 
556
#-------------------------------------------------------------------------------
557
#   Documentation
558
#
559
 
560
=pod
561
 
562
=head1 NAME
563
 
564
CCdiff - ClearCase Difference Report
565
 
566
=head1 SYNOPSIS
567
 
568
  jats CCdiff [options] [[old_label] new-label]
569
 
570
 Options:
571
    -help              - brief help message
572
    -help -help        - Detailed help message
573
    -man               - Full documentation
574
    -old=label         - Old label (optional)
575
    -new=label         - New label (mandatory)
576
    -output=file       - Output filename
577
    -vob=name          - Vob for labels
578
    -drive=path        - Alternate vob location
579
 
580
=head1 OPTIONS
581
 
582
=over 8
583
 
584
=item B<-help>
585
 
586
Print a brief help message and exits.
587
 
588
=item B<-help -help>
589
 
590
Print a detailed help message with an explanation for each option.
591
 
592
=item B<-man>
593
 
594
Prints the manual page and exits.
595
 
596
=item B<-old=label>
597
 
598
This option specifies the old, or base, label for the difference report. This
599
option is not required when a new package is being processed.
600
 
601
=item B<-new=label>
602
 
603
This option specifies the new, or current, label for the difference report. This
604
label is mandatory for the difference report.
605
 
606
The old and new labels may be provided on the command line, or via named
607
options, but not both.
608
 
609
=item B<-vob=name>
610
 
611
This option limits the label search to the specified VOB. This option may be
612
needed if the labels are to be found in multiple VOBs.
613
 
614
This option may be used multiple times. All specified vobs will be searched and
615
the first one containing the label will be used.
616
 
617
=item B<-output=file>
618
 
619
This option specifies the output filename. The program will generate an output
620
file based on the two source labels.
621
 
622
=item B<-drive=path>
623
 
624
This option allows the user to provide an alternate location for the
625
administration vob used by the program. The default location is:
626
 
627
=over 8
628
 
629
=item * Windows o:
630
 
631
=item * Unix /view
632
 
633
=back
634
 
635
=head1 DESCRIPTION
636
 
637
This program is the primary tool for creating 'diff' reports to be uploaded to
638
Code Striker.
639
 
640
The program will determine the files that are different between the two specified
641
labels. It will determine full pathnames for the files and create a difference
642
report that is suitable for Code Striker.
643
 
644
The program uses a global administration view for the purposes of determining
645
file versions. The path names that are generated are full vob-extended pathnames.
646
These may be very long and may not be directly usable under windows.
647
 
648
=cut
649