Subversion Repositories DevTools

Rev

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