Subversion Repositories DevTools

Rev

Rev 1357 | 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;
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';
1360 dpurdie 113
    Error ("Use of BeyondCompare is limited to Windows", "Only the -check mode is available under Unix")
383 dpurdie 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',
1360 dpurdie 237
                        '-devmode=escrow',
383 dpurdie 238
                        '-view', $tag ,
239
                        '-label', $vcstag,
240
                   );
241
    push @view_commands, \@command;
242
 
243
    if ( $opt_debug && -d $tag )
244
    {
245
        Message ("Using existing view");
246
    }
247
    else
248
    {
249
        JatsTool( @command );
250
    }
251
 
252
    #
253
    #   Minor Kludge
254
    #       Should be in a library
255
    #   Iff CC::, then process path info too
256
    #
257
    if ( $vcstag =~ m~^CC::(.*?)(::(.+))?$~ )
258
    {
259
        my $path = $1;
260
        if ( $path )
261
        {
262
            my $try = $tag . '/' . $path;
263
            if ( -d  $try )
264
            {
265
                $tag = $try;
266
            }
267
        }
268
    }
269
 
270
    return $tag;
271
}
272
 
273
#-------------------------------------------------------------------------------
274
# Function        : create_path_view
275
#
276
# Description     : Not using a view, using a path
277
#                   Return the path as requested
278
#
279
# Inputs          : $label                  - with embedded path
280
#
281
# Returns         : Path to the (dummy) view
282
#
283
sub create_path_view
284
{
285
    my ($label) = @_;
286
    my $path  = '.';
287
 
288
    $path = $1
289
        if ( $label =~ m~.+=(.+)~ );
290
 
291
    Error ("Directory not found: $path" )
292
        unless ( -d $path );
293
 
294
    $path = FullPath( $path );
295
    return $path;
296
}
297
 
298
#-------------------------------------------------------------------------------
299
# Function        : massage_paths
300
#
301
# Description     : Used when one of the paths is a view and the the other
302
#                   is a local directory.
303
#
304
#                   Attempt to locate the common root
305
#
306
# Inputs          : None
307
#
308
# Returns         : Modifies $path1 and $path2
309
#
310
sub massage_paths
311
{
312
    my $view_path = $view_tags[0];
313
    my $user_path = $path1;
314
    $user_path = $path2 if ( $view_path eq $path1 );
315
 
316
    #
317
    #   Split the user path into its component directory entries
318
    #   Start at the top and look for one of these in the view
319
    #
320
    my @user_path = split ('/', $user_path );
321
    my $tpath = '';
322
    foreach my $dir ( @user_path )
323
    {
324
        if ( -d "$view_path/$dir" )
325
        {
326
            #
327
            #   Common directory found
328
            #   Set the user path to the previous directory
329
            #
330
            $user_path = $tpath;
331
            if ( $view_path eq $path1   )
332
            {
333
                $path2 = $user_path;
334
            }
335
            else
336
            {
337
                $path1 = $user_path;
338
            }
339
 
340
            #
341
            #   now add the common part
342
            #
343
            $path1 .= "/$dir";
344
            $path2 .= "/$dir";
345
            Message ("Setting common root path ($dir)", $path1, $path2);
346
            last;
347
        }
348
        $tpath .= '/' if ( $tpath );
349
        $tpath .= $dir;
350
    }
351
}
352
 
353
#-------------------------------------------------------------------------------
354
# Function        : GetBc2ExePath
355
#
356
# Description     : Determine the path to the BeyondCompare executable
357
#                   by looking in the Windows Registry
358
#
359
# Inputs          : None
360
#
361
# Returns         : Path to an executable
362
#
363
 
364
sub GetBc2ExePath
365
{
366
    eval "require Win32::TieRegistry"
367
        or Error ("Win32::TieRegistry not available");
368
 
369
    my $userKey= Win32::TieRegistry->new("CUser")
370
        or  Error( "Can't access HKEY_CURRENT_USER key: $^E" );
371
 
372
    my $bc2Key= $userKey->Open( "Software/Scooter Software/Beyond Compare", {Delimiter=>"/"} )
373
        or  Error "Can't access BC2 Keys: $^E";
374
 
375
    my $bc2Data = $bc2Key->GetValue( 'ExePath' )
376
        or Error( "Cannot locate BeyondCompare in Windows Registry");
377
 
378
    Error ("BeyondCompare program not found", "Prog: $bc2Data") unless ( -x $bc2Data );
379
    return $bc2Data;
380
}
381
 
382
#-------------------------------------------------------------------------------
383
# Function        : END
384
#
385
# Description     : This function will be called as the program exits
386
#                   It will also be called under error conditions
387
#                   Close down stuff we created
388
#
389
# Inputs          : 
390
#
391
# Returns         : 
392
#
393
 
394
sub END
395
{
396
    my $exitCode = $?;
397
 
398
    if ( $opt_debug )
399
    {
400
        Message ("NOT Cleaning up views");
401
        return;
402
    }
403
 
404
    Message ("Cleaning up views") if @view_tags;
405
    foreach my $cmds ( @view_commands )
406
    {
407
        JatsTool( @{$cmds}, '-delete' );
408
    }
409
 
410
    foreach my $file ( @cleanFiles )
411
    {
412
        unlink $file;
413
    }
414
 
415
    #
416
    #   The exit code may get modified by the JatsTool
417
    #   Preserve any error indication
418
    #
419
    $? = $exitCode;
420
}
421
 
422
#-------------------------------------------------------------------------------
423
#   Documentation
424
#
425
 
426
=pod
427
 
428
=head1 NAME
429
 
430
jats_vcsdiff - Difference two views
431
 
432
=head1 SYNOPSIS
433
 
434
  jats vcsdiff [options] [old_label new_label]
435
 
436
 Options:
437
    -help              - brief help message
438
    -help -help        - Detailed help message
439
    -man               - Full documentation
440
    -check             - Perform MD5SUM over both views
441
    -old=tag           - Old VcsTag (or dir=path)
442
    -new=tag           - New VcsTag (or dir=path)
443
 
444
=head1 OPTIONS
445
 
446
=over 8
447
 
448
=item B<-help>
449
 
450
Print a brief help message and exits.
451
 
452
=item B<-help -help>
453
 
454
Print a detailed help message with an explanation for each option.
455
 
456
=item B<-man>
457
 
458
Prints the manual page and exits.
459
 
460
=item B<-check>
461
 
462
This option controls the mode in which the program will operate.
463
 
464
If enabled the prgram will perform an MD5 Cheksum over the files in the first
465
view and compare that with files in the second view.
466
 
467
If not enabled, then the program will invoke BeyondCompare to perform a visual
468
difference between the two views. This operation is only supported under
469
Windows.
470
 
471
=item B<-old=tag>
472
 
473
This option specifies the old, or base, VcsTag for the difference report. This
474
tag is mandatory.
475
 
476
The old and new tags may be provided on the command line, or via named
477
options, but not both.
478
 
479
The tag may be of the form dir=path to force the utility to use a local
480
view or path.
481
 
482
=item B<-new=tag>
483
 
484
This option specifies the new, or current, VcsTag for the difference report. This
485
tag is mandatory.
486
 
487
The old and new tags may be provided on the command line, or via named
488
options, but not both.
489
 
490
The tag may be of the form dir=path to force the utility to use a local
491
view or path.
492
 
493
=back
494
 
495
=head1 DESCRIPTION
496
 
497
This program has two modes of operation:
498
 
499
=over 4
500
 
501
=item 1 MD5Sum of the two views
502
 
503
=item 2 Invoke BeyondCompare to perform a visual diff.
504
 
505
This mode simplifies the process of perform a code review between two
506
VCS Tags by:
507
 
508
=over 8
509
 
510
=item *
511
 
512
Creating a visual difference between two labels
513
 
514
=item *
515
 
516
Creating a visual difference between a label and a directory
517
 
518
=item *
519
 
520
Creating a visual difference between two directories.
521
 
522
=back
523
 
524
=back
525
 
526
The program will:
527
 
528
=over 8
529
 
530
=item *
531
 
532
Create two 'extract only' views based on the VCS Tags provided. The resultant
533
views are not connected to any version control system.
534
 
535
=item *
536
 
537
Perform the desired operation: MD5Sum or Visual Difference.
538
 
539
=item *
540
 
541
Delete the created directories the comparison is complete.
542
 
543
=back
544
 
545
If one of the Vcs Tags is of the form:
546
 
547
=over 8
548
 
549
=item *
550
 
551
current
552
 
553
=item *
554
 
555
current=path
556
 
557
=item *
558
 
559
dir=path
560
 
561
=back
562
 
563
Then the tag will be treated as a directory and will be used for one side
564
of the comparison.
565
 
566
Two directories views will be created. These should be deleted by this program,
567
but may remain if the command line program is terminated.
568
 
569
=head1 EXAMPLE
570
 
571
The following command will compare a Subversion view with a ClearCase view.
572
 
573
    jats vcsdiff SVN::AUPERASVN02/COTS/crc/tags/crc_26.4.0007.cr@18587 CC::/MASS_Dev_Infra/crc::crc_26.4.0006.cr -check
574
 
575
The following command will compare a Subversion View with a local directory
576
 
577
    jats vcsdiff SVN::AUPERASVN02/COTS/crc/tags/crc_26.4.0000.cr dir=crc
578
 
579
=cut
580