I've included here a script which enforces tag permissions on a per-user
basis.
I also added a block to check if the tag ends in "_BRANCH", which is our
convention for naming branch tags. If it is a branch tag, no one is allowed
to move or delete it.
Again, to use this, you will need to edit your passwd file to include
comment lines that specify PERMISSION followed by one or more of add mov
del. Users will have tag permissions according to the most recently read
PERMISSION line.
e.g.
# PERMISSION add mov del
admin_user1:dkfjd83748:cvs
admin_user2:dkfjiwuerje8:cvs
# PERMISSION add
developer:dkfjdk83743:cvs
bozo:eifusi83984kd:cvs
Your taginfo should look like this:
DEFAULT /project/cvs_repository/CVSROOT/tag_check.pl $USER
I hope this is somewhat effective to help prevent inadvertent branch tag
deletion or renaming!
(I think we've all been there),
David
#!/usr/bin/perl
# -*-Perl-*-
# tag_check.pl
#
# Perl script to verify a user's permission set defined in the passwd
# file prior to executing tag commands.
#
# Developed using perl, version 5.004_04 built for sun4-solaris
#
# Usage: tag_check.pl username
#
# username = CVS client username $USER passed from taginfo
# Additional automatic taginfo arguments follow username as
# received by this script
# (tag name, operation, repository, [file, revision])
#
# Contributed under the GNU Public License
# No warranty is expressed or implied
##### MAIN PROGRAM
#
# Get program arguments
get_args() or
die "Usage: tag_check.pl <username> <tagname> <operation>\n";
read_permissions() or
die "Could not read permissions\n";
validate_permissions() or
die "Tag $operation not allowed for user $username\n";
exit( 0 );
#
###### END MAIN PROGRAM
###### SUBROUTINES
#
sub get_args {
# For our purposes here, we only want the
# first argument - username
# second argument - tag name
# third argument - operation (add, mov, or del)
$username = shift @ARGV;
if ( $username eq '' ) {
return; # Return undef indicating error
}
$tagname = shift @ARGV;
if ( $tagname eq '' ) {
return; # Return undef indicating error
}
$operation = shift @ARGV;
if ( $operation eq '' ) {
return; # Return undef indicating error
}
return ( OK );
}
sub read_permissions {
# Open the password file for input
open( AFILE, "</project/cvs_repository/CVSROOT/passwd" )
or die "Could not open password file for read\n";
# Read the whole file
while ( <AFILE> ) {
chomp;
push (@lines, $_);
}
close( AFILE );
return(OK);
}
sub validate_permissions {
# Let's be sure we aren't attempting to move or delete a branch tag
# (Our local convention is that all branch tags end in "_BRANCH")
if ( $tagname =~ m/_BRANCH$/ ) {
if ( ( $operation =~ /del/ ) ||
( $operation =~ /mov/ ) ) {
printf "No one is allowed to $operation a branch tag\n";
return;
}
}
# Initialize our allowed permissions to nothing
$allowed = '';
foreach $line (@lines) {
# Search each line for "PERMISSION" and get subsequent fields
@fields = split(/PERMISSION/, $line);
$num_fields = @fields;
if( $num_fields > 1 ) {
$allowed = @fields[ 1 ];
}
# Search each line for matching $username
@fields = split(/:/, $line);
$num_fields = @fields;
if( $num_fields > 1 ) {
$found_user = @fields[ 0 ];
# Username match - validate attempted $operation against $allowed
permissions
if( $found_user eq $username ) {
if ( $allowed =~ m/$operation/ ) {
return( OK );
}
else
{
return;
}
}
}
}
printf "User $username not found in passwd file - contact CVS
administrator\n";
return; # Return undef indicating error
}
#
##### END SUBROUTINES