Subversion Repositories DevTools

Rev

Rev 3967 | 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;
400
    if ($bcKey = $userKey->Open( "Software/Scooter Software/Beyond Compare 3", {Delimiter=>"/"} ))
401
    {
402
        Verbose("Using BC3");
403
        push @DiffArgs, '/solo';
404
    }
405
    elsif ($bcKey = $userKey->Open( "Software/Scooter Software/Beyond Compare", {Delimiter=>"/"} ))
406
    {
407
        Verbose("Using BC2");
408
    }
409
    else
410
    {
411
        Error "Can't access BC2 or BC3 Keys: $^E";
412
    }
383 dpurdie 413
 
3967 dpurdie 414
    $DiffProg = $bcKey->GetValue( 'ExePath' )
415
        or Error( "Cannot locate BeyondCompare ExePath in Windows Registry");
383 dpurdie 416
 
3967 dpurdie 417
    Error ("BeyondCompare program not found", "Prog: $DiffProg")
418
        unless ( -x $DiffProg );
383 dpurdie 419
}
420
 
421
#-------------------------------------------------------------------------------
422
# Function        : END
423
#
424
# Description     : This function will be called as the program exits
425
#                   It will also be called under error conditions
426
#                   Close down stuff we created
427
#
428
# Inputs          : 
429
#
430
# Returns         : 
431
#
432
 
433
sub END
434
{
435
    my $exitCode = $?;
436
 
437
    if ( $opt_debug )
438
    {
439
        Message ("NOT Cleaning up views");
440
        return;
441
    }
442
 
443
    Message ("Cleaning up views") if @view_tags;
444
    foreach my $cmds ( @view_commands )
445
    {
446
        JatsTool( @{$cmds}, '-delete' );
447
    }
448
 
449
    foreach my $file ( @cleanFiles )
450
    {
451
        unlink $file;
452
    }
453
 
454
    #
455
    #   The exit code may get modified by the JatsTool
456
    #   Preserve any error indication
457
    #
458
    $? = $exitCode;
459
}
460
 
461
#-------------------------------------------------------------------------------
462
#   Documentation
463
#
464
 
465
=pod
466
 
467
=head1 NAME
468
 
469
jats_vcsdiff - Difference two views
470
 
471
=head1 SYNOPSIS
472
 
473
  jats vcsdiff [options] [old_label new_label]
474
 
475
 Options:
476
    -help              - brief help message
477
    -help -help        - Detailed help message
478
    -man               - Full documentation
479
    -check             - Perform MD5SUM over both views
2931 dpurdie 480
    -[no]diff          - Force the use of a 'diff' utility
383 dpurdie 481
    -old=tag           - Old VcsTag (or dir=path)
482
    -new=tag           - New VcsTag (or dir=path)
483
 
484
=head1 OPTIONS
485
 
486
=over 8
487
 
488
=item B<-help>
489
 
490
Print a brief help message and exits.
491
 
492
=item B<-help -help>
493
 
494
Print a detailed help message with an explanation for each option.
495
 
496
=item B<-man>
497
 
498
Prints the manual page and exits.
499
 
500
=item B<-check>
501
 
502
This option controls the mode in which the program will operate.
503
 
2931 dpurdie 504
If enabled the program will perform an MD5 Cheksum over the files in the first
383 dpurdie 505
view and compare that with files in the second view.
506
 
2931 dpurdie 507
This option cannot be used in conjunction with the '-diff' option'.
383 dpurdie 508
 
2931 dpurdie 509
=item B<-diff>
510
 
511
This option controls the mode in which the program will operate.
512
 
513
By default the program is Operating System dependent. It will:
514
 
515
=over 4
516
 
517
=item * Windows - Use Beyond Compare
518
 
519
=item * Unix - Use gdiff or diff
520
 
521
=back
522
 
523
This option will force the use of a 'diff' utility on both Windows and
524
Unix.
525
 
526
This option cannot be used in conjunction with the '-check' option'.
527
 
383 dpurdie 528
=item B<-old=tag>
529
 
530
This option specifies the old, or base, VcsTag for the difference report. This
531
tag is mandatory.
532
 
533
The old and new tags may be provided on the command line, or via named
534
options, but not both.
535
 
536
The tag may be of the form dir=path to force the utility to use a local
537
view or path.
538
 
539
=item B<-new=tag>
540
 
541
This option specifies the new, or current, VcsTag for the difference report. This
542
tag is mandatory.
543
 
544
The old and new tags may be provided on the command line, or via named
545
options, but not both.
546
 
547
The tag may be of the form dir=path to force the utility to use a local
548
view or path.
549
 
550
=back
551
 
552
=head1 DESCRIPTION
553
 
554
This program has two modes of operation:
555
 
556
=over 4
557
 
558
=item 1 MD5Sum of the two views
559
 
2931 dpurdie 560
=item 2 Invoke a differencing program.
383 dpurdie 561
 
2931 dpurdie 562
The program that is invoked is, by default, Operating System dependent. It will:
563
 
564
=over 4
565
 
566
=item * Windows - Use Beyond Compare to perform a visual diff.
567
 
383 dpurdie 568
This mode simplifies the process of perform a code review between two
569
VCS Tags by:
570
 
571
=over 8
572
 
573
=item *
574
 
575
Creating a visual difference between two labels
576
 
577
=item *
578
 
579
Creating a visual difference between a label and a directory
580
 
581
=item *
582
 
583
Creating a visual difference between two directories.
584
 
585
=back
586
 
2931 dpurdie 587
=item * Unix - Use gdiff or diff
588
 
383 dpurdie 589
=back
590
 
2931 dpurdie 591
=back
592
 
383 dpurdie 593
The program will:
594
 
595
=over 8
596
 
597
=item *
598
 
599
Create two 'extract only' views based on the VCS Tags provided. The resultant
600
views are not connected to any version control system.
601
 
602
=item *
603
 
2931 dpurdie 604
Perform the desired operation: MD5Sum or Difference.
383 dpurdie 605
 
606
=item *
607
 
608
Delete the created directories the comparison is complete.
609
 
610
=back
611
 
612
If one of the Vcs Tags is of the form:
613
 
614
=over 8
615
 
616
=item *
617
 
618
current
619
 
620
=item *
621
 
622
current=path
623
 
624
=item *
625
 
626
dir=path
627
 
628
=back
629
 
630
Then the tag will be treated as a directory and will be used for one side
631
of the comparison.
632
 
633
Two directories views will be created. These should be deleted by this program,
634
but may remain if the command line program is terminated.
635
 
636
=head1 EXAMPLE
637
 
638
The following command will compare a Subversion view with a ClearCase view.
639
 
640
    jats vcsdiff SVN::AUPERASVN02/COTS/crc/tags/crc_26.4.0007.cr@18587 CC::/MASS_Dev_Infra/crc::crc_26.4.0006.cr -check
641
 
642
The following command will compare a Subversion View with a local directory
643
 
644
    jats vcsdiff SVN::AUPERASVN02/COTS/crc/tags/crc_26.4.0000.cr dir=crc
645
 
646
=cut
647