#!/bin/sh
#	This file is part of the Concurrent Versions System CVS.
#	Written by Dick Grune, Vrije Universiteit, Amsterdam.
#	$Header: CM,v 3.1 89/09/25 16:29:59 dick Exp $

#
#		C o m m i t
#	CM commits the present configuration to the RCS repository, AFTER
#	having done a test on conflicts.  The call is
#		CM [ -n ] 'log-message'
#	for a general commit, and
#		CM [ -n ] 'log-message' file ...
#	for a (dangerous) partial commit.
#
#	The -n option restricts the actions to reporting only.
#
Name=CM; export Name

# CVSBIN, CVSLIB and RCSBIN directories
CVSBIN=/home/top/dick/cvs
CVSLIB=/home/top/dick/cvs
RCSBIN=${RCSBIN-/usr/local/bin}
export CVSBIN CVSLIB RCSBIN

# avoid spurious identifications
PATH=${CVSPATH-/bin:/usr/bin}; export PATH

# determine the name of the repository
Repository=""
. $CVSLIB/NR.aux

# get possible options
. $CVSLIB/OP.aux			# sets $Options

# to ACT or not to ACT, that is the question
case "$Options" in
*-n*)
	ACT=echo
	;;
esac

Message="$1"
if	# there was no message
	[ "$Message" = "" ] \
||	# it was a file name
	[ -r "$Message" ]
then
	echo $Name: no modification message! >&2
	exit 1
fi
shift

AutoRemove=yes				# with AutoRemove on,
. $CVSLIB/WL.aux			# set write lock to write in safety

# determine the way we are called
case $# in
0)
	# no file names: treat all pertinent files
	set "`$CVSLIB/FN.aux $Repository`"
	NOPARAMS=yes
	;;
*)
	NOPARAMS=no
	;;
esac

# collect the sets of affected files

OK=yes
. $CVSLIB/CS.aux	# sets CLIST, GLIST, MLIST, OLIST, ALIST, RLIST, WLIST

case $OK in
no)
	# this checks for CLIST as well, since CLIST != "" <-> OK=no
	exit 1
esac

# everything up to date?
case "$GLIST$OLIST$WLIST" in
"")
	;;
*)
	echo $Name: the following files are not up to date\; use UV first >&2
	echo $GLIST$OLIST$WLIST >&2
	exit 1
	;;
esac

# is there anything to do in the first place?
case "$MLIST$RLIST$ALIST" in
"")
	echo $Name: there is nothing to commit! >&2
	exit 1
	;;
esac

# try to get exclusive control of all files to be affected
OK=yes
for User in $MLIST $RLIST
do
	Rcs=$Repository/$User,v
		
	if	# we can lock $Rcs
		$ACT $RCSBIN/rcs -q -l $Rcs
	then	# add it to the list LLIST
		LLIST="$LLIST $User"
	else
		echo $Name: could not lock $Rcs >&2
		OK=no
	fi
done

# try to create all files in the add list
for User in $ALIST
do
	Rcs=$Repository/$User,v
	
	if	# create $Rcs, using the description files $User,[pt]
		$ACT $RCSBIN/rcs -i `cat $User,p` -t$User,t $Rcs
	then	:
	else	# something is wrong
		echo $Name: could not create $Rcs >&2
		OK=no
	fi
done

# did we succeed?
case $OK in
no)
	# something failed; unlock all locked files & remove all added files
	for User in $LLIST
	do	# unlock the RCS file
		Rcs=$Repository/$User,v
		if	# unlock $Rcs
			$ACT $RCSBIN/rcs -q -u $Rcs
		then	:
		else	# something very wrong
			echo $Name: could not UNlock $Rcs >&2
		fi
	done
	
	for User in $ALIST
	do	# remove the newly created RCS file
		Rcs=$Repository/$User,v
		$ACT rm -f $Rcs
	done
	
	# and give up
	exit 1
	;;
esac

# got them all; now go ahead!

# add the files in the ALIST

for User in $ALIST
do
	. $CVSLIB/CI.aux		# a careful check-in; may set OK=no
	$ACT rm -f $User,[pt]		# throw away the info files from AE
done

# modify the files in the MLIST
for User in $MLIST
do
	. $CVSLIB/CI.aux		# a careful check-in; may set OK=no
done

# remove the RCS files in the RLIST
case "$RLIST" in
"")
	# no need for $Repository/Attic
	;;
*)
	# $Repository/Attic needed
	Attic=$Repository/Attic

	if	[ -d $Attic ]
	then	# $Attic exists
		:
	else	# $Attic must be made
		if	$ACT mkdir $Attic >/dev/null 2>/dev/null
		then	:
		else	echo $Name: could not make $Attic
			OK=no
		fi
	fi

	if	[ -d $Attic ]
	then
		for User in $RLIST
		do
			Rcs=$Repository/$User,v
			Old=$Attic/$User,v
			
			if	# we can move the RCS file away
				(	# we can unlock $Rcs
					$ACT $RCSBIN/rcs -u -q $Rcs \
				&&	# we can move it away
					$ACT mv $Rcs $Old
				) \
			||	# the file was already removed
				( [ ! -r $Rcs -a -r $Old ] )
			then	# scratch the entry as well
				$ACT $CVSLIB/SC.aux $User
			else
				echo $Name: attempt to move $Rcs \
							to $Old failed >&2
				OK=no
			fi
		done
	fi
esac

case $NOPARAMS in
yes)	# clear the Mod list, for full commit only
	$ACT cp /dev/null CVS.adm/Mod
	#set time of last update, since commit involves an update
	$ACT rm -f CVS.adm/LastUpdate
	$ACT cp /dev/null CVS.adm/LastUpdate
	;;
esac

# did we succeed?
case $OK in
no)
	exit 1
	;;
esac

# All has gone well: register the commit

Admin=$Repository/Admin
Cfr=CVS.confrec
RcsCfr=$Admin/$Cfr,v
UsrCfr=CVS.adm/$Cfr

# we need the Admin directory
if	# $Admin exists
	[ -d $Admin ]
then	:
else	# $Admin must be made
	if	$ACT mkdir $Admin >/dev/null 2>/dev/null
	then	:
	else	echo $Name: could not make $Admin >&2
		exit 1
	fi
fi

# create the new configuration history file
<CVS.adm/Entries sed 's/|.* /| /' >$UsrCfr

# and commit it
Revision=
. $CVSLIB/CC.aux			# commit configuration record

exit 0

