Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
227 dpurdie 1
 
2
# interpreter options
3
use strict;
4
#use warnings;
5
 
6
# perl libraries
7
use Cwd;
8
use Carp;
9
use DirHandle;
10
use FileHandle;
11
use File::Compare;
12
use File::Copy;
13
use Getopt::Long;
14
 
15
#==================================================================================================
16
#
17
#   module global constants
18
 
19
    # none
20
 
21
#==================================================================================================
22
#
23
#   module global variables
24
 
25
    # none
26
 
27
#==================================================================================================
28
# preserve the command line for later output to the log file
29
my $commandLine;
30
$0              =~ m%\\?([^\\]*$)%;                 # strip off any leading path stuff
31
$commandLine    = $1 . " " . join( " ", @ARGV );
32
 
33
#==================================================================================================
34
# define the command line options we accept
35
# NOTE: don't forget to update the help text if you play with these...
36
# NOTE: these are globals too, lited here to associate them with the option routines...
37
 
38
my  $opt_destinationDir;
39
my  $opt_sourceDirectory;
40
my  $opt_dryRun;
41
my  $opt_log;
42
my  $opt_recurse;
43
my  $opt_admin;
44
my  $opt_label;
45
my  $opt_comment;
46
my  $opt_noClearcase;
47
my  $opt_noViewCheck;
48
my  $opt_noDelete;
49
my  $opt_noCheckin;
50
my  $opt_noBranch;
51
 
52
my %gOptionList;
53
%gOptionList =
54
(
55
    "dest=s"        =>  sub                             # where to place the files
56
                        {
57
                            $_[1] =~ s%\\%/%g;
58
                            $opt_destinationDir = $_[1];
59
                        },
60
    "src=s"         =>  sub                             # where the files come from
61
                        {
62
                            $_[1] =~ s%\\%/%g;
63
                            $opt_sourceDirectory = $_[1] ;
64
                        },
65
    "dryRun!"       =>  \$opt_dryRun,                   # if  set, display what would happen, don't
66
                                                        # actually do it
67
    "log=s"         =>  \$opt_log,                      # nominate the log file to output to
68
    "recurse!"      =>  \$opt_recurse,                  # specify whether we're to recurse or not
69
    "admin=s"       =>  \$opt_admin,                    # specify the administrative vob to create the label in
70
    "label=s"       =>  \$opt_label,                    # specify a label to apply
71
    "comment=s"     =>  \$opt_comment,                  # specify a comment to go with the label
72
    "noClearCase!"  =>  \$opt_noClearcase,              # specify whether clearcase is involved or not
73
    "noViewCheck!"  =>  \$opt_noViewCheck,              # specify whether clearcase view check to be done or not
74
    "noDelete!"     =>  \$opt_noDelete,                 # specify whether to delete files not in source
75
                                                        # but in destination
76
    "noCheckin!"    =>  \$opt_noCheckin,                # set means don't check in the files...
77
    "noBranch!"     =>  \$opt_noBranch,                 # set means check file out without branching
78
 
79
    "help!"         =>  \&giveHelp,                     # provide the punter with help
80
);
81
 
82
#==================================================================================================
83
#
84
#   main code body
85
 
86
#==================================================================================================
87
# recover any command line options
88
GetOptions( %gOptionList );
89
 
90
#==================================================================================================
91
# verify that if specified, the labelling parameters are all specified
92
#   NOTE no check is made as to whether the vob is correct or the label can be created/used
93
unless( $opt_noClearcase || !defined $opt_label )
94
{
95
    # do we have an administrative vob?
96
    die "No administrative VOB specified\n" unless ( $opt_admin );
97
    die "No label comment specified\n"      unless ( $opt_comment );
98
}
99
 
100
#==================================================================================================
101
#   use stdout or nominated file for status output?
102
my $statusFh;
103
$statusFh = new FileHandle;
104
if ( defined $opt_log )
105
{
106
    # open up the nominated destination
107
    unless ( open( $statusFh, "> $opt_log" ) )
108
    {
109
        die "Unable to open '$opt_log': $!\n";
110
    }
111
}
112
else
113
{
114
    # duplicate stdout
115
    unless ( open( $statusFh, ">-" ) )
116
    {
117
        die "Unable to dup 'STDOUT'\n";
118
    }
119
}
120
 
121
#==================================================================================================
122
# record what the command line was
123
print $statusFh $commandLine, "\n";
124
 
125
#==================================================================================================
126
#   if a clearcase view & check not suppressed, verify it...
127
doClearcaseViewCheck( $opt_destinationDir ) unless( $opt_noClearcase || $opt_noViewCheck );
128
 
129
#==================================================================================================
130
#   locate all directories from here down (if required)
131
doThisDirectory( $opt_sourceDirectory, $opt_destinationDir );
132
 
133
#==================================================================================================
134
#   label this sucker
135
doLabel( $opt_destinationDir, $opt_admin, $opt_label, $opt_comment ) unless( $opt_noClearcase || !defined $opt_label );
136
 
137
exit 0;
138
 
139
#
140
#==================================================================================================
141
#
142
#   doClearcaseViewCheck
143
#
144
#   PERSISTENT LOCALS:
145
#       none
146
#
147
sub doClearcaseViewCheck
148
#
149
{
150
#
151
    # correct number of input parameters?
152
    if ( ($#_+1) != 1 )
153
    {
154
        confess "Incorrect parameter count, expected 1 parameter, saw ", $#_+1, "\n";
155
    }
156
#
157
#   INPUTS:
158
    my $destinationDir  = shift;    # IN  - name of the directory containing destination elements
159
#
160
#   OUTPUTS:
161
#       none
162
#
163
#   GLOBALS:
164
#
165
#   NOTES:
166
#       none
167
#
168
#==================================================================================================
169
 
170
    my $command;
171
 
172
    print $statusFh "Verifying destination view\n";
173
 
174
    # anything currently checked out?
175
    my @checkedout;
176
    $command = "cleartool lscheckout -short -recurse -me -cview $destinationDir";
177
    @checkedout = doClearCaseCommand( $command );
178
    if ( 0 <= $#checkedout )
179
    {
180
        chomp @checkedout;
181
        map( s%\\%/%g, @checkedout );
182
        print $statusFh "The following items are checked out:\n\t",
183
                join( "\n\t", @checkedout ), "\nAborting\n";
184
        exit -1 unless $opt_dryRun;
185
    }
186
 
187
    # collate list of source items
188
    my @sources;
189
    $command = cleartool ls -short -recurse $destinationDir;
190
    @sources = doClearCaseCommand( $command );
191
    chomp @sources;
192
    map( s%\\%/%g, @sources );
193
 
194
    #now see if there's anything that isn't 'latest' and tell the user...
195
    my $item;
196
    my @naughtyList;
197
    foreach $item ( @sources )
198
    {
199
        # item managed by clearcase?
200
        next unless ( $item =~ /@@/ );
201
        next if     ( $item =~ /CHECKEDOUT/ );
202
 
203
        # clearcase item, see if the viewed vbersion is the same as the latest on this branch
204
        my $compare;
205
        $item =~ m%(^.*/)[0-9]+$%;
206
        $compare = $1 . "LATEST";
207
 
208
        my $result;
209
        $command = cleartool describe -short $compare;
210
        $result = doClearCaseCommand( $command );
211
        $result =~ s%\\%/%g;
212
        chomp $result;
213
 
214
        print $statusFh "Verifying: $item\n";
215
        if ( $item ne $result )
216
        {
217
            # we have a mismatch, record it for posterity...
218
            push @naughtyList, $item . " " x 5 . "=>" . " " x 5 . $result;
219
        }
220
    }
221
 
222
    # any items not at end of list?
223
    if ( 0 <= $#naughtyList )
224
    {
225
        print $statusFh "ERROR:  The following elements are not the latest version:\n\t",
226
                join( "\n\t", @naughtyList ), "\nAborting\n";
227
        exit -1 unless $opt_dryRun;
228
    }
229
 
230
}   # doClearcaseViewCheck
231
 
232
#
233
#==================================================================================================
234
#
235
#   doThisDirectory
236
#
237
#   PERSISTENT LOCALS:
238
#       none
239
#
240
sub doThisDirectory
241
#
242
{
243
#
244
    # correct number of input parameters?
245
    if ( ($#_+1) != 2 )
246
    {
247
        confess "Incorrect parameter count, expected 2 parameters, saw ", $#_+1, "\n";
248
    }
249
#
250
#   INPUTS:
251
    my $sourceDirectory = shift;    # IN  - name of the directory containing source elements
252
    my $destinationDir  = shift;    # IN  - name of the directory containing destination elements
253
#
254
#   OUTPUTS:
255
#
256
#   GLOBALS:
257
#
258
#   NOTES:
259
#       none
260
#
261
#==================================================================================================
262
 
263
    print $statusFh "Processing source directory '$sourceDirectory', and destination directory '$destinationDir'\n";
264
 
265
    # collate source files
266
    print $statusFh "Collating source files...\n";
267
    my $refSourceFiles;
268
    my $refSourceDirs;
269
    ( $refSourceDirs, $refSourceFiles ) = collateFileList( $sourceDirectory );
270
 
271
    # collate destination files
272
    print $statusFh "\n";
273
    print $statusFh "Collating destination files...\n";
274
    my $refDestinationFiles;
275
    my $refDestinationDirs;
276
    ( $refDestinationDirs, $refDestinationFiles ) = collateFileList( $destinationDir );
277
 
278
    # are we recursing down?
279
    if ( defined $opt_recurse )
280
    {
281
        print $statusFh "Recursing down...\n";
282
 
283
        my @newDirs;
284
        my @commonDirs;
285
        my @deletedDirs;
286
        arrayDiff(  $refSourceDirs,
287
                    $refDestinationDirs,
288
                    \@newDirs,
289
                    \@commonDirs,
290
                    \@deletedDirs );
291
 
292
        print $statusFh "New directories are:\n\t", join( "\n\t", @newDirs ), "\n";
293
        print $statusFh "Common directories are:\n\t", join( "\n\t", @commonDirs ), "\n";
294
        print $statusFh "Deleted directories are:\n\t", join( "\n\t", @deletedDirs ), "\n";
295
 
296
        # yep, go handle any new directories
297
        foreach ( @newDirs )
298
        {
299
            print $statusFh "New directory, making '${destinationDir}/$_'\n";
300
 
301
            unless ( $opt_dryRun )
302
            {
303
                # make the directory
304
                mkdir "${destinationDir}/$_";
305
 
306
                # add it to CC control
307
                unless ( $opt_noClearcase )
308
                {
309
                    # for new directories, not sure how to get it to NOT branch...
310
                    print $statusFh "Adding '${destinationDir}/$_' to ClearCase.\n";
311
                    doClearCaseCommand( "cleartool mkelem -eltype directory -ci -ncomment ${destinationDir}/$_" );
312
                }
313
 
314
                # now recurse to it...
315
                doThisDirectory( "${sourceDirectory}/$_", "${destinationDir}/$_" );
316
 
317
                # and check it back in...
318
                unless ( $opt_noClearcase || $opt_noCheckin )
319
                {
320
                    print $statusFh "Checking in '${destinationDir}/$_'\n";
321
                    doClearCaseCommand( "cleartool ci -ncomment ${destinationDir}/$_" );
322
                }
323
            }
324
        }
325
 
326
        # and the common ones...
327
        foreach ( @commonDirs )
328
        {
329
            print $statusFh "Processing common Directory '${destinationDir}/$_'\n";
330
            doThisDirectory( "${sourceDirectory}/$_", "${destinationDir}/$_" );
331
        }
332
 
333
        # just nuke the deleted ones...
334
        if ( 0 <= $#deletedDirs )
335
        {
336
            unless ( $opt_noDelete )
337
            {
338
                print $statusFh "Deleting non-existent directory '${destinationDir}/$_'\n";
339
 
340
                unless ( $opt_dryRun )
341
                {
342
                    # check out the diestination dorectory...
343
                    unless ( $opt_noClearcase )
344
                    {
345
                        print $statusFh "Checking out parent directory '$destinationDir' to allow deletion\n";
346
                        unless ( $opt_noBranch )
347
                        {
348
                            # use config spec rules for branching...
349
                            doClearCaseCommand( "cleartool co -reserved -ncomment $destinationDir" );
350
                        }
351
                        else
352
                        {
353
                            # suppress config spec branching rules
354
                            my @description;
355
                            @description = doClearCaseCommand( "cleartool describe $destinationDir" );
356
 
357
                            my $version;
358
                            foreach ( @description )
359
                            {
360
                                # search for the directory version...
361
                                if ( m/version.*"(.*)"$/ )
362
                                {
363
                                    $version = $1;
364
                                    last;
365
                                }
366
                            }
367
                            doClearCaseCommand( "cleartool co -reserved -ncomment -version $version" );
368
                        }
369
                    }
370
 
371
                    # nuke the offending elements...
372
                    foreach ( @deletedDirs  )
373
                    {
374
                        # nuke it...
375
                        print $statusFh "Deleting '${destinationDir}/$_'\n";
376
                        doClearCaseCommand( "cleartool rm ${destinationDir}/$_" );
377
                    }
378
 
379
                    # and check it back in...
380
                    unless ( $opt_noClearcase || $opt_noCheckin )
381
                    {
382
                        print $statusFh "Deletion complete, checking in parent directory '$destinationDir'\n";
383
                        doClearCaseCommand( "cleartool ci -ncomment ${destinationDir}" );
384
                    }
385
                }
386
            }
387
        }
388
    }
389
 
390
    # let's 'hash-it-out' to locate new and deleted files...
391
    my @newFiles;
392
    my @commonFiles;
393
    my @deletedFiles;
394
    arrayDiff(  $refSourceFiles,
395
                $refDestinationFiles,
396
                \@newFiles,
397
                \@commonFiles,
398
                \@deletedFiles );
399
 
400
    print $statusFh "New files are:\n\t", join( "\n\t", @newFiles ), "\n";
401
    print $statusFh "Common files are:\n\t", join( "\n\t", @commonFiles ), "\n";
402
    print $statusFh "Deleted files are:\n\t", join( "\n\t", @deletedFiles ), "\n";
403
 
404
    updateFiles( $sourceDirectory, $destinationDir, \@newFiles, \@commonFiles, \@deletedFiles );
405
 
406
}   # doThisDirectory
407
 
408
#
409
#==================================================================================================
410
#
411
#   doLabel
412
#
413
#   PERSISTENT LOCALS:
414
#       none
415
#
416
sub doLabel
417
#
418
{
419
#
420
    # correct number of input parameters?
421
    if ( ($#_+1) != 4 )
422
    {
423
        confess "Incorrect parameter count, expected 2 parameters, saw ", $#_+1, "\n";
424
    }
425
#
426
#   INPUTS:
427
    my $destinationDir  = shift;    # IN  - name of the directory containing destination elements
428
    my $adminVob        = shift;    # IN  - label to apply
429
    my $label           = shift;    # IN  - label to apply
430
    my $comment         = shift;    # IN  - comment to apply to the label
431
#
432
#   OUTPUTS:
433
#
434
#   GLOBALS:
435
#
436
#   NOTES:
437
#       none
438
#
439
#==================================================================================================
440
 
441
    my $command;
442
 
443
    # tidy up inputs
444
    $destinationDir =~ s%\\%/%g;
445
    $adminVob = "/" . $adminVob unless ( $adminVob =~ m%^/% );
446
 
447
    # create the label in the admin vob
448
    my $createResult;
449
    $command = "cleartool mklbtype -global -c \"$comment\" ${label}\@${adminVob}";
450
    print $statusFh "Creating the label '$command'\n";
451
    $createResult = doClearCaseCommand( $command ) unless $opt_dryRun;
452
 
453
    # apply the label to the destination
454
    my @labelResult;
455
    $command = "cleartool mklabel -recurse $label $destinationDir";
456
    print $statusFh "Labelling '$command'\n";
457
    @labelResult = doClearCaseCommand( $command ) unless $opt_dryRun;
458
 
459
    # now walk our way back up the directory tree labelling the inbetween directorys needed
460
    while ( $destinationDir =~ m%/% )
461
    {
462
        # go backwards one directory
463
        $destinationDir =~ m%(^.*)/[^/]+$%;
464
        $destinationDir = $1;
465
 
466
        # have we reached the root yet?
467
        last if $destinationDir =~ /^[A-Za-z]:$/;
468
        last if $destinationDir =~ /^\s*$/;
469
 
470
        #not at root, so apply label
471
        push @labelResult, doClearCaseCommand( "cleartool mklabel ${label}\@ ${destinationDir}" )
472
                unless $opt_dryRun;
473
    }
474
 
475
    # report on what's labelled
476
    chomp @labelResult;
477
    print $statusFh "Label result:\n\t",
478
            join "\n\t", @labelResult, "\n";
479
 
480
    # and finally, lock the sucker
481
    doClearCaseCommand( "cleartool lock lbtype:$label" ) unless $opt_dryRun;
482
}   # doLabel
483
 
484
#
485
#==================================================================================================
486
#
487
#   collateFileList
488
#
489
#   PERSISTENT LOCALS:
490
#       none
491
#
492
sub collateFileList
493
#
494
{
495
#
496
    # correct number of input parameters?
497
    if ( ($#_+1) != 1 )
498
    {
499
        confess "Incorrect parameter count, expected 1 parameter, saw ", $#_+1, "\n";
500
    }
501
#
502
#   INPUTS:
503
        my $searchDirectory = shift;        # IN  - the nominated directory to search for items
504
#
505
#   OUTPUTS:
506
#       none
507
#
508
#   GLOBALS:
509
#       none
510
#
511
#   NOTES:
512
#       none
513
#
514
#==================================================================================================
515
 
516
    # open the directory to get the file list...
517
    my $dirHandle;
518
    $dirHandle = new DirHandle;
519
    opendir( $dirHandle, $searchDirectory ) or die "Unable to open '$searchDirectory': $!\n";
520
 
521
    # now go get the file list...
522
    my $dirEntry;
523
    my @fileList;
524
    my @dirList;
525
    while ( $dirEntry = readdir( $dirHandle ) )
526
    {
527
        # do we have a valid directory?
528
        chomp $dirEntry;
529
        next if $dirEntry eq ".";
530
        next if $dirEntry eq "..";
531
 
532
        # do we have a file or directory to parse?
533
        if ( -d "${searchDirectory}/${dirEntry}" )
534
        {
535
            # directory, are we recursing??
536
            if ( defined $opt_recurse )
537
            {
538
                # yep, so let's do it...
539
                print $statusFh "Adding ${dirEntry} to the directory list...\n";
540
                push @dirList, "${dirEntry}";
541
            }
542
        }
543
 
544
        else
545
        {
546
            # we've a file, add it to the file list
547
            print $statusFh "Adding ${dirEntry} to the file list...\n";
548
            push @fileList, "${dirEntry}";
549
        }
550
    }
551
 
552
    closedir( $dirHandle );
553
    return \@dirList, \@fileList;
554
}   # collateFileList
555
 
556
#
557
#==================================================================================================
558
#
559
#   arrayDiff
560
#
561
#   PERSISTENT LOCALS:
562
#       none
563
#
564
sub arrayDiff
565
#
566
{
567
#
568
    # correct number of input parameters?
569
    if ( ($#_+1) != 5 )
570
    {
571
        confess "Incorrect parameter count, expected 5 parameters, saw ", $#_+1, "\n";
572
    }
573
#
574
#   INPUTS:
575
    my $refSourceArray      = shift;    # IN  - reference to an array of source items
576
    my $refDestinationArray = shift;    # IN  - reference to an array of destination items
577
    my $refNewArray         = shift;    # I/O - reference to an array to populate with new items
578
    my $refCommonArray      = shift;    # I/O - reference to an array to populate with common items
579
    my $refDeletedArray     = shift;    # I/O - reference to an array to populate with deleted items
580
#
581
#   OUTPUTS:
582
#
583
#   GLOBALS:
584
#
585
#   NOTES:
586
#       none
587
#
588
#==================================================================================================
589
 
590
    # prepare to locate new, common and deleted directories...
591
    my %sourceHash;
592
    my %destinationHash;
593
    map { $sourceHash{$_}      = $_ } @{$refSourceArray};
594
    map { $destinationHash{$_} = $_ } @{$refDestinationArray};
595
 
596
    # new...
597
    foreach ( keys %sourceHash )
598
    {
599
        # keep list of common files
600
        push ( @{$refNewArray}, $_ ) unless exists $destinationHash{$_};
601
    }
602
 
603
    # common...
604
    foreach ( keys %sourceHash )
605
    {
606
        # keep list of common files
607
        push ( @{$refCommonArray}, $_ ) if exists $destinationHash{$_};
608
    }
609
 
610
    # deleted...
611
    foreach ( keys %destinationHash )
612
    {
613
        # keep list of common files
614
        push ( @{$refDeletedArray}, $_ ) unless exists $sourceHash{$_};
615
    }
616
}   # arrayDiff
617
 
618
#
619
#==================================================================================================
620
#
621
#   updateFiles
622
#
623
#   PERSISTENT LOCALS:
624
#       none
625
#
626
sub updateFiles
627
#
628
{
629
#
630
    # correct number of input parameters?
631
    if ( ($#_+1) != 5 )
632
    {
633
        confess "Incorrect parameter count, expected 5 parameters, saw ", $#_+1, "\n";
634
    }
635
#
636
#   INPUTS:
637
    my $sourceDir       = shift;    # IN  - name of the source directory
638
    my $destinationDir  = shift;    # IN  - name of the destination directory
639
    my $refNewFiles     = shift;    # IN  - reference to an array of new files
640
    my $refcommonFiles  = shift;    # IN  - reference to an array of common files
641
    my $refDeletedFiles = shift;    # IN  - reference to an array of deleted files
642
#
643
#   OUTPUTS:
644
#
645
#   GLOBALS:
646
#
647
#   NOTES:
648
#       none
649
#
650
#==================================================================================================
651
 
652
    my $fileName;
653
 
654
    # just add the new files to CC control...
655
    if ( 0 <= $#{$refNewFiles} )
656
    {
657
        unless ( $opt_noClearcase || $opt_dryRun )
658
        {
659
            print $statusFh "Checking out parent directory '$destinationDir' to allow addition\n";
660
            unless ( $opt_noBranch )
661
            {
662
                # use config spec rules for branching...
663
                doClearCaseCommand( "cleartool co -reserved -ncomment $destinationDir" );
664
            }
665
            else
666
            {
667
                # suppress config spec branching rules
668
                my @description;
669
                @description = doClearCaseCommand( "cleartool describe $destinationDir" );
670
 
671
                my $version;
672
                foreach ( @description )
673
                {
674
                    # search for the directory version...
675
                    if ( m/version.*"(.*)"$/ )
676
                    {
677
                        $version = $1;
678
                        last;
679
                    }
680
                }
681
                doClearCaseCommand( "cleartool co -reserved -ncomment -version $version" );
682
            }
683
        }
684
 
685
        foreach $fileName ( @{$refNewFiles} )
686
        {
687
            # copy file across, then add it to CC control
688
            print $statusFh "Copying '${sourceDir}/${fileName}' to '${destinationDir}/${fileName}'\n";
689
 
690
            unless ( $opt_dryRun )
691
            {
692
                copy( "${sourceDir}/${fileName}", "${destinationDir}/${fileName}" );
693
                unless ( $opt_noClearcase )
694
                {
695
                    print $statusFh "Adding '${destinationDir}/${fileName}' to ClearCase control\n";
696
                    doClearCaseCommand( "cleartool mkelem -eltype file -ci -ncomment ${destinationDir}/${fileName}" );
697
                }
698
            }
699
        }
700
 
701
        # no need to check-in directory if there are files to be deleted
702
        if ( 0 > $#{$refDeletedFiles} )
703
        {
704
            unless ( $opt_noClearcase || $opt_dryRun || $opt_noCheckin )
705
            {
706
                print $statusFh "Addition complete, checking in parent directory '$destinationDir'\n";
707
                doClearCaseCommand( "cleartool ci -ncomment $destinationDir" );
708
            }
709
        }
710
    }
711
 
712
    # find the common files that are different, update the different ones under clearcase control
713
    foreach $fileName ( @{$refcommonFiles} )
714
    {
715
        # do we have matching files?
716
        next if ( 0 == compare( "${sourceDir}/${fileName}", "${destinationDir}/${fileName}" ) );
717
 
718
        # they differ
719
        print $statusFh "Files '${sourceDir}/${fileName}' and '${destinationDir}/${fileName} are different\n";
720
 
721
        # files differ! so check out the destination...
722
        unless ( $opt_noClearcase || $opt_dryRun )
723
        {
724
            print $statusFh "Checking out '${destinationDir}/${fileName}'\n";
725
            unless ( $opt_noBranch )
726
            {
727
                # use config spec rules for branching...
728
                doClearCaseCommand( "cleartool co -reserved -ncomment ${destinationDir}/${fileName}" );
729
            }
730
            else
731
            {
732
                # suppress config spec branching rules
733
                my @description;
734
                @description = doClearCaseCommand( "cleartool describe ${destinationDir}/${fileName}" );
735
 
736
                my $version;
737
                foreach ( @description )
738
                {
739
                    # search for the file version...
740
                    if ( m/version.*"(.*)"$/ )
741
                    {
742
                        $version = $1;
743
                        last;
744
                    }
745
                }
746
                doClearCaseCommand( "cleartool co -reserved -ncomment -version $version" );
747
            }
748
        }
749
 
750
        # copy the new file over the top
751
        unless ( $opt_dryRun )
752
        {
753
            print $statusFh "Copying '${sourceDir}/${fileName}' to '${destinationDir}/${fileName}'\n";
754
            copy( "${sourceDir}/${fileName}", "${destinationDir}/${fileName}" );
755
        }
756
 
757
        # and check it back in again
758
        unless ( $opt_noClearcase || $opt_dryRun || $opt_noCheckin )
759
        {
760
            print $statusFh "Checking '${destinationDir}/${fileName}' in\n";
761
            doClearCaseCommand( "cleartool ci -ncomment ${destinationDir}/${fileName}" );
762
        }
763
    }
764
 
765
    # remove the deleted files
766
    if ( 0 <= $#{$refDeletedFiles} )
767
    {
768
        unless ( $opt_noDelete )
769
        {
770
            # no need to checkout directory if we've added new fies
771
            if ( 0 > $#{$refNewFiles} )
772
            {
773
                unless ( $opt_noClearcase || $opt_dryRun )
774
                {
775
                    print $statusFh "Checking out parent directory '$destinationDir' to allow deletion\n";
776
                    unless ( $opt_noBranch )
777
                    {
778
                        # use config spec rules for branching...
779
                        doClearCaseCommand( "cleartool co -reserved -ncomment $destinationDir" );
780
                    }
781
                    else
782
                    {
783
                        # suppress config spec branching rules
784
                        my @description;
785
                        @description = doClearCaseCommand( "cleartool describe $destinationDir" );
786
 
787
                        my $version;
788
                        foreach ( @description )
789
                        {
790
                            # search for the directory version...
791
                            if ( m/version.*"(.*)"$/ )
792
                            {
793
                                $version = $1;
794
                                last;
795
                            }
796
                        }
797
                        doClearCaseCommand( "cleartool co -reserved -ncomment -version $version" );
798
                    }
799
                }
800
            }
801
 
802
            # now do each deleted file
803
            foreach $fileName ( @{$refDeletedFiles} )
804
            {
805
                print $statusFh "Deleting '${destinationDir}/${fileName}'\n";
806
                unless ( $opt_noClearcase || $opt_dryRun )
807
                {
808
                    doClearCaseCommand( "cleartool rm ${destinationDir}/${fileName}" );
809
                }
810
            }
811
        }
812
 
813
        unless ( $opt_noClearcase || $opt_dryRun || $opt_noCheckin || ( $opt_noDelete && ( 0 > $#{$refNewFiles} ) ) )
814
        {
815
            print $statusFh "Deletion complete, checking in parent directory '$destinationDir'\n";
816
            doClearCaseCommand( "cleartool ci -ncomment $destinationDir" );
817
        }
818
    }
819
}   # updateFiles
820
 
821
 
822
#
823
#==================================================================================================
824
#
825
#   doClearCaseCommand
826
#
827
#   PERSISTENT LOCALS:
828
#       none
829
#
830
sub doClearCaseCommand
831
#
832
{
833
#
834
    # correct number of input parameters?
835
    if ( ($#_+1) != 1 )
836
    {
837
        confess "Incorrect parameter count, expected 1 parameter, saw ", $#_+1, "\n";
838
    }
839
#
840
#   INPUTS:
841
    my $command = shift;
842
#
843
#   OUTPUTS:
844
#
845
#   GLOBALS:
846
#
847
#   NOTES:
848
#       none
849
#
850
#==================================================================================================
851
 
852
    # add the redirection stuff
853
    $command .= " 2>&1";
854
 
855
    # do the command
856
    my @commandResult = `$command`;
857
 
858
    # see if we had an error
859
    if ( 0 != $? )
860
    {
861
        my $message;
862
        $message = "'$command' FAILED ($?): " . join( "", @commandResult) . "\n";
863
        print $statusFh $message;
864
        eval{ confess };
865
        print $statusFh $@;
866
        die $@;
867
    }
868
 
869
    # command succeeded
870
    return @commandResult;
871
 
872
}   # doClearCaseCommand
873
 
874
#
875
#==================================================================================================
876
#
877
#   giveHelp
878
#
879
#   provide the punters with some help...
880
#
881
#   PERSISTENT LOCALS:
882
#       none
883
#
884
sub giveHelp
885
#
886
{
887
#
888
    # correct number of input parameters?
889
    # IGNORED - no input parameters used or parsed!!!!
890
#
891
#   INPUTS:
892
#       none
893
#
894
#   OUTPUTS:
895
#       none
896
#
897
#   GLOBALS:
898
#       none
899
#
900
#   NOTES:
901
#       none
902
#
903
#==================================================================================================
904
 
905
    my $exeName;
906
 
907
    # a slight bit of trickery to cater for those that like to rename things...
908
    $0       =~ m%\\?([^\\]*$)%;        # strip off any leading path stuff
909
    $exeName = $1;
910
 
911
    # give 'em heaps....
912
    print <<EOF;
913
Usage:
914
    $exeName [-dest <dir-name>] [-src=<dir-name>] [-dryRun] [-log <filename>] \
915
        [-recurse] [-noClearCase] [-noDelete] [-noBranch] [-help]
916
 
917
Where:
918
    [-dest <dir-name>]          Specify the destination directory.
919
    [-src <ext-name>]           Specify the source directory.
920
    [-dryRun]                   Do not do anything, just pretend.  NOTE: will
921
                                not recurse through new directories!!!!
922
    [-log <filename>]           Optionally specify a log file for the status
923
                                output information.  If not used, output will
924
                                go to the screen.
925
    [-recurse]                  Recurse through directories for ALL source
926
                                files.
927
    [-admin <vob-name]          Specify the administrative vob to create the
928
                                label in.
929
    [-label <label-name>]       Specify a label name to apply.
930
    [-comment "<lbl-comment>"]  Specify a comment to go with the label.
931
    [-noClearCase]              Do not perform any clear case operations.
932
    [-noViewCheck]              Specify whether clearcase view check to be
933
                                done or not.
934
    [-noDelete]                 Specify whether to delete (for the destination
935
                                directory) files not in the source directory
936
                                but exist in the destination directory.
937
    [-noCheckin]                Set means don't check in the files.
938
    [-noBranch]                 Specify to check file out without branching.
939
    [-help]                     Provide the punter with help - ie this blob of
940
                                text.
941
 
942
    NOTES:
943
    Option abbreviations are supported as long as enough characters are given
944
    to uniquely ID a given option.  Eg. -no won't work, but -noCh or -noD will.
945
EOF
946
 
947
    # we don't want to carry on from here...
948
    exit( 0 );
949
 
950
}   # giveHelp
951