Subversion Repositories DevTools

Rev

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

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