Subversion Repositories DevTools

Rev

Rev 6177 | Rev 7213 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
383 dpurdie 1
########################################################################
6177 dpurdie 2
# COPYRIGHT - VIX IP PTY LTD ("VIX"). ALL RIGHTS RESERVED.
383 dpurdie 3
#
4
# Module name   : jats_vcsdiff.pl
5
# Module type   : Makefile system
6
# Compiler(s)   : Perl
7
# Environment(s): jats
8
#
9
# Description   : Create two views and DIFF them
10
#                 The views can be any type understood by JATS
11
#                 Can:
12
#                   - Compare with MD5SUms
13
#                   - Invoke BeyondCompare
14
#
15
#......................................................................#
16
 
17
require 5.008_002;
18
use strict;
19
use warnings;
20
 
21
use Pod::Usage;
22
use Getopt::Long;
23
 
24
use JatsError;
25
use JatsSystem;
26
use FileUtils;
27
use Cwd;
28
 
29
my $VERSION = "1.0.0";                      # Update this
30
 
31
#
32
#   Options
33
#
34
my $opt_debug   = $ENV{'GBE_DEBUG'};        # Allow global debug
35
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
36
my $opt_help = 0;
37
my $opt_manual = 0;
38
my $opt_new_label;
39
my $opt_old_label;
40
my $opt_md5check;
41
my $opt_mode;
2931 dpurdie 42
my $opt_diff;
6085 dpurdie 43
my @opt_options;
383 dpurdie 44
 
45
#
46
#   Globals - Provided by the JATS environment
47
#
48
my $USER            = $ENV{'USER'};
49
my $UNIX            = $ENV{'GBE_UNIX'};
50
my $TMP             = $UNIX ? "/tmp" : $ENV{'TMP'};
51
my $MACHINENAME     = $ENV{'GBE_HOSTNAME'};
52
 
53
#
54
#   Globals
55
#
2931 dpurdie 56
my $Name            = 'BeyondCompare';
3967 dpurdie 57
my $DiffProg;
2931 dpurdie 58
my @DiffArgs;
59
my $DiffWait;
383 dpurdie 60
my @view_tags;
61
my @view_commands;
62
my @cleanFiles;
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,              # Help level
78
                "manual"        => \$opt_manual,            # Help level
79
                "verbose:+"     => \$opt_verbose,           # Verbosity
80
                "debug:+"       => \$opt_debug,             # Debug Verbosity
81
                "new=s"         => \$opt_new_label,         # Path1
82
                "old=s"         => \$opt_old_label,         # Path2
83
                'check'         => \$opt_md5check,          # Force MD5 Check
2931 dpurdie 84
                'diff!'         => \$opt_diff,              # Force use of diff
6085 dpurdie 85
                'option=s'      => \@opt_options,           # User options
383 dpurdie 86
                );
87
 
88
                #
89
                #   UPDATE THE DOCUMENTATION AT THE END OF THIS FILE !!!
90
                #
91
 
92
#
93
#   Process help and manual options
94
#
95
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result );
96
pod2usage(-verbose => 1)  if ($opt_help == 2 );
97
pod2usage(-verbose => 2)  if ($opt_manual || ($opt_help > 2));
98
 
99
InitFileUtils();
100
 
101
#
102
#   Configure the error reporting process now that we have the user options
103
#
104
ErrorConfig( 'name'    => 'VCSDIFF',
105
             'verbose' => $opt_verbose,
106
             'debug'   => $opt_debug );
107
 
2931 dpurdie 108
Error ("Options -check and -diff cannot be combined")
109
    if ( $opt_md5check && $opt_diff );
110
 
383 dpurdie 111
#
112
#   Determine mode
113
#   Not all modes work on all machines
114
#
115
Verbose ("Machine Type: UNIX=$UNIX");
116
if ( $opt_md5check )
117
{
118
    $opt_mode = 'md5';
119
}
2931 dpurdie 120
elsif ( $UNIX || $opt_diff )
121
{
122
    $opt_mode = 'diff';
123
    $Name = 'diff';
124
    push @DiffArgs, '-r';
125
    $Name = 'gdiff';
126
    $DiffProg = LocateProgInPath( $Name, '--All');
127
    unless ( $DiffProg =~ m~/~ )
128
    {
129
        $Name = 'diff';
130
        $DiffProg = LocateProgInPath( $Name, '--All');
131
    }
132
 
133
    Error ("Cannot locate a 'diff' utility in the users PATH")
134
        unless ( $DiffProg =~ m~/~ );
135
}
383 dpurdie 136
else
137
{
138
    $opt_mode = 'bc2';
2931 dpurdie 139
    $DiffWait = 1;
383 dpurdie 140
 
141
    #
3967 dpurdie 142
    #   Determine the path to Beyond Compare Exe
143
    #       It may not be installed in the default place, but the Windows
144
    #       registry will know where it is
383 dpurdie 145
    #
3967 dpurdie 146
    GetBeyondCompareExePath();
383 dpurdie 147
}
148
 
149
#
150
#   Validate user options
151
#
152
#   Be nice to the user
153
#   If we have two options and no labels, then assign them
154
#
155
if ( ! $opt_new_label && ! $opt_old_label )
156
{
157
    Error ("Must provide two labels on command line unless they are provided via -old and -new options")
158
         if ( $#ARGV < 1 );
159
 
160
    $opt_old_label = shift @ARGV;
161
    $opt_new_label = shift @ARGV;
162
}
163
 
164
Error ("Need two labels on the command line, or via options")
165
    unless ( $opt_old_label && $opt_new_label );
166
 
167
Error ("Too many command line arguments" )
168
    unless ( $#ARGV < 0 );
169
 
170
#
171
#   Extract parameters that will be used to create a view that is
172
#   unique. Will use hostname and user name
173
#
174
Error ("Machine Name not determined")
175
    unless ( $MACHINENAME );
176
 
177
Error ("USER name not determined" )
178
    unless ( $USER );
179
 
180
#
181
#   Need a TMP working directory
182
#   Used to create config files
183
#
184
Error ("TMP not found or not a directory")
185
    unless ( $TMP && -d $TMP );
186
$TMP = "$TMP/$$";
187
 
188
#
189
#   Create views for the two views
190
#   Verify that the view are present
191
#
192
Message ("Constructing views");
193
my $path1 = create_view( $opt_old_label, 1 );
194
my $path2 = create_view( $opt_new_label, 2 );
195
 
196
Error ("Cannot locate view directory: $path1" ) unless (-d $path1);
197
Error ("Cannot locate view directory: $path2" ) unless (-d $path2);
198
 
199
#
200
#   If one of the paths is a dynamic view and the other is a local path
201
#   then attempt to locate the common directories
202
#
203
if ( $#view_tags == 0 )
204
{
205
    massage_paths();
206
}
207
 
208
if ( $opt_md5check )
209
{
210
    Verbose ("Performing MD5 Check");
211
    my $checkfile = 'vcsdiff_md5.txt';
212
    my $rv;
213
    push @cleanFiles, $checkfile;
214
    $rv = JatsTool ('jats_manifest', '-quiet',
215
                '-manifest', $checkfile,
216
                '-rootdir', $path1 );
217
 
218
    $rv = JatsTool ('jats_manifest', '-quiet', '-check',
219
                '-manifest', $checkfile,
220
                '-rootdir', $path2 ) unless $rv;
221
 
222
    exit $rv;
223
}
224
 
2931 dpurdie 225
#
226
#   Diffing the paths
227
#   Will use BeyondCompare under Windows
228
#   Will use diff under unix
229
#
230
Message ("Using '$Name' to compare two views",
231
         "Wait for utility to exit so that we can delete the views" ) if ($DiffWait);
383 dpurdie 232
 
2931 dpurdie 233
Verbose ("Diff Utility: $DiffProg");
6085 dpurdie 234
System ( $DiffProg, @DiffArgs, split(/,/, join (',', @opt_options)), $path1, $path2 );
383 dpurdie 235
exit 0;
236
 
237
#-------------------------------------------------------------------------------
238
# Function        : create_view
239
#
240
# Description     : Create dynamic view, based on a Vcs Tag
241
#
242
# Inputs          : $vcstag
243
#
244
# Returns         : Path to the view
245
#
246
sub create_view
247
{
248
    my ($vcstag, $num) = @_;
249
 
250
    #
251
    #   Intercept and treat the special label 'current'
252
    #
253
    return create_path_view( $vcstag )
254
        if ( $vcstag eq 'current'  || $vcstag =~ m~^dir=.+~ || $vcstag =~ m~^current=.+~ );
255
 
256
    my $tag = "${USER}_${MACHINENAME}_vcsdiff_${num}";
257
    push @view_tags, $tag;
258
 
259
    #
260
    #   Use vcsrelease to do the hard work
261
    #
262
    my @command = ( 'jats_vcsrelease',
263
                        '-extractfiles',
264
                        '-root=.' ,
265
                        '-noprefix',
1403 dpurdie 266
                        '-devmode=escrow',
383 dpurdie 267
                        '-view', $tag ,
268
                        '-label', $vcstag,
269
                   );
270
    push @view_commands, \@command;
271
 
272
    if ( $opt_debug && -d $tag )
273
    {
274
        Message ("Using existing view");
275
    }
276
    else
277
    {
278
        JatsTool( @command );
279
    }
280
 
281
    #
282
    #   Minor Kludge
283
    #       Should be in a library
284
    #   Iff CC::, then process path info too
285
    #
286
    if ( $vcstag =~ m~^CC::(.*?)(::(.+))?$~ )
287
    {
288
        my $path = $1;
289
        if ( $path )
290
        {
291
            my $try = $tag . '/' . $path;
292
            if ( -d  $try )
293
            {
294
                $tag = $try;
295
            }
296
        }
297
    }
298
 
299
    return $tag;
300
}
301
 
302
#-------------------------------------------------------------------------------
303
# Function        : create_path_view
304
#
305
# Description     : Not using a view, using a path
306
#                   Return the path as requested
307
#
308
# Inputs          : $label                  - with embedded path
309
#
310
# Returns         : Path to the (dummy) view
311
#
312
sub create_path_view
313
{
314
    my ($label) = @_;
315
    my $path  = '.';
316
 
317
    $path = $1
318
        if ( $label =~ m~.+=(.+)~ );
319
 
320
    Error ("Directory not found: $path" )
321
        unless ( -d $path );
322
 
323
    $path = FullPath( $path );
324
    return $path;
325
}
326
 
327
#-------------------------------------------------------------------------------
328
# Function        : massage_paths
329
#
330
# Description     : Used when one of the paths is a view and the the other
331
#                   is a local directory.
332
#
333
#                   Attempt to locate the common root
334
#
335
# Inputs          : None
336
#
337
# Returns         : Modifies $path1 and $path2
338
#
339
sub massage_paths
340
{
341
    my $view_path = $view_tags[0];
342
    my $user_path = $path1;
343
    $user_path = $path2 if ( $view_path eq $path1 );
344
 
345
    #
346
    #   Split the user path into its component directory entries
347
    #   Start at the top and look for one of these in the view
348
    #
349
    my @user_path = split ('/', $user_path );
7040 dpurdie 350
    shift @user_path if $user_path[0] eq '';
383 dpurdie 351
    my $tpath = '';
352
    foreach my $dir ( @user_path )
353
    {
354
        if ( -d "$view_path/$dir" )
355
        {
356
            #
357
            #   Common directory found
358
            #   Set the user path to the previous directory
359
            #
360
            $user_path = $tpath;
361
            if ( $view_path eq $path1   )
362
            {
363
                $path2 = $user_path;
364
            }
365
            else
366
            {
367
                $path1 = $user_path;
368
            }
369
 
370
            #
371
            #   now add the common part
372
            #
373
            $path1 .= "/$dir";
374
            $path2 .= "/$dir";
375
            Message ("Setting common root path ($dir)", $path1, $path2);
376
            last;
377
        }
378
        $tpath .= '/' if ( $tpath );
379
        $tpath .= $dir;
380
    }
381
}
382
 
383
#-------------------------------------------------------------------------------
3967 dpurdie 384
# Function        : GetBeyondCompareExePath
383 dpurdie 385
#
386
# Description     : Determine the path to the BeyondCompare executable
387
#                   by looking in the Windows Registry
388
#
389
# Inputs          : None
390
#
391
# Returns         : Path to an executable
392
#
393
 
3967 dpurdie 394
sub GetBeyondCompareExePath
383 dpurdie 395
{
396
    eval "require Win32::TieRegistry"
397
        or Error ("Win32::TieRegistry not available");
398
 
5264 dpurdie 399
    Win32::TieRegistry::import(qw( REG_SZ REG_EXPAND_SZ REG_DWORD REG_BINARY REG_MULTI_SZ KEY_READ KEY_WRITE KEY_ALL_ACCESS ));
400
 
401
    my $userKey= Win32::TieRegistry->new("CUser", {Access=>KEY_READ(),Delimiter=>"/"})
383 dpurdie 402
        or  Error( "Can't access HKEY_CURRENT_USER key: $^E" );
403
 
5264 dpurdie 404
    my $localKey= Win32::TieRegistry->new("LMachine", {Access=>KEY_READ(),Delimiter=>"/"})
5240 dpurdie 405
        or  Error( "Can't access HKEY_LOCAL_MACHINE key: $^E" );
406
 
407
    sub checkKeys
408
    {
409
        my ($userKey, $localKey, $key) = @_;
410
        my ($bcKey, $DiffProg);
5264 dpurdie 411
        $bcKey = $userKey->Open( $key );
5240 dpurdie 412
        if ($bcKey && ($DiffProg = $bcKey->GetValue( 'ExePath' )) )
413
        {
414
            return $DiffProg;
415
        }
5264 dpurdie 416
        $bcKey = $localKey->Open( $key );
5240 dpurdie 417
        if ($bcKey && ($DiffProg = $bcKey->GetValue( 'ExePath' )) )
418
        {
419
            return $DiffProg;
420
        }
421
        return undef;
422
    }
423
 
3967 dpurdie 424
    my $bcKey;
5240 dpurdie 425
    if ($DiffProg = checkKeys( $userKey, $localKey,"Software/Scooter Software/Beyond Compare 4" ))
3967 dpurdie 426
    {
5100 dpurdie 427
        Verbose("Using BC4");
428
        push @DiffArgs, '/solo';
429
    }
5240 dpurdie 430
    elsif ($DiffProg = checkKeys( $userKey, $localKey,"Software/Scooter Software/Beyond Compare 3"))
5100 dpurdie 431
    {
3967 dpurdie 432
        Verbose("Using BC3");
433
        push @DiffArgs, '/solo';
434
    }
5240 dpurdie 435
    elsif ($DiffProg = checkKeys( $userKey, $localKey,"Software/Scooter Software/Beyond Compare"))
3967 dpurdie 436
    {
437
        Verbose("Using BC2");
438
    }
439
    else
440
    {
5100 dpurdie 441
        Error "Can't access BC2, BC3 or BC4 Keys: $^E";
3967 dpurdie 442
    }
383 dpurdie 443
 
3967 dpurdie 444
    Error ("BeyondCompare program not found", "Prog: $DiffProg")
445
        unless ( -x $DiffProg );
383 dpurdie 446
}
447
 
448
#-------------------------------------------------------------------------------
449
# Function        : END
450
#
451
# Description     : This function will be called as the program exits
452
#                   It will also be called under error conditions
453
#                   Close down stuff we created
454
#
455
# Inputs          : 
456
#
457
# Returns         : 
458
#
459
 
460
sub END
461
{
462
    my $exitCode = $?;
463
 
464
    if ( $opt_debug )
465
    {
466
        Message ("NOT Cleaning up views");
467
        return;
468
    }
469
 
470
    Message ("Cleaning up views") if @view_tags;
471
    foreach my $cmds ( @view_commands )
472
    {
473
        JatsTool( @{$cmds}, '-delete' );
474
    }
475
 
476
    foreach my $file ( @cleanFiles )
477
    {
478
        unlink $file;
479
    }
480
 
481
    #
482
    #   The exit code may get modified by the JatsTool
483
    #   Preserve any error indication
484
    #
485
    $? = $exitCode;
486
}
487
 
488
#-------------------------------------------------------------------------------
489
#   Documentation
490
#
491
 
492
=pod
493
 
494
=head1 NAME
495
 
496
jats_vcsdiff - Difference two views
497
 
498
=head1 SYNOPSIS
499
 
500
  jats vcsdiff [options] [old_label new_label]
501
 
502
 Options:
6085 dpurdie 503
    -help               - Brief help message
504
    -help -help         - Detailed help message
505
    -man                - Full documentation
506
    -check              - Perform MD5SUM over both views
507
    -[no]diff           - Force the use of a 'diff' utility
508
    -option=opt1,...    - Add user options to the command line
509
    -old=tag            - Old VcsTag (or dir=path)
510
    -new=tag            - New VcsTag (or dir=path)
383 dpurdie 511
 
512
=head1 OPTIONS
513
 
514
=over 8
515
 
516
=item B<-help>
517
 
518
Print a brief help message and exits.
519
 
520
=item B<-help -help>
521
 
522
Print a detailed help message with an explanation for each option.
523
 
524
=item B<-man>
525
 
526
Prints the manual page and exits.
527
 
528
=item B<-check>
529
 
530
This option controls the mode in which the program will operate.
531
 
2931 dpurdie 532
If enabled the program will perform an MD5 Cheksum over the files in the first
383 dpurdie 533
view and compare that with files in the second view.
534
 
2931 dpurdie 535
This option cannot be used in conjunction with the '-diff' option'.
383 dpurdie 536
 
2931 dpurdie 537
=item B<-diff>
538
 
539
This option controls the mode in which the program will operate.
540
 
541
By default the program is Operating System dependent. It will:
542
 
543
=over 4
544
 
545
=item * Windows - Use Beyond Compare
546
 
547
=item * Unix - Use gdiff or diff
548
 
549
=back
550
 
551
This option will force the use of a 'diff' utility on both Windows and
552
Unix.
553
 
554
This option cannot be used in conjunction with the '-check' option'.
555
 
6085 dpurdie 556
=item B<-option=opt1,..>
557
 
558
This option allows the user to modify the operation of the invoked diff program.
559
 
560
The options are passed directly to the diff utility invoved by the program. It is the users
561
responsibility to ensure that the options are valid.
562
 
563
This option may be used mutiple times, or options may be comma-seperated.
564
 
383 dpurdie 565
=item B<-old=tag>
566
 
567
This option specifies the old, or base, VcsTag for the difference report. This
568
tag is mandatory.
569
 
570
The old and new tags may be provided on the command line, or via named
571
options, but not both.
572
 
573
The tag may be of the form dir=path to force the utility to use a local
574
view or path.
575
 
576
=item B<-new=tag>
577
 
578
This option specifies the new, or current, VcsTag for the difference report. This
579
tag is mandatory.
580
 
581
The old and new tags may be provided on the command line, or via named
582
options, but not both.
583
 
584
The tag may be of the form dir=path to force the utility to use a local
585
view or path.
586
 
587
=back
588
 
589
=head1 DESCRIPTION
590
 
591
This program has two modes of operation:
592
 
593
=over 4
594
 
595
=item 1 MD5Sum of the two views
596
 
2931 dpurdie 597
=item 2 Invoke a differencing program.
383 dpurdie 598
 
2931 dpurdie 599
The program that is invoked is, by default, Operating System dependent. It will:
600
 
601
=over 4
602
 
603
=item * Windows - Use Beyond Compare to perform a visual diff.
604
 
383 dpurdie 605
This mode simplifies the process of perform a code review between two
606
VCS Tags by:
607
 
608
=over 8
609
 
610
=item *
611
 
612
Creating a visual difference between two labels
613
 
614
=item *
615
 
616
Creating a visual difference between a label and a directory
617
 
618
=item *
619
 
620
Creating a visual difference between two directories.
621
 
622
=back
623
 
2931 dpurdie 624
=item * Unix - Use gdiff or diff
625
 
383 dpurdie 626
=back
627
 
2931 dpurdie 628
=back
629
 
383 dpurdie 630
The program will:
631
 
632
=over 8
633
 
634
=item *
635
 
636
Create two 'extract only' views based on the VCS Tags provided. The resultant
637
views are not connected to any version control system.
638
 
639
=item *
640
 
2931 dpurdie 641
Perform the desired operation: MD5Sum or Difference.
383 dpurdie 642
 
643
=item *
644
 
645
Delete the created directories the comparison is complete.
646
 
647
=back
648
 
649
If one of the Vcs Tags is of the form:
650
 
651
=over 8
652
 
653
=item *
654
 
655
current
656
 
657
=item *
658
 
659
current=path
660
 
661
=item *
662
 
663
dir=path
664
 
665
=back
666
 
667
Then the tag will be treated as a directory and will be used for one side
668
of the comparison.
669
 
670
Two directories views will be created. These should be deleted by this program,
671
but may remain if the command line program is terminated.
672
 
673
=head1 EXAMPLE
674
 
675
The following command will compare a Subversion view with a ClearCase view.
676
 
677
    jats vcsdiff SVN::AUPERASVN02/COTS/crc/tags/crc_26.4.0007.cr@18587 CC::/MASS_Dev_Infra/crc::crc_26.4.0006.cr -check
678
 
679
The following command will compare a Subversion View with a local directory
680
 
681
    jats vcsdiff SVN::AUPERASVN02/COTS/crc/tags/crc_26.4.0000.cr dir=crc
682
 
683
=cut
684