Subversion Repositories DevTools

Rev

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