Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

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