Subversion Repositories DevTools

Rev

Rev 365 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
361 dpurdie 1
########################################################################
2
# Copyright (C) 1998-2011 Vix Technology, All rights reserved
3
#
4
# Module name   : jats_cclabel.pl
5
# Module type   : Makefile system
6
# Compiler(s)   : Perl
7
# Environment(s): jats
8
#
9
# Description   : A script to perform a number of labeling operations
10
#                 The script will:
11
#                   create a label
12
#                   lock a label
13
#                   unlock a label
14
#                   label all files below the current directory and
15
#                         all directories above the current directory
16
#
17
# Version   Who      Date        Description
18
# 1.0.0     DDP      04-Feb-05   Created
19
#
20
#......................................................................#
21
 
22
require 5.008_002;
23
use strict;
24
use warnings;
25
use JatsError;
26
use JatsSystem;
27
 
28
use Pod::Usage;                             # required for help support
29
use Getopt::Long;
30
use Cwd;
31
 
32
my $VERSION = "1.2.2";                      # Update this
33
 
34
#
35
#   Options
36
#
37
my $opt_debug   = $ENV{'GBE_DEBUG'};        # Allow global debug
38
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
39
my $opt_help = 0;
40
my $opt_label;
41
my $opt_replace;
42
my $opt_create;
43
my $opt_lock;
44
my $opt_unlock;
45
my $opt_show;
46
my $opt_all;
47
my $opt_remove;
48
my $opt_delete;
49
my @opt_exclude;
50
my $opt_test;
51
my $opt_rename;
52
my $opt_auto;
53
my $opt_clone;
54
my $opt_recurse = 1;
55
my $opt_mine;
56
my $opt_info;
57
my $opt_up = 0;
58
my $opt_smartlock;
59
my $opt_checkout = 2;
60
my @opt_files;
61
my @opt_dirs;
62
my $opt_comment;
63
my $opt_vob;
64
my $opt_user;
65
my $opt_admin_vob;
66
my $opt_entire_view;
67
 
68
my $label;
69
my $user_cwd;
70
my @error_list;
71
my @last_results;
72
my $last_result;
73
my $opr_done;
74
my $label_exists = 0;
75
my $label_is_locked = 0;
76
my $build_count = 0;
77
my $vob_desc ='';
78
my $vob_base;
79
 
80
#
81
#   Globals
82
#
83
my $USER = $ENV{'USER'};
84
my $UNIX = $ENV{'GBE_UNIX'};
85
my $autobuild = $ENV{'GBE_ABT'};
86
my $UNIX_VOB_PREFIX = '/vobs';
87
my $VOB_SEP = $UNIX ? '/' : '\\';
88
 
89
#-------------------------------------------------------------------------------
90
# Function        : Mainline Entry Point
91
#
92
# Description     :
93
#
94
# Inputs          :
95
#
96
my $result = GetOptions (
97
                "help:+"        => \$opt_help,
98
                "manual:3"      => \$opt_help,
99
                "verbose:+"     => \$opt_verbose,
100
                "label"         => \$opt_label,             # Flag
101
                "replace"       => \$opt_replace,           # Flag
102
                "create"        => \$opt_create,            # Flag
103
                "lock"          => \$opt_lock,              # Flag
104
                "unlock"        => \$opt_unlock,            # Flag
105
                "smartlock"     => \$opt_smartlock,         # Flag
106
                "show"          => \$opt_show,              # Flag
107
                "remove"        => \$opt_remove,            # Flag
108
                "delete"        => \$opt_delete,            # Flag
109
                "all"           => \$opt_all,               # Flag
110
                "test"          => \$opt_test,              # Flag
111
                "exclude=s"     => \@opt_exclude,           # Multiple strings
112
                "rename=s"      => \$opt_rename,            # String
113
                "clone=s"       => \$opt_clone,             # String
114
                "auto"          => \$opt_auto,              # Flag
115
                "recurse!",     => \$opt_recurse,           # [No]Flag
116
                "mine!",        => \$opt_mine,              # Flag
117
                "info",         => \$opt_info,              # Flag
118
                "up",           => \$opt_up,                # Flag
119
                "checkout!",    => \$opt_checkout,          # [No]Flag
120
                "files=s"       => \@opt_files,             # Multiple strings
121
                "dirs=s"        => \@opt_dirs,              # Multiple strings
122
                "comment=s"     => \$opt_comment,           # String
123
                "vob=s"         => \$opt_vob,               # String
124
                "user=s"        => \$opt_user,              # String
125
                "admin"         => \$opt_admin_vob,         # String
126
                "entireview"    => \$opt_entire_view,       # Flag
127
 
128
                );
129
 
130
                #
131
                #   UPDATE THE DOCUMENTATION AT THE END OF THIS FILE !!!
132
                #
133
 
134
#
135
#   Process help and manual options
136
#
137
pod2usage(-verbose => 0, -message => "Version: $VERSION") if ($opt_help == 1 || ! $result);
138
pod2usage(-verbose => 1) if ( $opt_help == 2 );
139
pod2usage(-verbose => 2) if ( $opt_help > 2 );
140
pod2usage(-verbose => 0, -message => "Version: $VERSION") if ( $#ARGV < 0 );
141
 
142
#
143
#   Configure the error reporting process now that we have the user options
144
#
145
ErrorConfig( 'name'    =>'LABEL',
146
             'verbose' => $opt_verbose,
147
             'on_exit' => \&display_error_list
148
            );
149
 
150
#
151
#   Validate user options
152
#   Use either -spec or one command line argument
153
#
154
Error ("No labels provided") if ( $#ARGV < 0);
155
Error ("Too many labels provided") if ( $#ARGV > 0);
156
Error ("Conflicting options: -clone and -label") if ( $opt_clone && $opt_label );
157
Error ("Conflicting options: -entireview and -label" ) if ( $opt_entire_view && $opt_label );
158
Error ("Conflicting options: -entireview and -exclude" ) if ( $opt_entire_view && @opt_exclude );
159
Error ("Conflicting options: -entireview and -files" ) if ( $opt_entire_view && @opt_files );
160
Error ("Conflicting options: -entireview and -dir" ) if ( $opt_entire_view && @opt_dirs );
161
Error ("Conflicting options: -entireview and -norecurse" ) if ( $opt_entire_view && !$opt_recurse );
162
 
163
$label = $ARGV[0];
164
 
165
#
166
#   Allow the exclude list to contain comma seperated names
167
#
168
@opt_exclude = split( /,/,join(',',@opt_exclude));
169
@opt_files   = split( /,/,join(',',@opt_files));
170
@opt_dirs    = split( /,/,join(',',@opt_dirs));
171
 
172
#
173
#   Determine the user
174
#
175
Error ("USER name not determined" )
176
    unless ( $USER );
177
$opt_user = $USER unless ( $opt_user );
178
 
179
#
180
#   Ensure that the 'cleartool' program can be located
181
#
182
Verbose ("Locate clearcase utility in users path");
183
Error ("Cannot locate the 'cleartool' utility in the users PATH")
184
    unless ( LocateProgInPath('cleartool', '--All') );
185
 
186
#-------------------------------------------------------------------------------
187
#   Construct a vob descriptor, if required
188
#
189
#   There is a potential problem/race condition if doing a rename
190
#   within a static view of a label that is a part of the views config spec
191
#
192
#   Work around: If performing a rename, then ensure that we have the VOB name
193
#
194
if ( ($opt_rename || $opt_entire_view ) && ! $opt_vob )
195
{
196
    Verbose ("Determine VOB name");
197
    ClearCmd ('describe', '-short', 'vob:.' );
198
    Error ("Cannot determine vob from current directory") if ( @error_list || ! $last_result );
199
    $vob_base = $last_result;
200
    $vob_desc = '@' . $vob_base;
201
    $vob_desc =~ s~/~$VOB_SEP~g;
202
    Verbose ("VOB name: $vob_base");
203
}
204
elsif ( $opt_vob )
205
{
206
    Error ("-vob option cannot be used with this command")
207
        if ( $opt_clone || $opt_label || $opt_show || $opt_remove );
208
 
209
    $vob_desc = $UNIX_VOB_PREFIX if ( $UNIX );
210
    $vob_desc = '@/' . $vob_desc . '/' . $opt_vob;
211
    $vob_desc =~ s~//~/~g;
212
    $vob_desc =~ s~/~$VOB_SEP~g;
213
}
214
 
215
#-------------------------------------------------------------------------------
216
#   Check to see if the clone source label exists
217
#       Create a label
218
#
219
if ( $opt_clone )
220
{
221
    Verbose ("Check clone label");
222
    ClearCmd ("describe", "-short", "lbtype:$opt_clone" );
223
    Error ("Clone source label does not exist") if ( @error_list );
224
}
225
 
226
#-------------------------------------------------------------------------------
227
#   Check to see if the label exists
228
#   Determine if its locked at the same time
229
#
230
Verbose ("Check label");
231
ClearCmd ("describe", "-fmt", "%[locked]p", "lbtype:$label$vob_desc" );
232
$label_exists = 1 unless( $opt_test
233
                          || grep ( /Label type not found/, @error_list )
234
                          || grep ( /Unable to determine VOB/, @error_list )
235
                            );
236
if ( $label_exists && $last_result )
237
{
238
    $label_is_locked = ($last_result =~ m~unlocked~)? 0:1;
239
}
240
Verbose ("Check label: Exist:$label_exists, Locked:$label_is_locked");
241
 
242
 
243
#-------------------------------------------------------------------------------
244
#   Process command
245
#       Create a label
246
#
247
if ( $opt_create || ( $opt_auto && ! $label_exists ) )
248
 
249
{
250
    Verbose ("Create label");
251
    Error ("Label already exists") if ( $label_exists );
252
 
253
    my @opts;
254
    push @opts, $opt_comment ? ( '-c', '"' . $opt_comment . '"' ) : '-nc';
255
    push @opts, '-global' if ( $opt_admin_vob );
256
 
257
    ClearCmd ("mklbtype", @opts, "$label$vob_desc" ) unless $opt_test;
258
    Error ("Program Terminated") if ( @error_list );
259
    $opr_done = 1;
260
    $label_exists = 1;
261
}
262
 
263
#-------------------------------------------------------------------------------
264
#   Process command
265
#       Unlock a label - if it was locked
266
#
267
if (( $opt_unlock || $opt_smartlock ) )
268
{
269
    Verbose ("Unlock label");
270
 
271
    if ( $label_is_locked )
272
    {
273
        ClearCmd ("unlock", "lbtype:$label$vob_desc" ) unless $opt_test;
274
        Error ("Program Terminated") if ( @error_list );
275
        $opt_lock = 1 if ( $opt_smartlock );
276
        $label_is_locked = 0;
277
    }
278
    $opr_done = 1;
279
}
280
 
281
#-------------------------------------------------------------------------------
282
#   Process command
283
#       Rename a label
284
if ( $opt_rename )
285
{
286
    Verbose ("Rename label");
287
    ClearCmd ("rename", "lbtype:$label$vob_desc", "lbtype:$opt_rename$vob_desc" ) unless $opt_test;
288
    Error ("Program Terminated") if ( @error_list );
289
    $label = $opt_rename;
290
 
291
    #
292
    #   Also rename the owner of the label
293
    #   This facility is used by the build process to rename WIP labels
294
    #   The idea is to prevent the original owner from modifying the label
295
    #
296
    $opt_mine = 1
297
        if ( $opt_mine && ($opt_mine != 0) );
298
 
299
    $opr_done = 1;
300
}
301
 
302
#-------------------------------------------------------------------------------
303
#   Change label ownership
304
#
305
if ( $opt_mine )
306
{
307
    Verbose ("Change label owner: $opt_user");
308
    ClearCmd ("protect", "-chown", $opt_user, "lbtype:$label$vob_desc" ) unless $opt_test;
309
    Error ("Program Terminated") if ( @error_list );
310
 
311
    $opr_done = 1;
312
}
313
 
314
#-------------------------------------------------------------------------------
315
#   Process command
316
#       Label files and directories
317
 
318
if ( $opt_label || ( $opt_auto && ! $opt_clone && ! $opt_entire_view ))
319
{
320
    my $label_error;
321
    my @cmd_opt;
322
    my %info;
323
    push @cmd_opt, "-replace" if ( $opt_replace );
324
 
325
    #
326
    #   Locate and label directories first
327
    #   Label dirs before we locate files as it simplifies the process
328
    #   of avoiding the current directory
329
    #
330
    determine_dirs_to_label(\%info);
331
    DebugDumpData("Directory Data", \%info ) if (IsVerbose (2));
332
    #
333
    #   Label the directories
334
    #
335
    if ( @{$info{'dir_list'}}  )
336
    {
337
        print "Root : $info{'VobRoot'}\n";
338
        foreach  ( @{$info{'dir_list'}} )
339
        {
340
            my $name = $_;
341
            $name =~ s~^$info{'VobRoot'}/~~;
342
            print "Label: $name\n";
343
        }
344
 
345
        ClearCmd ("mklabel", @cmd_opt, $label, @{$info{'dir_list'}} ) unless $opt_test;
346
        $label_error = 1
347
            if ( display_error_list() );
348
    }
349
 
350
    #
351
    #   Locate and label files
352
    #
353
    determine_files_to_label( \%info );
354
    DebugDumpData("File Data", \%info ) if (IsVerbose (2));
355
 
356
    #
357
    #   Label required files
358
    #   Only do a few at a time so as to limit the command line length
359
    #
360
    if ( @{$info{'label_list'}} )
361
    {
362
        print "Label: $_\n" foreach @{$info{'label_list'}};
363
 
364
        #
365
        #   Process the labels in groups
366
        #   The command line does have a finite length
367
        #
368
        my $base = 0;
369
        my $num = $#{$info{'label_list'}};
370
 
371
        while ( $base <= $num )
372
        {
373
            my $end = $base + 10;
374
            $end = $num if ( $end > $num );
375
 
376
            print ".";
377
            ClearCmd ("mklabel", @cmd_opt, $label, @{$info{'label_list'}}[$base .. $end] ) unless ( $opt_test );
378
            $label_error = 1
379
                if ( display_error_list() );
380
            $base = $end + 1;
381
        }
382
        print "\n";
383
    }
384
 
385
    #
386
    #   Generate warnings based on collected data
387
    #
388
    sub show_warning
389
    {
390
        my ($text, $element, $allowed) = @_;
391
        $allowed = 0 unless ( $allowed );
392
        my $count = scalar(@{$info{$element}});
393
        print $text, ': ', $count, "\n"
394
            if ( $count > $allowed );
395
    }
396
 
397
    print "Exclude: $_\n" foreach @{$info{'exclude_list'}};
398
    print "Exclude(/main/0): $_\n" foreach @{$info{'element0_list'}};
399
    print "Missing File: $_\n" foreach @{$info{'missing_files'}};
400
    print "Checkedout File: $_\n" foreach @{$info{'checked_out_files'}};
401
    print "Checkedout Dir: $_\n" foreach @{$info{'checked_out_dirs'}};
402
 
403
    print        ("Labels applied:", scalar(@{$info{'label_list'}}) + scalar(@{$info{'dir_list'}}), "\n" );
404
    show_warning ("WARNING: Labels applied to checked out parent directories", 'checked_out_pdirs' );
405
    show_warning ("WARNING: Labels applied to checked out files", 'checked_out_files' );
406
    show_warning ("WARNING: Labels applied to checked out dirs", 'checked_out_dirs' );
407
    show_warning ("WARNING: Labels NOT applied to missing files", 'missing_files' );
408
    show_warning ("WARNING: Labels NOT applied to element-0 of files", 'element0_list' );
409
    print        ("WARNING: Path to the VOB root contains a symbolic link. Labeling incomplete") if ( $info{'is_symlink'} );
410
    show_warning ("WARNING: Multiple build.pl files labeled", 'build_files', 1 );
411
 
412
    Error ("Program Terminated") if ( $label_error );
413
    $opr_done = 1;
414
}
415
 
416
#-------------------------------------------------------------------------------
417
#   Process command
418
#       Label entire view.
419
#       Intended for 'buildtool' use as its not as flexible, bit it is faster
420
#
421
if ( $opt_entire_view )
422
{
423
    #
424
    #   The -recurse option doesn't do a good job of reporting
425
    #   errors if the label does not exist. Ensure thatit exists
426
    #
427
    Error ("Label does not exist: $label")
428
        unless ( $label_exists );
429
 
430
    #
431
    #   Calculate the root of the vob
432
    #
433
    my $here =  getcwd();
434
    Verbose ("Current dir: $here");
435
 
436
    $here =~ m~^(.*$vob_base)~;
437
    my $base_dir = $1;
438
    Verbose ("Path of base: $base_dir");
439
    Error ("Calculating Vob Root: $base_dir" ) unless ( -d  $base_dir );
440
    Message ("Labeling ENTIRE view", $base_dir);
441
 
442
    #
443
    #   Use -recurse option to label the entire view
444
    #
445
    my @cmd_opt = ('-recurse', '-follow');
446
    push @cmd_opt, '-replace' if ( $opt_replace );
447
    ClearCmd ("mklabel", @cmd_opt, $label, $base_dir  ) unless ( $opt_test );
448
 
449
    #
450
    #   Can't use the return value or the error list as the command will
451
    #   report errors for many different conditions
452
    #
453
    #   Look at the tail of @last_results
454
    #   The last line is the most informative.
455
    #       Check that its in the right form. ie: ' nnn failed'
456
    #
457
    Error ("Cannot parse comamnd result for recursive label", $last_result )
458
        unless ( $last_result =~ m~(\d+)\s+failed~ );
459
    my $fail_count = $1;
460
    if ( $fail_count )
461
    {
462
        #
463
        #   Pretty up the error list
464
        #   
465
        #
466
        @error_list = grep ( !/No such file or directory.$/, @error_list );
467
        @error_list = grep ( !/^Created label/, @error_list );
468
 
469
        Error ("Labeling entire view: $fail_count Errors" );
470
    }
471
    Message ("Labeling entire view", @last_results[-5 .. -1 ]);
472
 
473
    #
474
    #   Since we don't have 100% confidence in this 'new' labeling
475
    #   process, within the auto build environment we will double
476
    #   check the process.
477
    #
478
    #   Note: This test can be removed at some time in the future
479
    #         When we have more faith in the process
480
    #
481
    unless ( $opt_test )
482
    {
483
        my %info = ();
484
        @opt_files = ();
485
        @opt_dirs = $base_dir;
486
        undef $opt_up;
487
        $opt_recurse = 1;
488
 
489
        Message ("Double checking labeling");
490
        determine_files_to_label( \%info );
491
        if ( @{$info{'label_list'}} )
492
        {
493
            DebugDumpData("DoubleCheck Data", \%info );
494
            Error ('ClearCase label problem detected',
495
                   'Please report to david.purdie@vix-erg.com',
496
                   'Directories and Files not recursively labled as requested'
497
                   );
498
        }
499
    }
500
 
501
    $opr_done = 1;
502
}
503
 
504
#-------------------------------------------------------------------------------
505
#   Process command
506
#       Clone
507
if ( $opt_clone )
508
{
509
    Verbose ("Clone Label");
510
    my @cmd_opt;
511
    push @cmd_opt, "-all" if ($opt_all);
512
 
513
    my @cmd2_opt;
514
    push @cmd2_opt, "-replace" if ( $opt_replace );
515
 
516
    my $count = 0;
517
    my $checked_out_count = 0;
518
 
519
    my $cmd = QuoteCommand ("cleartool", "find", ".", @cmd_opt, "-version", "lbtype($opt_clone)", "-print");
520
    Verbose2($cmd);
521
 
522
    open(CLONECMD, "$cmd 2>&1 |") || Error( "can't run command: $!");
523
    while (<CLONECMD>)
524
    {
525
        chomp;
526
        print($_ . "\n");
527
        $count++;
528
        $checked_out_count++ if ( m/CHECKEDOUT$/ );
529
 
530
        ClearCmd ("mklabel", @cmd2_opt, $label, $_ ) unless ( $opt_test );
531
        last if ( @error_list )
532
    }
533
    close(CLONECMD);
534
 
535
    Error ("Program Terminated") if ( @error_list );
536
    print "Labels applied: $count\n";
537
    print "WARNING: Labels applied to checked out files: $checked_out_count\n" if ( $checked_out_count );
538
    $opr_done = 1;
539
}
540
 
541
 
542
#-------------------------------------------------------------------------------
543
#   Process command
544
#       Show labeled files and directories
545
#       Remove labels
546
 
547
if ( $opt_show || $opt_remove )
548
{
549
    Verbose ("Show Label");
550
    my @cmd_opt;
551
    push @cmd_opt, "-all" if ($opt_all);
552
 
553
    my $cmd = QuoteCommand("cleartool", "find", ".", @cmd_opt, "-version", "lbtype($label)", "-print");
554
    Verbose2($cmd);
555
 
556
    open(SHOWCMD, "$cmd 2>&1 |") || Error( "can't run command: $!");
557
    while (<SHOWCMD>)
558
    {
559
        #
560
        #   Filter output from the user
561
        #
562
        chomp;
563
        print($_ . "\n");
564
 
565
        if ( $opt_remove )
566
        {
567
            ClearCmd ( "rmlabel", $label, $_ ) unless $opt_test;
568
        }
569
 
570
    }
571
    close(SHOWCMD);
572
    $opr_done = 1;
573
}
574
 
575
#-------------------------------------------------------------------------------
576
#   Process command
577
#       Delete a label
578
if ( $opt_delete )
579
{
580
    Verbose ("Delete label");
581
    ClearCmd ("rmtype", "-force", "-rmall", "lbtype:$label$vob_desc" ) unless $opt_test;
582
    Error ("Program Terminated") if ( @error_list );
583
    $opr_done = 1;
584
}
585
 
586
#-------------------------------------------------------------------------------
587
#   Process command
588
#       Lock a label - if not already locked
589
if ( $opt_lock )
590
{
591
    Verbose ("Lock label");
592
    unless ( $label_is_locked )
593
    {
594
        ClearCmd ("lock", "lbtype:$label$vob_desc" ) unless $opt_test;
595
        Error ("Program Terminated") if ( @error_list );
596
    }
597
    $opr_done = 1;
598
}
599
 
600
#-------------------------------------------------------------------------------
601
#   Process command
602
#       Display Label information
603
if ( $opt_info )
604
{
605
    Verbose ("Describe label");
606
    my $cmd = 'cleartool ' . QuoteCommand('describe', '-long', "lbtype:$label$vob_desc" );
607
    Verbose2 $cmd;
608
    my $rv = system ($cmd);
609
    Error ("Program Terminated") if ( $rv / 256 );
610
    $opr_done = 1;
611
}
612
 
613
#-------------------------------------------------------------------------------
614
#   End of all operations
615
#   If nothing has been done, then let the user know
616
#
617
Error ("No valid operations specified. Try -h") unless ( $opr_done );
618
 
619
#
620
#   End of program
621
#   Highlight test mode if its been active
622
#
623
print ("End program", $opt_test ? " [Test Mode]":'' ,"\n");
624
exit 0;
625
 
626
#-------------------------------------------------------------------------------
627
# Function        : determine_dirs_to_label
628
#
629
# Description     : Determine diretories up to the VOB root that need to be
630
#                   labeled.
631
#
632
# Inputs          : $data           - Ref to hash to collect info
633
#
634
# Returns         : Nothing
635
#                   Values populated into $data hash
636
#
637
sub determine_dirs_to_label
638
{
639
    my ($data) = @_;
640
    Verbose ("Locate directories to label");
641
 
642
    #
643
    #   Init data - so that we can see what to expect
644
    #
645
    $data->{'dir_list'} = [];
646
    $data->{'checked_out_pdirs'} = [];
647
    $data->{'is_symlink'} = 0;
648
    $data->{'VobRoot'} = '';
649
    $data->{'DirsSeen'} = {};
650
 
651
    #
652
    #   Figure out what to do
653
    #       Label dirs upwards if requested, or we are not doing files or dirs
654
    #       Label the current directory unless asked to do files/dirs or up-only
655
    #
656
    my $do_files = scalar @opt_files;
657
    my $do_dirs  = scalar @opt_dirs;
658
    my $do_up = $opt_up || ( ! $do_files && ! $do_dirs );
659
 
660
    #
661
    #   Build up a list of parent directories up to the root of the VOB
662
    #   that do not have the desired label
663
    #
664
    if ( $do_up )
665
    {
666
        Verbose ("Examine parent directories");
667
        examine_directory (getcwd(), $data, 1);
668
 
669
        #
670
        #   If the user has provided a list of directories or files then we should label
671
        #   the directory components too
672
        #
673
        my @dirs_from_files;
674
        foreach my $file ( @opt_files )
675
        {
676
            my $dir = $file;
677
            $dir =~ tr~\\/~/~s;
678
            $dir =~ s~/[^/]+$~~ unless ( -d $dir);
679
            push @dirs_from_files, $dir;
680
        }
681
 
682
        foreach my $dir ( @opt_dirs , @dirs_from_files)
683
        {
684
            examine_directory ($dir, $data);
685
        }
686
    }
687
}
688
 
689
#-------------------------------------------------------------------------------
690
# Function        : examine_directory
691
#
692
# Description     : Examine one directory entry
693
#
694
# Inputs          : $path           - Path to examine
695
#                   $data           - Ref to hash to collect info
696
#                   $find_root      - Finding root
697
#
698
# Returns         : 
699
#
700
sub examine_directory
701
{
702
    my ($path, $data, $find_root) = @_;
703
    my $is_symlink;
704
    $path =~ tr~\\/~/~s;
705
 
706
    while ( 1 )
707
    {
708
        return if ( defined $data->{'DirsSeen'}{$path} );
709
        $data->{'DirsSeen'}{$path} = 1;
710
 
711
        my $cmd = QuoteCommand ("cleartool", "describe", $path);
712
        my $has_label;
713
        my $is_versioned;
714
        my $start_labels;
715
        my $link;
716
        my $is_checkedout;
717
 
718
        Verbose($cmd);
719
        my $cmd_handle;
720
        open($cmd_handle, "$cmd 2>&1 |") || Error( "Can't run command: $!");
721
        while (<$cmd_handle>)
722
        {
723
            #
724
            #   Filter output from the user
725
            #
726
            chomp;
727
            Verbose2($_);
728
            push @error_list, $_    if ( m~Error:~ );
729
            $link = $1              if ( m~^symbolic link.* -> (.*)~ );
730
            $is_versioned = 1       if ( m~^directory version ~ );
731
            $start_labels = 1       if ( m~^\s+Labels:$~ );
732
            $is_checkedout = 1      if ( m~[\\/]CHECKEDOUT"~ );
733
            next unless ( $start_labels );
734
            $has_label = 1          if ( m~^\s+$label$~ );
735
        }
736
        close($cmd_handle);
737
        $data->{'VobRoot'} = $path if ( $find_root );
738
 
739
        #
740
        #   Symbolic link located
741
        #   Resolve the link and continue
742
        #   The link cannot be labeled. If we can label the resolved link then
743
        #   all is good, otherwise we have a a problem
744
        #
745
        if ( $link )
746
        {
747
            $is_symlink = 1;
748
            $path =~ s~[/][^/]*$~~;
749
            $path = $path . '/' . $link;
750
            $path =~ s~/[^/]+/\.\./~/~;
751
            Verbose("Symbolic link: $link, Path: $path" );
752
            next;
753
        }
754
 
755
        #
756
        #   Parent directory checked out. Options:
757
        #       0: Don't Label checkedout elements
758
        #       1: Do Label only checkout elements
759
        #       2: Label both (default)
760
        #
761
        if ( $is_checkedout )
762
        {
763
            $has_label = 2 if ( $opt_checkout == 0 );
764
            push @{$data->{'checked_out_pdirs'}}, $_;
765
        }
766
        else
767
        {
768
            $has_label = 2 if ( $opt_checkout == 1 );
769
        }
770
 
771
        last unless ( $is_versioned );
772
        unshift @{$data->{'dir_list'}}, $path unless ( $has_label );
773
 
774
        #
775
        #   Versioned directory seen
776
        #   If the previous one loop was a symlink, then we have labeled
777
        #   the link correctly
778
        #
779
        $is_symlink = 0;
780
 
781
        #
782
        #   Calculate the path of the parent directory
783
        #   Stop when we get to the top ( ie z: is not good )
784
        #
785
        last unless ( $path =~ s~[/][^/]*$~~);
786
        last unless ( length $path);
787
        last if ( $path =~ m~:$~ );
788
    }
789
 
790
    #
791
    #   Accumulate bad symlinks
792
    #
793
    $data->{'is_symlink'}++
794
        if ( $is_symlink );
795
}
796
 
797
 
798
#-------------------------------------------------------------------------------
799
# Function        : determine_files_to_label
800
#
801
# Description     : Determine a list of files that need to be
802
#                   labeled.
803
#
804
# Inputs          : $data           - Ref to hash to collect info
805
#
806
# Returns         : Nothing
807
#                   Values populated into $data hash
808
#
809
sub determine_files_to_label
810
{
811
    my ($data) = @_;
812
    Verbose ("Locate files to label");
813
 
814
    #
815
    #   Init data - so that we can see what to expect
816
    #
817
    $data->{'label_list'} = [];
818
    $data->{'checked_out_files'} = [];
819
    $data->{'checked_out_dirs'} = [];
820
    $data->{'missing_files'} = [];
821
    $data->{'element0_list'} = [];
822
    $data->{'exclude_list'} = [];
823
    $data->{'build_files'} = [];
824
 
825
    #
826
    #   Figure out what to do
827
    #       Label dirs upwards if requested, or we are not doing files or dirs
828
    #       Label the current directory unless asked to do files/dirs or up-only
829
    #
830
    my $do_files = scalar @opt_files;
831
    my $do_dirs  = scalar @opt_dirs;
832
    push @opt_dirs, '.' unless ($opt_up || $do_files || $do_dirs);
833
 
834
    my @check_these;
835
 
836
    #
837
    #   Examine all specified files and directories
838
    #       Detect nasty files
839
    #       Don't label elements that have already been labled
840
    #
841
    #   Use the cleartool find command as it will allow us to determine
842
    #   if the element has already been labled.
843
    #
844
    #   Note: cleartool find works on files and directories
845
    #
846
    my $doing_files = 0;
847
    foreach my $dir (@opt_dirs ,undef, @opt_files )
848
    {
849
        if ( ! defined $dir )
850
        {
851
            $doing_files = 1;
852
            next;
853
        }
854
 
855
        #
856
        #   If this element is from the files option and its not a file
857
        #   this skip it - the path will have been processed
858
        #
859
        next if ($doing_files  && -d $dir );
860
 
861
        #
862
        #   Remove possible trailing / from user specified directory as
863
        #   clearcase doesn't handle these too well.
864
        #
865
        $dir =~ tr~\\/~/~s;
866
        $dir =~ s~/+$~~;
867
        $dir = '/' unless ( $dir );
868
 
869
        Verbose ("Examine subdirectory: $dir");
870
        my $find_arg = $opt_recurse && !$doing_files ? '' : '-nrecurse';
871
        my $cmd = QuoteCommand ("cleartool", "find", "$dir", "-cview", $find_arg, "-version", "{!lbtype($label)}", "-print");
872
        Verbose2($cmd);
873
 
874
        my $cmd_handle;
875
        @error_list = ();
876
        @last_results = ();
877
        $last_result = undef;
878
        open($cmd_handle, "$cmd 2>&1 |") || Error( "can't run command: $!");
879
        while (<$cmd_handle>)
880
        {
881
            #
882
            #   Filter output from the user
883
            #
884
            chomp;
885
            Verbose2($_);
886
            if ( m~Error:~ )
887
            {
888
                #
889
                #   In AutoBuild Mode allow the error "Not a vob object"
890
                #   This may be cause by generated directory that has been checked in
891
                #   If the directory gets re-generated then the Find gets confused.
892
                #
893
                if ( $autobuild && m~Not a vob object:~ )
894
                {
895
                    Warning( "AutoBuildTool supressed: $_" );
896
                    next;
897
                }
898
                push @error_list, $_;
899
                next;
900
            }
901
            push @check_these, $_;
902
        }
903
        close($cmd_handle);
904
        Error ("Program Terminated") if ( @error_list );
905
    }
906
 
907
    #
908
    #   Have a list of files to examine to see if we really want to label them
909
    #
910
    find:
911
    foreach ( @check_these )
912
    {
913
        ( my $file = $_ ) =~ s~@@.*~~;
914
 
915
        #
916
        #   If we are not recursing - then skip directories
917
        #
918
        next find
919
            if ( ! $opt_recurse  && -d $file );
920
 
921
        tr~\\/~/~s;
922
        s~^\./~~;
923
 
924
        #
925
        #   Exclude files and directories that are the /main/0 element
926
        #   These may be in a view due to branching rules
927
        #   The contents will be empty. Labeling them will create uglyness
928
        #   it simplifies life if we don't label them
929
        #
930
        if ( m~/main/0$~ )
931
        {
932
            push @{$data->{'element0_list'}}, $_;
933
            next find;
934
        }
935
 
936
        #
937
        #   Has it been excluded
938
        #
939
        foreach my $name ( @opt_exclude )
940
        {
941
            if ( m~(^|/)$name[/@]~ )
942
            {
943
                push @{$data->{'exclude_list'}}, $_;
944
                next find;
945
            }
946
        }
947
 
948
        #
949
        #   Ensure that the file is really present
950
        #   In a static sandbox CC retains memory of files that have been
951
        #   deleted. This may be intentional it may be an error
952
        #
953
        if ( ! -e $file && ! $opt_all )
954
        {
955
            push @{$data->{'missing_files'}}, $file;
956
            next find;
957
        }
958
 
959
        #
960
        #   Count build.pl files
961
        #   Not really useful for Ant Builds 
962
        #
963
        if ( m~(^|/)build.pl@~i )
964
        {
965
            push @{$data->{'build_files'}}, $_
966
        }
967
 
968
        #
969
        #   Handle Checked out files
970
        #
971
        if ( m/CHECKEDOUT$/ )
972
        {
973
            next find if ( $opt_checkout == 0 );
974
            if ( -d $file  )
975
            {
976
                push @{$data->{'checked_out_dirs'}}, $_;
977
            }
978
            else
979
            {
980
                push @{$data->{'checked_out_files'}}, $_;
981
            }
982
        }
983
        else
984
        {
985
            next find if ( $opt_checkout == 1 );
986
        }
987
 
988
        push @{$data->{'label_list'}}, $_ ;
989
    }
990
}
991
 
992
#-------------------------------------------------------------------------------
993
# Function        : display_error_list
994
#
995
# Description     : Display the error list
996
#                   This function is registered as an Error callback function
997
#                   it will be called on error exit
998
#
999
#                   Will clear error list when called, so that it can be used
1000
#                   in non-exit situations.
1001
#
1002
# Inputs          :
1003
#
1004
# Returns         : true            - Errors in list
1005
#                   false           - No error in list
1006
#
1007
sub display_error_list
1008
{
1009
    return 0 unless ( @error_list );
1010
    print "$_\n" foreach ( @error_list );
1011
    @error_list = ();
1012
    return 1;
1013
}
1014
 
1015
#-------------------------------------------------------------------------------
1016
# Function        : ClearCmd
1017
#
1018
# Description     : Similar to the system command
1019
#                   Does allow standard output and standard error to be captured
1020
#                   to a log file
1021
#
1022
#                   Used since I was having problems with calling other programs
1023
#                   and control-C. It could hang the terminal session.
1024
#
1025
# Inputs          :
1026
#
1027
# Returns         :
1028
#
1029
sub ClearCmd
1030
{
1031
    my $cmd = QuoteCommand (@_);
1032
    Verbose2 "cleartool $cmd";
1033
 
1034
        @error_list = ();
1035
        @last_results = ();
1036
        $last_result = undef;
1037
        my $cmd_handle;
1038
        open($cmd_handle, "cleartool $cmd  2>&1 |")    || Error "can't run command: $!";
1039
        while (<$cmd_handle>)
1040
        {
1041
            chomp;
1042
            $last_result = $_;
1043
            $last_result =~ tr~\\/~/~s;
1044
            push @last_results, $last_result;
1045
            Verbose ( "cleartool resp:" . $_);
1046
            push @error_list, $_ if ( m~Error:~ );
1047
        }
1048
        close($cmd_handle);
1049
 
1050
    Verbose2 "Exit Status: $?";
1051
    return $? / 256;
1052
}
1053
 
1054
#-------------------------------------------------------------------------------
1055
#   Documentation
1056
#
1057
 
1058
=pod
1059
 
1060
=for htmltoc    GENERAL::ClearCase::
1061
 
1062
=head1 NAME
1063
 
1064
jats_cclabel - ClearCase label operations
1065
 
1066
=head1 SYNOPSIS
1067
 
1068
jats cclabel [options] label
1069
 
1070
 Options:
1071
    -help              - brief help message
1072
    -help -help        - Detailed help message
1073
    -man               - Full documentation
1074
    -auto              - Auto create and label
1075
    -clone=xxx         - Apply new label to objects with label xxx
1076
    -create            - Create a label
1077
    -label             - Labels a directory tree
1078
    -entireview        - Labels entire view
1079
    -lock              - Lock the label
1080
    -remove            - Remove label from elements
1081
    -delete            - Delete label label from elements and vob
1082
    -rename=xxx        - Rename a label
1083
    -show              - Show elements with the label
1084
    -unlock            - Unlock the label
1085
    -[no]mine          - Set label owner to user.
1086
    -info              - Provide label information
1087
    -smartlock         - Unlock and Relock label, if it was locked
1088
 
1089
 Modifiers
1090
    -admin             - Modifies label creation to create global label
1091
    -all               - Process all the VOB. Use with -show, -remove and -clone.
1092
    -replace           - Replace existing labels. Use with -label
1093
    -exclude=n1,n2     - Exclude files and directories from the -label process.
1094
    -files=f1,f2,...   - Label only the named files.
1095
    -dirs=d1,d2,...    - Label only the named dirs.
1096
    -[no]recurse       - Exclude all subdirectories from the -label process.
1097
    -[no]checkout      - Don't/Do label checked out files. Default - label both
1098
    -up                - Only label directories upwards. Do not label files/dirs
1099
    -test              - Just show the labels that would be added.
1100
    -comment=text      - Comment to add to label when created.
1101
    -user=name         - Used with -mine to specify user
1102
    -vob=name          - Specify VOB name when manipulating label.
1103
                         Not allowed with -label, -clone, -remove and -show
1104
 
1105
=head1 OPTIONS
1106
 
1107
=over 8
1108
 
1109
=item B<-help>
1110
 
1111
Print a brief help message and exits.
1112
 
1113
=item B<-help -help>
1114
 
1115
Print a detailed help message with an explanation for each option.
1116
 
1117
=item B<-man>
1118
 
1119
Prints the manual page and exits.
1120
 
1121
=item B<-all>
1122
 
1123
This option modifies the operation of the -show, -remove, -clone and -label
1124
operations.
1125
 
1126
With this option the processing extends to the entire VOB. This is a slower, but
1127
more complete operation.
1128
 
1129
With this option the -label will label files that are not currently present in a
1130
static view.
1131
 
1132
=item B<-auto>
1133
 
1134
This option will create the label if the label does not exist and then label the
1135
current directory.
1136
 
1137
This option is a combination of a -create and a -label, except that it will
1138
not fail if the label already exists.
1139
 
1140
=item B<-clone=xxx>
1141
 
1142
This option will apply a new label to all objects that have the label xxx.
1143
The effect is that the specified label is clone of label xxx.
1144
 
1145
This operation may be used to initiate a new build label by first cloning an
1146
existing build before tailoring the file set.
1147
 
1148
=item B<-create>
1149
 
1150
This option will create the specified label. The operations will fail if the
1151
label is already present in the current VOB.
1152
 
1153
The label will be created in the current VOB with a comment if one is provided.
1154
 
1155
=item B<-delete>
1156
 
1157
This option will delete the specified label from all objects with the label
1158
and remove the label from the VOB. You need to be the owner of this label in
1159
order for the operation to occur without error.
1160
 
1161
=item B<-exclude name>
1162
 
1163
Exclude specific files and directories from the labeling process.
1164
 
1165
The names may be comma separated, or the option may be specified multiple times.
1166
 
1167
Wildcards are supported in the form of regular expressions. All .h
1168
files may be excluded with the command "-exclude=.*\.h".
1169
 
1170
examples:
1171
    -exclude=test will exclude all directory trees called test
1172
 
1173
    -exclude=test,play will exclude all directory trees called 'test' and 'play'
1174
 
1175
    -exclude=test/seattle will exclude all directory trees called test/seattle
1176
 
1177
=item B<-files=name>
1178
 
1179
Label only the specified files. The names may be comma separated, or the option
1180
may be specified multiple times.
1181
 
1182
The use of this option overrides the default operation of the label utility
1183
and the entire file tree will not be scanned. Only the specified files will be
1184
labeled.
1185
 
1186
Wildcards are not supported.
1187
 
1188
Directories will not be recursed, but may be labeled.
1189
 
1190
The component paths of the named path will also be labeled, when the B<-up> is
1191
used.
1192
 
1193
=item B<-dirs=name>
1194
 
1195
Label only the specified directories. The names may be comma separated, or the
1196
option may be specified multiple times.
1197
 
1198
The use of this option overrides the default operation of the label utility
1199
and the entire file tree will not be scanned. Only the specified directories
1200
will be labeled.
1201
 
1202
Wildcards are not supported.
1203
 
1204
The component paths of the named path will also be labeled, when the B<-up> is
1205
used.
1206
 
1207
=item B<-label>
1208
 
1209
This option will label all the files in, and below, the current directory and
1210
all the parent directories.
1211
 
1212
The -replace option may be used to force labels to be moved.
1213
 
1214
The -norecurse option may be used to prevent recursion into all subdirectories,
1215
and the labeling of any directories.
1216
 
1217
=item B<-entireview>
1218
 
1219
This option will label all the files and directories in the current view. It may be
1220
invoked at any point within the view.
1221
 
1222
This option is intended to be used by the 'autobuild' process. It is not as
1223
flexible as the B<-label> option, nor can it be used in conjunction with
1224
may other options.
1225
 
1226
The -replace option may be used to force labels to be moved.
1227
 
1228
The option will determine the root of the vob and label all components in the
1229
current view, following vib-symbolic links in the process.
1230
 
1231
=item B<-lock>
1232
 
1233
This option will lock the specified label. This operation will be done after any
1234
other operations have been performed.  If the label is already locked then
1235
this operation will not attempt to lock the label.
1236
 
1237
=item B<-remove>
1238
 
1239
This option will remove the specified label from all objects with the label.
1240
 
1241
If the -all option is present then all elements in the entire VOB will be
1242
examined, otherwise just this in and below the current directory will be
1243
examined.
1244
 
1245
The -all operation may take some time.
1246
 
1247
=item B<-rename=xxx>
1248
 
1249
This option will rename a label. The new name of the label is provided as the
1250
argument after the option. If any further operation are to be performed the
1251
new label name will be used.
1252
 
1253
By default, the owner of the label will be set to the current user. This
1254
mechanism is used in the build process. This -nomine option changes this
1255
behaviour.
1256
 
1257
=item B<-replace>
1258
 
1259
This option may be used with the -label command to force labels to be moved to
1260
the file or directory in the current view.
1261
 
1262
=item B<-[no]recurse>
1263
 
1264
This option modifies the behaviour of the B<-label> operation. The default
1265
behaviour is to label all files and directories in and below the current
1266
directory.
1267
 
1268
The B<-norecurse> option prevents recursion into subdirectories and the labeling
1269
of subdirectories. Only files in the current directory will be labeled. -
1270
together with parent directories as required.
1271
 
1272
=item B<-show>
1273
 
1274
This operation will show all clearcase elements with the specified label.
1275
 
1276
If the -all option is present then all elements in the entire VOB will be shown,
1277
otherwise just this in and below the current directory will be displayed.
1278
 
1279
The -all operation may take some time.
1280
 
1281
=item B<-test>
1282
 
1283
This operation will prevent the program from performing any destructive
1284
operation. It may be used to show what operation would be done.
1285
 
1286
=item B<-unlock>
1287
 
1288
This option will unlock the specified label. This operation will be done before
1289
any other operations have been performed.  If the label is not locked then
1290
this operation will not attempt to unlock the label.
1291
 
1292
=item B<-[no]mine>
1293
 
1294
This option will set the owner of the label to the current user. This
1295
operation is performed automatically when a -rename operation occurs. The
1296
"no" option allows this behaviour to be modified.
1297
 
1298
=item B<-up>
1299
 
1300
This option will prevent the utility from labeling files and directories below
1301
the current directory. Only directories above the current directory will be
1302
labeled.
1303
 
1304
This option may be specifically used with -dirs and -files to label the named
1305
directories and files as well as the directoires up, from the current directory.
1306
 
1307
=item B<-info>
1308
 
1309
This option will provide label information. It uses the clearcase describe
1310
command.
1311
 
1312
=item B<-smartlock>
1313
 
1314
This option will unlock the label for the duration of the operations and then
1315
lock the label again - if it was locked to start with. Smart locking allows
1316
label operations while retaining the lock state of the label.
1317
 
1318
=item B<-[no]checkout>
1319
 
1320
This option affects the processing of checked out files. There are three modes of
1321
operation:
1322
 
1323
=over 4
1324
 
1325
=item 1
1326
 
1327
-nocheckout      Checked out files are not labeled
1328
 
1329
=item 2
1330
 
1331
-checkout        Only checked out files are labeled
1332
 
1333
=item 3
1334
 
1335
Neither          All files are labeled.
1336
 
1337
=back
1338
 
1339
=item B<-comment=text>
1340
 
1341
This option allows a comment to be added to a label when it is created. The
1342
option has no effect if the label is not created.
1343
 
1344
=item B<-vob=name>
1345
 
1346
This option is used by commands that do not acutally place labels on files to
1347
manipulate when the user's current directry is not within a view. This allows lables to be created,
1348
locked and unlocked without having a view present.
1349
 
1350
=item B<-admin>
1351
 
1352
This option modifies the label creation process to create a global label. This
1353
may be used in an admin vob.
1354
 
1355
=back
1356
 
1357
=head1 DESCRIPTION
1358
 
1359
The L<JATS|TOOLS::jats> wrapper script will invoke this command when the 'label'
1360
command is run and the script determine the ClearCase is the default VCS.
1361
 
1362
This program provides a number of useful ClearCase labeling operations. These
1363
are:
1364
 
1365
=over 8
1366
 
1367
=item   *
1368
 
1369
create - create a label
1370
 
1371
=item   *
1372
 
1373
unlock - unlock the specified label
1374
 
1375
=item   *
1376
 
1377
rename - rename a label
1378
 
1379
=item   *
1380
 
1381
mine - change ownership of a label
1382
 
1383
=item   *
1384
 
1385
label - label a directory tree
1386
 
1387
=item   *
1388
 
1389
remove - remove the label from all labeled objects
1390
 
1391
=item   *
1392
 
1393
show - show all objects tagged with the label
1394
 
1395
=item   *
1396
 
1397
lock - lock a label
1398
 
1399
=item   *
1400
 
1401
delete - delete all instances of a label and the label
1402
 
1403
=item   *
1404
 
1405
info - describe the labels properties
1406
 
1407
=back
1408
 
1409
The various operations may be mixed in the one command. The order of the
1410
operations is: create, unlock, rename, mine, label, show, remove, delete, lock
1411
and info.
1412
 
1413
Thus it is possible to create a label, label a directory tree and then lock the
1414
label.
1415
 
1416
=head1 EXAMPLE
1417
 
1418
jats label -create -label -lock daf_br_23.0.0.syd
1419
 
1420
=cut
1421