#! @SH@
#
# @(#)unix_platform.sh 1.15  Copyright (c) Andrew Chang
# platform specific stuff for bk.sh
#
__platformInit()
{
	# Unix specific stuff
	GUI_BIN=$BIN
	RM=/bin/rm
	ECHO=echo
	TMP=/tmp/
	DEV_NULL=/dev/null
	if [ -x /usr/bin/mailx ]
	then	MAIL_CMD=mailx
	else	MAIL_CMD=mail
	fi
	if [ -x /usr/bin/nawk ]
	then	AWK=nawk
	else	AWK=awk
	fi
	ext=""	# Unlike win32, Unix binary does not have .exe extension
	tcl=""
	if type wish8.2 >/dev/null 2>&1
	then wish=wish8.2
	elif type wish8.0 >/dev/null 2>&1
	then wish=wish8.0
	else wish=wish
	fi
	if [ "X$EDITOR" = X ]
	then EDITOR=vi
	fi
	if [ "X$PAGER" = X ]
	then PAGER=more
	fi
}
#! /bin/sh

# import.sh - import various sorts of files into BitKeeper
# TODO
#	we allow repeated imports on patches but don't error check the other
#	cases.  We should fail if the repository is not empty.
# @(#)import.sh 1.83 wscott@wscott1.homeip.net

import() {
	if [ X"$1" = "X--help" ]
	then	bk help import; exit 0;
	fi
	COMMENTS=
	COMMIT=YES
	CUTOFF=
	EX=NO
	EXCLUDE=""
	FIX_ATTIC=NO
	FORCE=NO
	INC=NO
	INCLUDE=""
	LIST=""
	PARALLEL=1
	QUIET=
	REJECTS=YES
	RENAMES=YES
	SYMBOL=
	TYPE=
	UNDOS=
	VERBOSE=-q
	VERIFY=-h
	while getopts ACc:efFHij:l:qRrS:t:uvxy: opt
	do	case "$opt" in
		A) FIX_ATTIC=YES;;		# doc 2.0
		c) CUTOFF=-c$OPTARG;;		# doc 2.0
		C) COMMIT=NO;;
		e) EX=YES;;			# undoc 2.0 - same as -x
		x) EX=YES;;			# doc 2.0
		f) FORCE=YES;;			# doc 2.0
		F) CLOCK_DRIFT=5
		   export CLOCK_DRIFT;;		# doc 2.1
		H) VERIFY=;;			# doc 2.0
		i) INC=YES;;			# doc 2.0
		j) PARALLEL=$OPTARG;;		# doc 2.0
		l) LIST=$OPTARG;;		# doc 2.0
		S) SYMBOL=-S$OPTARG;;		# doc 2.0
		r) RENAMES=NO;;			# doc 2.0
		R) REJECTS=NO;;
		t) TYPE=$OPTARG;;		# doc 2.0
		q) QUIET=-qq; export _BK_SHUT_UP=YES;;	# doc 2.0
		u) UNDOS=-u;;			# doc 2.0
		v) VERBOSE=;;			# doc 2.0
		y) COMMENTS="$OPTARG";;
		esac
	done
	test X$CLOCK_DRIFT != X -a X$PARALLEL != X1 && {
		echo Parallel imports may not set CLOCK_DRIFT
		exit 1
	}
	shift `expr $OPTIND - 1`
	if [ X"$1" = X -o X"$2" = X -o X"$3" != X ]
	then	bk help -s import; exit 1;
	fi
	gettype $TYPE
	if [ $TYPE = patch ]
	then	if [ ! -f "$1" ]
		then	echo import: "$1" is not a patch file
			exit 1
		fi
		if [ X"$LIST" != X ]
		then	echo import: no lists allowed with patch files
			exit 1
		fi
		if [ "$EX" != NO -o $INC != NO ]
		then	echo import: no include/excludes allowed with patch files
			exit 1
		fi
	else	if [ ! -d "$1" ]
		then	echo import: "$1" is not a directory
			exit 1
		fi
	fi
	if [ ! -d "$2" ]
	then	echo import: "$2" is not a directory, run setup first
		exit 1
	fi
	if [ ! -d "$2/BitKeeper" ]
	then	echo "$2 is not a BitKeeper package"; exit 1
	fi
	if [ ! -w "$2" -o ! -w "$2/BitKeeper" ]
	then	echo import: "$2" is not writable
		exit 1
	fi
	HERE=`bk pwd`
	if [ $TYPE != patch ]
	then	cd "$1"
		FROM=`bk pwd`
		cd "$HERE"
	else	FROM="$1"
		test -f "$FROM" || {
			echo "No such file $FROM"
			exit 1
		}
	fi
	cd "$2"
	TO="`bk pwd`"
	getIncExc
	if [ X"$LIST" != X ]
	then	cd "$HERE"
		if [ ! -s "$LIST" ]
		then	echo Empty file $LIST
			exit 1
		fi
		read path < $LIST
		case "$path" in
		/*) echo \
	    "Absolute pathnames are disallowed, they should relative to $FROM"
		    exit 1;;
		esac
		cd "$FROM"
		if [ ! -f "$path" ]
		then	echo No such file: $FROM/$path
			exit 1
		fi
		cd "$HERE"
		sed 's|^\./||'< $LIST > ${TMP}import$$
	else	if [ $TYPE != patch ]
		then	if [ X$QUIET = X ]
			then	echo Finding files in $FROM
			fi
			cd "$FROM"
			cmd="bk _find"
			if [ X"$INCLUDE" != X ]
			then	cmd="$cmd | egrep '$INCLUDE'"
			fi
			if [ X"$EXCLUDE" != X ]
			then	cmd="$cmd | egrep -v '$EXCLUDE'"
			fi
			eval "$cmd" > ${TMP}import$$
			if [ X$QUIET = X ]; then echo OK; fi
		else	echo "" > ${TMP}import$$
		fi
	fi
	if [ $TYPE != patch ]
	then	if [ X$QUIET = X ]
		then	echo Checking to make sure there are no files already in
			echo "	$TO"
		fi
		cd "$TO"
		x=`bk _exists < ${TMP}import$$` && {
			echo "import: $x exists, entire import aborted"
			rm -f ${TMP}import$$
			exit 1
		}
		if [ $TYPE != SCCS ]
		then	bk _g2sccs < ${TMP}import$$ > ${TMP}sccs$$
			x=`bk _exists < ${TMP}sccs$$` && {
				echo "import: $x exists, entire import aborted"
				rm -f .x ${TMP}sccs$$ ${TMP}import$$
				exit 1
			}
			if [ X$QUIET = X ]; then echo OK; fi
		fi
	fi
	rm -f ${TMP}sccs$$
	cd "$TO"
	eval validate_$type \"$FROM\" \"$TO\"
	transfer_$type "$FROM" "$TO" "$TYPE"
	eval import_$type \"$FROM\" \"$TO\"
	import_finish "$TO"
}

msg() {
	if [ X$QUIET = X ]
	then	echo "$*"
	fi
}

getIncExc () {
	if [ "$INC" = YES ]
	then	echo End patterns with "." by itself or EOF
		echo $N "File name pattern to include>> " $NL
		while read x
		do	if [ X"$x" = X. ]; then break; fi
			if [ X"$x" = X ]; then break; fi
			if [ "X$INCLUDE" != X ]
			then	INCLUDE="$INCLUDE|$x"
			else	INCLUDE="$x"
			fi
			echo $N "File name pattern to include>> " $NL
		done
	fi
	if [ "$EX" = YES ]
	then	echo End patterns with "." by itself or EOF
		echo $N "File name pattern to exclude>> " $NL
		while read x
		do	if [ X"$x" = X. ]; then break; fi
			if [ X"$x" = X ]; then break; fi
			if [ "X$EXCLUDE" != X ]
			then	EXCLUDE="$EXCLUDE|$x"
			else	EXCLUDE="$x"
			fi
			echo $N "File name pattern to exclude>> " $NL
		done
	fi
}

gettype() {
	type=
	if [ "X$1" != X ]
	then	case "$1" in
		    plain)	type=text;;
		    patch)	type=patch;;
		    RCS|CVS)	type=RCS;;
		    SCCS)	type=SCCS;;
		esac
		if [ X$type != X ]
		then	TYPE=$type
			return
		fi
	fi
	cat <<EOF

BitKeeper can currently handle the following types of imports:

    plain	- these are regular files which are not under revision control
    patch	- a patch file generated by diff -Nur
    SCCS	- SCCS files which are not presently under BitKeeper
    RCS		- files controlled by RCS
    CVS		- files controlled by CVS

If the files you wish to import do not match any of these forms, you will
have to write your own conversion scripts.  See the rcs2sccs program for
an example.  If you write such a script, please consider contributing
it to the BitKeeper project.

EOF
	TRY=yes
	while [ $TRY = yes ]
	do	echo $N "Type of files to import? " $NL
		read type
		TRY=no
		case "$type" in
		    pa*) type=patch;;
		    pl*) type=text;;
		    R*|C*) type=RCS;;
		    S*) type=SCCS;;
		    *)	echo Invalid file type.
			echo Valid choices: plain patch RCS CVS SCCS
			TRY=yes
		    	;;
		esac
	done
	TYPE=$type
}


transfer_RCS() { transfer "$@"; }
transfer_SCCS() { transfer "$@"; }
transfer_text() { transfer "$@"; }
transfer_patch() { return; }

transfer() {
	FROM="$1"
	TO="$2"
	TYPE="$3"
	NFILES=`wc -l < ${TMP}import$$ | sed 's/ //g'`
	if [ $FORCE = NO ]
	then	echo
		echo $N "Would you like to edit the list of $NFILES files to be imported? " $NL
		read x
		echo ""
		case X"$x" in
		    Xy*)
			echo $N "Editor to use [$EDITOR] " $NL
			read editor
			echo
			if [ X$editor != X ]
			then	eval $editor ${TMP}import$$
			else	eval $EDITOR ${TMP}import$$
			fi
			if [ $? -ne 0 ]; then
			    echo ERROR: aborting...
			    exit 1
			fi
			NFILES=`wc -l < ${TMP}import$$ | sed 's/ //g'`
		esac
	fi
	if [ X$QUIET = X ]
	then	echo Transfering files
		echo "	from $FROM"
		echo "	to   $TO"
	fi
	cd "$FROM"
	bk sfio -omq < ${TMP}import$$ | (cd "$TO" && bk sfio -im $VERBOSE ) || exit 1
}

import_patch() {
	PATCH=$1
	PNAME=`basename $PATCH`
	SAVE=$USER
	USER=patch
	export USER
	Q=$QUIET
	cd "$2"

	if [ "X$COMMENTS" != X ]
	then	COMMENTOPT=-y"$COMMENTS"
	else	COMMENTOPT=-y"Import patch $PNAME"
	fi
	
	# This must be done after we cd to $2
	case `bk version` in
	*Basic*)	RENAMES=NO
			;;
	esac
	
	msg Patching...
	# XXX TODO For gfile with a sfile, patch -E option should translates
	#          delete event to "bk rm"
	(cd "$HERE" && cat "$PATCH") |
	    bk patch -g1 -f -p1 -ZsE \
		-z '=-PaTcH_BaCkUp!' --forcetime --lognames > ${TMP}plog$$ 2>&1
	if [ X$QUIET = X ]
	then	cat ${TMP}plog$$
	fi
	bk sfiles -x | grep '=-PaTcH_BaCkUp!$' | bk _unlink
	bk sfiles -x | grep '\.rej$' > ${TMP}rejects$$
	if [ $REJECTS = NO -a -s ${TMP}rejects$$ ]
	then	
		rm -f `cat ${TMP}rejects$$`
		bk unedit `bk sfiles -l`
		Done 1
	fi
	TRIES=0
	while [ -s ${TMP}rejects$$ -a $TRIES -lt 5 ]
	do 	echo "Patch rejects:"
		cat ${TMP}rejects$$
		echo 
		echo ===============================================
		echo Dropping you into a shell to clean the rejects.
		echo Please fix the rejects and then exit the shell 
		echo to continue the import
		echo ===============================================
		echo 
		sh -i
		bk sfiles -x | grep '\.rej$' > ${TMP}rejects$$
		TRIES=`expr $TRIES + 1`
	done
	test -s ${TMP}rejects$$ && {
		echo Giving up, too many tries to clean up.
		rm -f `cat ${TMP}rejects$$`
		bk unedit `bk sfiles -l`
		Done 1
	}
	grep '^Creating file ' ${TMP}plog$$ |
	    sed 's/Creating file //' > ${TMP}creates$$
	grep '^Removing file ' ${TMP}plog$$ |
	    sed 's/Removing file //' > ${TMP}deletes$$
	if [ $RENAMES = YES ]
	then	msg Checking for potential renames in `pwd` ...
		# Go look for renames
		if [ -s ${TMP}deletes$$ -a -s ${TMP}creates$$ ]
		then	(
			cat ${TMP}deletes$$
			echo ""
			cat ${TMP}creates$$
	    		) | bk renametool $Q
		fi
	fi
	msg Checking in new or modified files in `pwd` ...
	# Do the deletes automatically
	if [ -s ${TMP}deletes$$ -a ! -s ${TMP}creates$$ ]
	then	msg Removing `wc -l < ${TMP}deletes$$` files
		bk rm -f - < ${TMP}deletes$$
	fi
	# Do the creates automatically
	if [ ! -s ${TMP}deletes$$ -a -s ${TMP}creates$$ ]
	then	msg Creating `wc -l < ${TMP}creates$$` files
		bk new $Q -G "$COMMENTOPT" - < ${TMP}creates$$
	fi
	rm -f ${TMP}creates$$ ${TMP}deletes$$

	bk -cr ci $VERBOSE -G "$COMMENTOPT"

	bk sfiles -x | grep -v '^BitKeeper/' > ${TMP}extras$$
	if [ -s ${TMP}extras$$ ]
	then	echo =========================================================
		echo There were extra files, patch aborted, here is the list
		echo ===================== extra files =========================
		cat ${TMP}extras$$
		echo =========================================================
		cat <<EOF

For some reason, possible an error reported above, one or more files did not
get checked in.  You need to figure out why this happened and remove the 
cause.  

To get back to where you were before, just clone this repository to someplace
else and try again, the clone will throw away any partial work.

EOF
		Done 1
    	fi

	bk sfiles -c > ${TMP}extras$$
	if [ -s ${TMP}extras$$ ]
	then	echo ===========================================================
		echo There are modified files, patch aborted, here is the list
		echo ===================== modified files ======================
		cat ${TMP}extras$$
		echo ===========================================================
		cat <<EOF

For some reason, probably an error reported above, one or more files did not
get checked in.  If the problem is one caused by your patch (an example is
a patch which is invalid, for instance, a patch which contains nulls), then
you need to fix the patch and try again.

To get back to where you were before, just clone this repository to someplace
else and try again, the clone will throw away any partial work.

EOF
		Done 1
    	fi

	if [ $COMMIT = NO ]
	then	Done 0
	fi
	USER=$SAVE
	# Ask about logging before commit, commit reads stdin.
	bk _loggingask
	if [ $? -eq 1 ]
	then 	Done 1
	fi
	msg Creating changeset for $PNAME in `pwd` ...
	bk sfiles -C | bk commit $QUIET $SYMBOL -a -y"`basename $PNAME`" -
	msg Done.
	Done 0
}

import_text () {
	Q=$QUIET

	cd "$2"
	if [ X$QUIET = X ]; then msg Checking in plain text files...; fi
	bk ci -1i $VERBOSE - < ${TMP}import$$ || exit 1
}

import_RCS () {
	cd "$2"
	if [ $FIX_ATTIC = YES ]
	then	HERE=`pwd`
		grep Attic/ ${TMP}import$$ | while read x
		do	d=`dirname $x`
			test -d $d || continue	# done already
			cd $d || exit 1
			# If there is a name conflict, do NOT use the Attic file
			find . -name '*,v' -print | while read i
			do	if [ -e "../$i" ] 
				then	rm "$i"
				else	mv "$i" ..
				fi
			done
			cd ..
			rmdir Attic || { touch ${TMP}failed$$; exit 1; }
			cd $HERE
		done
		test -f ${TMP}failed$$ && {
			echo Attic processing failed, aborting.
			exit 1
		}
		mv ${TMP}import$$ ${TMP}Attic$$
		sed 's|Attic/||' < ${TMP}Attic$$ | sort -u > ${TMP}import$$
		rm ${TMP}Attic$$
	fi
	if [ $TYPE = RCS ]
	then	msg Moving RCS files out of RCS directories
		HERE=`pwd`
		find . -type d | grep 'RCS$' | while read x
		do	cd $x
			mv *,v ..
			cd ..
			rmdir RCS
			cd $HERE
		done
		mv ${TMP}import$$ ${TMP}rcs$$
		sed 's!RCS/!!' < ${TMP}rcs$$ > ${TMP}import$$
		rm ${TMP}rcs$$
	fi
	msg Converting RCS files.
	msg WARNING: Branches will be discarded.
	if [ $PARALLEL -eq 1 ]
	then	bk rcs2sccs $UNDOS $CUTOFF $VERIFY $QUIET - < ${TMP}import$$ ||
		    exit 1
		bk _unlink < ${TMP}import$$
		return
	fi
	LINES=`wc -l < ${TMP}import$$`
	LINES=`expr $LINES / $PARALLEL`
	split -$LINES ${TMP}import$$ ${TMP}split$$
	for i in ${TMP}split$$*
	do	bk rcs2sccs $UNDOS $CUTOFF $VERIFY $QUIET -q - < $i &
	done
	wait
	bk _unlink < ${TMP}import$$
}

import_SCCS () {
	cd "$2"
	msg Converting SCCS files...
	bk sccs2bk $VERIFY -c`bk prs -hr+ -nd:ROOTKEY: ChangeSet` - < ${TMP}import$$ ||
	    exit 1
	rm -f ${TMP}cmp$$
}

import_finish () {
	cd "$1"
	if [ X$QUIET = X ]; then echo ""; fi
	if [ X$QUIET = X ]; then echo Final error checks...; fi
	bk sfiles | bk admin -hhhq - > ${TMP}admin$$
	if [ -s ${TMP}admin$$ ]
	then	echo Import failed because
		cat ${TMP}admin$$
		exit 1
	fi
	if [ X$QUIET = X ]; then echo OK; fi
	
	rm -f ${TMP}import$$ ${TMP}admin$$
	bk idcache -q
	# So it doesn't run consistency check.
	touch BitKeeper/etc/SCCS/x.marked
	if [ $COMMIT != NO ]
	then	
		if [ X$QUIET = X ]
		then echo "Creating initial changeset (should be +$NFILES)"
		fi
		bk commit $QUIET $SYMBOL -y'Import changeset'
	fi
	bk -r check -ac
}

validate_SCCS () {
	FROM="$1"
	TO="$2"
	cd "$FROM"
	grep 'SCCS/s\.' ${TMP}import$$ > ${TMP}sccs$$
	grep -v 'SCCS/s\.' ${TMP}import$$ > ${TMP}notsccs$$
	if [ -s ${TMP}sccs$$ -a -s ${TMP}notsccs$$ ]
	then	NOT=`wc -l < ${TMP}notsccs$$ | sed 's/ //g'`
		echo
		echo Skipping $NOT non-SCCS files
		echo $N "Do you want to see this list of skipped files? [No] " $NL
		read x
		case "$x" in
		y*)	sed 's/^/	/' < ${TMP}notsccs$$ | more ;;
		esac
		mv ${TMP}sccs$$ ${TMP}import$$
	fi
	rm -f ${TMP}notsccs$$ ${TMP}sccs$$
	echo Looking for BitKeeper files, please wait...
	grep 'SCCS/s\.' ${TMP}import$$ | prs -hr -nd':PN: :TYPE:' - | grep ' BitKeeper' > ${TMP}reparent$$
	if [ -s ${TMP}reparent$$ ]
	then	cat <<EOF

You are trying to import BitKeeper files into a BitKeeper package.
We can do this, but it means that you are going to "reparent" these
files under a new ChangeSet file.  In general, that's not a good idea,
because you will lose all the old ChangeSet history in the copied files.
We can do it, but don't do it unless you know what you are doing.

The following files are marked as BitKeeper files:
EOF
		sed 's/ BitKeeper$//' < ${TMP}reparent$$ | sed 's/^/	/'
		echo ""
		echo $N "Reparent the BitKeeper files? [No] " $NL
		read x
		case "$x" in
		y*)	;;
		*)	rm -f ${TMP}sccs$$ ${TMP}import$$ ${TMP}reparent$$
			exit 1
		esac
		echo $N "Are you sure? [No] " $NL
		read x
		case "$x" in
		y*)	;;
		*)	rm -f ${TMP}sccs$$ ${TMP}import$$
			exit 1
		esac
		echo OK
	fi
	rm -f ${TMP}reparent$$
}

validate_RCS () {
	grep ',v$' ${TMP}import$$ >${TMP}rcs$$
	# Filter out CVS repository metadata here.
	grep -v ',v$' ${TMP}import$$ | egrep -v 'CVS|#cvs' >${TMP}notrcs$$
	if [ -s ${TMP}rcs$$ -a -s ${TMP}notrcs$$ ]
	then	NOT=`wc -l < ${TMP}notrcs$$ | sed 's/ //g'`
		echo
		echo Skipping $NOT non-RCS files
		echo $N "Do you want to see this list of files? [No] " $NL
		read x
		case "$x" in
		y*)	sed 's/^/	/' < ${TMP}notrcs$$ | more ;;
		esac
	fi
	mv ${TMP}rcs$$ ${TMP}import$$
	rm -f ${TMP}notrcs$$
}

validate_text () {
	FROM="$1"
	TO="$2"
	cd "$FROM"
	egrep 'SCCS/s\.|,v$' ${TMP}import$$ > ${TMP}nottext$$
	egrep -v 'SCCS/s\.|,v$' ${TMP}import$$ > ${TMP}text$$
	if [ -s ${TMP}text$$ -a -s ${TMP}nottext$$ ]
	then	NOT=`wc -l < ${TMP}nottext$$ | sed 's/ //g'`
		echo
		echo Skipping $NOT non-text files
		echo $N "Do you want to see this list of files? [No] " $NL
		read x
		case "$x" in
		y*)	sed 's/^/	/' < ${TMP}nottext$$ | more ;;
		esac
		mv ${TMP}text$$ ${TMP}import$$
		rm -f ${TMP}nottext$$
	fi
	rm -f ${TMP}nottext$$ ${TMP}text$$
}

# Make sure there are no locked/extra files
validate_patch() {
	cd "$2"
	msg Make sure there are no locked files in `pwd` ...
	bk sfiles -l | grep -v BitKeeper/ > ${TMP}locked$$
	if [ -s ${TMP}locked$$ ]
	then	echo Not patching because of locked files:
		cat ${TMP}locked$$
		Done 1
    	fi
	msg Make sure there are no extra files in `pwd` ...
	bk sfiles -x | grep -v BitKeeper/ > ${TMP}extras$$
	if [ -s ${TMP}extras$$ ]
	then	echo Not patching because of extra files:
		cat ${TMP}extras$$
		Done 1
    	fi
	rm -f ${TMP}locked$$ ${TMP}extras$$
}

Done() {
	for i in rejects plog extras locked import sccs
	do	rm -f ${TMP}${i}$$
	done
	exit $1
}

init() {
	__platformInit;
	if [ '-n foo' = "`echo -n foo`" ]
	then    NL='\c'
	        N=
	else    NL=
		N=-n
	fi
	if [ X$EDITOR = X ]
	then	EDITOR=vi
	fi
}

init
import "$@"
exit 0
