#!/bin/sh
# sbsvnget - sandbox-aware svn checkout/update
# Copyright (C) 2012 - 2018 FARGOS Development, LLC
# $Id$
# Depends upon getsbattr
originDir=`dirname "${0}"`
thisDir=`pwd`

# get sandbox-specific settings
sb_svnServer=`${originDir}/getsbattr -null svnServer`
sb_svnRoot=`${originDir}/getsbattr -null svnRoot`

# If sandbox-specific not defined, fill in from environment
svnServer="${sb_svnServer:-${SVN_HOST}}"
svnRoot="${sb_svnRoot:-${SVN_PATH}}"

relDir=`${originDir}/sbrel`
relRoot=`${originDir}/sbrel -showroot`
dirList=""
flags=""
forceFlag=""
revisionFlags=""
checkoutCmd="co --depth empty"
checkoutDir="co"
updateCmd="update"

while test $# -gt 0
do
	case "${1}" in
	-h | -help | --help)
		printf "usage: %s [--blame] [--server modeAndhostName] [--path pathToRepository] [--force] [--revision revId] dirOrFileName ...\n" "${0}" >&2
		exit 1
		;;
	--blame)
		checkoutCmd="blame"
		checkoutDir="blame"
		updateCmd="blame"
		;;
	-server | --server)
		svnServer="${2}"
		shift
		;;
	-path | --path)
		svnRoot="${2}"
		shift
		;;
	-r | --revision | --depth | --username | --password | --config-dir | --config-option) # two-element argument
		flags="${flags}${flags:+ }${1} ${2}"
		shift
		;;
	-force | --force)
		forceFlag="--force"
		;;
	-*) # single-element flag
		flags="${flags}${flags:+ }${1}"
		;;
	*)
		dirList="${dirList}${dirList:+ }${1}"
		;;
	esac
	shift
done

localKind=`svn info ${relRoot} 2>/dev/null | awk '/Node Kind:/ { print $3; }'`
if test -z ${localKind}
then
	overlayDirName=`basename ${relRoot}`
	# Expect overlayDirName to be "src" in a sandbox
	cd `dirname ${relRoot}`
	echo Initialize ${relRoot} for use with Subversion 
	parentURL="${svnServer}${svnRoot}"
	svn co --depth empty ${flags} ${parentURL} ${overlayDirName}
fi

for entryDir in ${dirList}
do
	# Always start from original context
	fullPath="${relDir}/${entryDir}"
	parentPath=`dirname ${fullPath}`
	parentDir=`dirname ${relRoot}${fullPath}`	# is absolute path
	entry=`basename ${fullPath}`			# should be last component of entryDir
	# echo fullPath $fullPath parentDir $parentDir parentPath $parentPath entry $entry
	# Query repository server for info about target
	kind=`svn info ${flags} ${svnServer}${svnRoot}${fullPath} | awk '/Node Kind:/ { print $3; }'`
	if test -z "${kind}"
	then
		printf "%s: invalid path %s\n" `basename $0` "${svnServer}${svnRoot}${fullPath}" >&2
		exit 1
	fi
	# Start from top of sandbox
	cd ${relRoot}
	pathTraverse=`echo $parentPath | sed -e 's:/: :g'`
	pathToHere=""
	for dir in ${pathTraverse}
	do
		pathToHere="${pathToHere}${pathToHere:+/}${dir}"
		localKind=`svn info ${dir} 2>/dev/null | awk '/Node Kind:/ { print $3; }'`
		case "X${localKind}" in
		Xdirectory) # parent already in subversion
			# echo Directory ${pathToHere} already under control of Subversion. >&2
			if test ! -d ${dir}
			then
				echo Attempt to restore missing directory ${pathToHere}
				svn update --depth empty ${forceFlag} ${flags} ${dir} 
			fi
			;;
		Xfile) # file already under control
			echo File ${pathToHere} already under control of Subversion. >&2
			# This would be VERY unexpected!
			;;
		X) # not in Subversion
			# echo Create intermediate directory svn update --depth empty ${dir} 
			svn update --depth empty ${forceFlag} ${flags} ${dir} 
			;;
		esac
		# echo descend to ${dir}
		cd ${dir} # descend
	done
	# echo now in `pwd` looking at ${entry}
	if test -e "${entry}"	# local entry exists
	then
		# echo Local ${entry} exists...
		localKind=`svn info ${entry} 2>/dev/null | awk '/Node Kind:/ { print $3; }'`
		# echo Local kind X${localKind}X
		case "X${localKind}" in
		Xdirectory)
			# echo UPDATE svn update infinity ${entry}
			svn update --set-depth infinity ${flags} ${entry}
			;;
		Xfile) # file already under control
			echo File ${fullPath} already under control of Subversion. >&2
			;;
		X)	# not yet under control
			# echo Entry ${fullPath} not yet under control by subversion
			svn update ${forceFlag} ${flags} ${entry}
			;;
		*)
			printf "%s: Unsupported kind: %s\n" $0 "${kind}" >&2
			exit 1
			;;
		esac
	else # No local entry exists...
		localParentKind=`svn info ${flags} ${parentDir} 2>/dev/null | awk '/Node Kind:/ { print $3; }'`
		case X${localParentKind} in
		Xdirectory) # Normal case, parent already under control
			# echo Parent in SVN, do svn update ${entry}
			svn update ${forceFlag} ${entry}
			;;
		X)	# Special case, parent not under Subversion (root)
			# echo Parent not in SVN...should not really happen..
			if test "${kind}" = "directory"
			then
				svn ${checkoutDir} ${flags} ${svnServer}${svnRoot}${fullPath} 
			else
				printf "Subversion does not permit individual files; entire parent directory to be checked out\n"
				parentDirPath=`pwd` # should be $thisDir
				overlayDirName=`basename ${parentDirPath}`
				# Expect overlayDirName to be "src" in a sandbox
				cd .. # go up to parent directory
				parentURL=`dirname ${svnServer}${svnRoot}${fullPath}`
				svn ${checkoutCmd} ${flags} ${parentURL} ${overlayDirName}
				# back to original directory
				cd ${overlayDirName}
				svn update ${flags} ${entry}
			fi
			;;
		*)
			printf "%s: Unsupported kind: %s\n" "${0}" "${kind}" >&2
			exit 1
			;;
		esac
	fi
done
