#!/usr/local/bin/perl # Manage a group of elements with one 'leader' to be operated # on as a unit. All group members must be in the same VOB. # Allow knowledgeable users to short-circuit the trigger with this EV. BEGIN { exit 0 if $ENV{CLEARCASE_SKIP_ELEM_GROUP} } use File::Basename; # Conceptually this is "use constant MSWIN ..." but ccperl can't do that. # Perl 5.005 and above uses MSWin32, prior versions use Windows_NT. sub MSWIN { ($^O || $ENV{OS}) =~ /MSWin32|Windows_NT/i ? 1 : 0 } # On Windows we must rely on PATH to find cleartool. On Unix, # /usr/atria/bin/cleartool is always a valid path so we use it. my $CT = MSWIN() ? 'cleartool' : '/usr/atria/bin/cleartool'; # Quit gracefully out of nested invocations. $ENV{CLEARCASE_SKIP_ELEM_GROUP} = "set"; my $action = $ENV{CLEARCASE_OP_KIND}; (my $vob = $ENV{CLEARCASE_VOB_PN}) =~ s%\\%/%g; (my $pn = $ENV{CLEARCASE_PN}) =~ s%\\%/%g; my $dpn = dirname($pn); my $bpn = basename($pn); die "$dpn: $!" unless chdir $dpn; my $sfx = $ENV{CLEARCASE_XN_SFX} || '@@'; chomp(my $leader = qx($CT desc -fmt %[triggers]Np $pn$sfx)); $pn =~ s%^\w:%% if MSWIN(); # don't do this till after the ct-desc if ($leader eq $bpn) { my $cmnt = "$action via $leader trigger on $ENV{CLEARCASE_XPN}"; my @followers; for(qx($CT find $vob -all -cvi -ele "trtype($leader)" -print)) { chomp; s%\\%/%g; # convert \ pathnames to / s%$ENV{CLEARCASE_XN_SFX}.*%%; # remove version extension next if $_ eq $pn; # the leader is already in process if (($action eq 'checkout' && -w) || ($action ne 'checkout' && !-w)) { warn "Warning: $action of '$_' is already done.\n"; } else { push(@followers, $_); } } exit 0 unless @followers; my @cmd = ($CT, $action); if ($action eq 'uncheckout') { push(@cmd, '-rm'); } elsif ($action eq 'checkout') { push(@cmd, '-nc'); } elsif ($action eq 'checkin') { push(@cmd, qw(-ident -c), MSWIN() ? qq("$cmnt") : $cmnt); } if (MSWIN()) { exit(system(@cmd, @followers) >> 8); } else { exec(@cmd, @followers); } } else { warn "Warning: $bpn is a member of a element_group led by '$leader'.\n"; } __END__ =head1 SYNOPSIS % cleartool mktrtype -element -preop checkout,checkin,uncheckout \ -exec /.../triggers/elem_group.tgr % cleartool mktrigger leader follower... This is an B trigger. Thus the type must be instantiated and then attached to individual elements. In the above, I is the name of the group-leader element, IleaderE> is its I, and I is the list of, well, followers. =head1 DESCRIPTION This trigger defines an I, a set of VOB files which are considered a unit that generally need to be checked out and in together. It uses a trick; the trtype name must be the same as that of the "group leader" element. When the trigger runs it determines what trtype fired it and, based on that, whether it's a leader or follower and behaves appropriately. Thus, multiple trigger types may be defined which all exec this trigger script. Each trigger type defines a group named after its leader element. When the group leader is checked out, checked in, or un-checked out, the followers will get the same treatment automatically. If the user attempts to operate on a follower directly, a warning is given (but the operation is still allowed). =head1 LIMITATIONS =over 4 =item * All group members must be in the same VOB. =item * The group leader's basename must be unique within the group. I.e. if the leader is "foo.y" then no followers may have the same basename. =item * Two leaders within the same VOB may not have the same basename. =item * If the group leader element is renamed, the trtype must be renamed too. =item * The leader must not have any other B triggers attached to it (all-element triggers are ok). A corollary of this is that no element may be the leader of more than one group. =back This trigger could be rewritten to rely on hyperlinks instead of the naming-convention trick, which would remove some of the restrictions above at the cost of needing to maintain parallel sets of hyperlinks and trigger attachments. With the current design, attaching the trigger to a set of elements is sufficient to create a working group. =head1 SAMPLE INSTALL Here's a script I've used to test it. Run as C<"attach I I ...>". #!/bin/ksh leader=$1 set -ex cleartool rmtype -rmall -force trtype:$leader cleartool mktrtype -element -preop checkout,checkin,uncheckout \ -execunix "perl /vbs/relmgmt/triggers/elem_group.tgr" \ -execwin "//ccserver/tools/nt/perl/bin/perl //ccserver/relmgmt/triggers/elem_group.tgr" \ $leader cleartool mktrigger $leader "$@" cp elem_group.tgr /vbs/relmgmt/triggers/elem_group.tgr =head1 PORTING This trigger is tested on UNIX and Windows NT4, command line and GUI, using Perls 5.6 and 5.004_04 and ClearCase 4.0. =head1 AUTHOR David Boyce (dsb@cleartool.com) =head1 COPYRIGHT Copyright (c) 2000-2002 David Boyce (dsb@cleartool.com), Clear Guidance Consulting. All rights reserved.