#!/usr/bin/python

# This commit info check file is used to make sure that files are not checked in
# on protected branches

# The "commitinfo" filter is used to control pre-commit checks.  The filter
# (this program) is invoked with the repository and a list of files to check.  A
# non-zero exit of the filter program will cause the commit to be aborted.

# When the "commitinfo" filter is run the program's working directory is put
# into a temporary directory where the files that are being checked in are
# located and also a directory called CVS is located.
#
# In the CVS directory there is a file called Entries which contains the list of
# files being checked in.  The information includes the file name, revision, &
# branch name.
#
# CVS/Entries file format for commitinfo runs:
#   /file_name/revision///Tbranch_name
#  0   1          2    34     5
# When using a split based on "/" the above numbers indicate where a component
# will be placed in the list

# import commonly needed modules
import sys, string, re, os

# search patterns for branches:
# format is  "repository location", "controlled branches", "authorized users"
#
#   Repository Location:    Location in the repository that we should monitor.
#			    Regular expressions are supported.
#
#   Controlled Branches:    The name of the branch that is restricted.  Regular
#			    expressions are supported.  In controlled branches,
#			    "" means the tip.
#
#   Authorized Users:	    A list of users who are authorized to check-in on
#			    the branch.  Currently regular expressions are NOT
#			    supported.
CONTROLLED_BRANCHES	= [
	[ "/kernel/linux-.*/src$", [ "", "^rh71__branch$" ], [ ] ]
    ]

CVSROOT="^/home/cvs"
FILES_START = 2

# Keep track of our argument count
ARGCOUNT = len(sys.argv)

# Make sure we were passed in a repository & file name
if ARGCOUNT <= FILES_START:
    print "Not enough parameters specified.  Was this called by CVS?"
    sys.exit(0)

# store command line parameters
REPOSITORY  = sys.argv[1]
USER	    = os.environ["USER"]


# Let's read in the CVS/Entries file and place all the branch names in a list.
#   List of branches
controlled_branches = []
# Open the CVS/Entries file for reading
entries_file = open("CVS/Entries", "r")
# Get the branch names
for entry_line in entries_file.readlines():
    # get the branch we are checking in on.  This is located on the 5th
    # split entry.  Also strip out any leading and trailing white space
    branch_name = string.strip( re.split("/", entry_line )[5] )
    # make sure valid entry
    if len( branch_name ) > 0:
	# make sure leading T since there is something in the branch
	# area
	if branch_name[0] == "T":
	    # remove leading T
	    branch_name = branch_name[1:]
	else:
	    print "Strange branch type in CVS/Entries!!!  Is not equal to T"
	    print "Branch name was: ", branch_name
	    print "Branch name length was: ", len(branch_name)
	    print "Entry line was: ", entry_line
	    sys.exit(1)
    # add branch name to list of controlled branches
    controlled_branches.append( branch_name )
# close the file
entries_file.close()

# We will assume they are allowed to checkin
change_allowed = 1

# See if we have a repository that we care about
for x in CONTROLLED_BRANCHES:
    monitored_repository = CVSROOT + x[0]
    monitored_branch_names = x[1]
    authorized_users = x[2]
    # See if we have a match on the repository
    if re.search( monitored_repository, REPOSITORY):
	# They are trying to check in a file on a repository we are watching.
	# Let's go through the list of tags they are checking in on and make
	# sure that they aren't doing something to one that we care about.
	for branch_name in controlled_branches:
	    # See if we need to break out
	    if change_allowed != 1:
		break
	    # go through the list of branches we are monitoring
	    for watched_branch_name in monitored_branch_names:
		if re.search(watched_branch_name, branch_name ):
		    # okay we have a match.  Let's assume that they are not
		    # allowed to change this branch tag
		    change_allowed = 0
		    # Go through the list of authorized users for this tag
		    for y in authorized_users:
			# See if they are one of the authorized users
			if USER == y:
			    # If they are an authorized user then allow them to change the
			    # tag
			    change_allowed = 1
		    # Print an error message if they are not allowed to change the tag
		    if change_allowed != 1:
			print
			print "You are NOT allowed to check-in (commit) on the branch:",
			if branch_name == "":
			    print ' "" (tip / main trunk )'
			else:
			    print branch_name
			print "In the repository:", REPOSITORY
			print "Only the following users are allowed to check-in (commit) on this branch:",
			if len(authorized_users) > 0:
			    print authorized_users
			else:
			    print "(no users)"
			print "Send email to cvs-admin@linux.intel.com if you have questions."
			print
			break

if change_allowed == 1:
    # Success
    sys.exit(0)
else:
    # Failure
    sys.exit(1)
