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