#!/usr/local/bin/perl


#
# This script:
# 0. maintains the ACLs of repository archive files and directories
#
# Notes:
# 0. needs %{sv} specified in loginfo
#
# Contributed by Noel Yap (yap_noel@jpmorgan.com)

# perl settings
$"=""; # set list separator to null

# constants

$STATE_NONE     = 0;
$STATE_MODIFIED = 1;
$STATE_ADDED    = 2;
$STATE_REMOVED  = 3;
$STATE_LOG      = 4;

$CVSROOT = $ENV{"CVSROOT"};
$CVSROOT =~ s/^.*://;

# subroutines
sub setacl
{
    my ($parent, $entry) = @_;

    if(-d "$entry")
    {
        system("getfacl $parent | grep -v '^default:' | setfacl -f - $entry");
    }
    elsif(-x "$entry")
    {
        system("getfacl $parent | grep -v '^default:' | sed -e 's/:r[-w][-x]/:r-x/' | setfacl -f - $entry");
    }
    else
    {
        system("getfacl $parent | grep -v '^default:' | sed -e 's/:r[-w][-x]/:r--/' | setfacl -f - $entry");
    }
}

# main
# parse command line arguments (file list is seen as one arg)
@argv = split(/ /, shift @ARGV);
$directory = shift @argv; # directory relative to $CVSROOT

foreach $v (@argv)
{
    my ($file, $rev) = split /,/, $v;

    if($file eq "-")
    {
        my ($word1, $rev) = split /,/, $argv[1];

        if($word1 eq "New")
        {
            my ($word2, $rev) = split /,/, $argv[2];

            if($word2 eq "directory") # new directory
            {
                ($file = $directory) =~ s/.*\///; # new directory name without path specification
                $directory =~ s/(.*)\/.*/$1/; # path specification of new directory relative to module

                &setacl("$CVSROOT/$directory", "$CVSROOT/$directory/$file");
            }
        }
        elsif($word1 eq "Imported")
        {
            my ($word2, $rev) = split /,/, $argv[2];

            if($word2 eq "sources") # import
            {
                my @directories;
                my @files;

                while(<STDIN>)
                {
                    chop;

                    if(/^Status:/)
                    {
                        $state = $STATE_NONE;

                        next;
                    }
                    elsif(/^Release Tags:/)
                    {
                        $state = $STATE_ADDED;

                        next;
                    }
                    elsif(/^Log Message:/)
                    {
                        $state = $STATE_LOG;

                        next;
                    }

                    if($state == $STATE_ADDED)
                    {
                        if(/^N /)
                        {
                            $file = $';

                            push @files, "$file ";
                        }
                    }
                }

                foreach $directory (`echo "@files" | xargs -n1 dirname | uniq`)
                {
                    chop $directory;

                    &setacl("$CVSROOT", "$CVSROOT/$directory");
                }

                foreach $file (@files)
                {
                    chop $file;

                    &setacl("$CVSROOT", "$CVSROOT/$file,v");
                }
            }
        }

        last;
    }
    else # the file has been added, modified, or removed
    {
        if(-f "$CVSROOT/$directory/$file,v")
        {
            &setacl("$CVSROOT/$directory", "$CVSROOT/$directory/$file,v");
        }
        else
        {
            &setacl("$CVSROOT/$directory", "$CVSROOT/$directory/Attic/$file,v");
        }
    }
}
