#!/bin/bash
# Can be changed via config and keys
LOGDIR=/var/log/notamocks/$(date +%m.%d.%H.%M)
PARALLEL=3 
TIMEOUT=0.2
MAXITER=10

# Can be changed via keys
DIRS=$(find ./ -maxdepth 1 -mindepth 1 -type d)
CHAIN='no'

# Can be changed via environment
SUCCESLOG=${SUCCESLOG:-_SUCCES.log}
FAILLOG=${FAILLOG:-_FAILURE.log}
NOTAMOCKSLOG=${NOTAMOCKSLOG:-_NOTAMOCKS.log}
CHAINLOG=${CHAINLOG:-_CHAIN_LOG}
REPOLOG=${REPOLOG:-_REPO_LOG}
CHAINREP=${CHAINREP:-"/tmp/notamocks_rep-$$"}

# internal variables
declare -A procs
RPIDS=''
aaa='==='
REWRITE="\e[25D\e[1A\e[K"
REGEXP='.'
ADDREP=''
SEPARATOR="###################################################################"

NOTAMOCKLIB="/usr/share/notamock/libnotamock"
[ -f './libnotamock' ] && NOTAMOCKLIB=./libnotamock
source "$NOTAMOCKLIB"

CFG=/etc/notamock.cfg
# special config for project
[ -f './notamock.cfg' ] && CFG=$(realpath ./notamock.cfg)

source "$CFG"

if [ -d "$CFGD" ] ; then
	for a in $(ls -1 ${CFGD}/. |sort ) ; do
		source ${CFGD}/$a
	done
fi

HLP(){
echo "$0 - "
echo "Usage:" 
echo "cd /dir/with/projects  ; $0 <$(basename $0) pars> <VAR=VALUE for notamock>"
echo "Parameters:
	-h | --help         -  this help
	-d | --projectdirs  -  dirs with projects, default dirs in ./
	-l | --logdir       -  dir for notamock logs, default:  /var/log/notamocks/<month.day.hour.min>/
	-t | --timeout      -  timout before run next notamock process in sec, default $TIMEOUT
	-p | --parallel     -  a max number of notamock processes, default $PARALLEL
	-s | --skip-built   -  do not run build process if project dir contain *.rpm files
	-f | --skip-fallen  -  do not run build process if project dir contain project*.buildlog files
	-R | --regexp       -  filter in a grep format, to select projects from list (default REGEXP='.')
	-n | --chain        -  chain build
	-m | --maxiter      -  maximum number of iterations for chain build
	"
echo "Keys for notamock:
	all keys and parameters except those listed will be sent to notamock at each use"
echo "Variables:
	all notamock variables specified from notamock config file can be changed from the cmdline of $(basename $0) 
	in KEY=VALUE format"
exit
}

while [ -n "$1" ] ; do
    case "${1}" in  
    "-h" | "--help") HLP ;;
    "-d" | "--projectdirs" ) shift ; DIRS="$1" ;;
    "-l" | "--logdir") shift ; LOGDIR="$1" ;;
    "-t" | "--timeout") shift ; TIMEOUT="$1" ;;
    "-p" | "--parallel") shift ; PARALLEL="$1" ;;
    "-R" | "--regexp") shift ; REGEXP="$1" ;;
    "-s" | "--skip-built") SKIP_BUILT=yes ;;
    "-f" | "--skip-fallen") SKIP_FALLEN=yes ;;
    "-n" | "--chain" ) CHAIN=yes ;;
    "-m" | "maxiter" ) shift ; MAXITER="$1" ;;
    *) notamock_vars="$notamock_vars $1";;
	esac
shift
done

# animation helper func
slash() {
case $1 in
	'===' ) echo '+==' ;;
	'+==' ) echo '=+=' ;;
	'=+=' ) echo '==+' ;;
	'==+' ) echo '===' ;;
esac
}

# run notamock for project
run_notamock() {
	pushd "$1" >/dev/null
		if [ "$SKIP_BUILT" ] ; then
			if find ./RPMS/ -maxdepth 3  -name '*.rpm' 2>/dev/null |egrep -q '\.rpm$' ; then
				echo "+++> skip: $(basename $PROJECT) - already built" |tee -a ${LOGDIR}/$NOTAMOCKSLOG
				exit
			fi
		fi
		if [ "$SKIP_FALLEN" ] ; then

			if find ./ -maxdepth 1  -name '*.buildlog'  |grep -q $(basename $PROJECT) ; then
				echo "---> skip: $(basename $PROJECT) - has bin fallen" |tee -a ${LOGDIR}/$NOTAMOCKSLOG
				exit
			fi
		fi
		date > $LOGDIR/$(basename $PROJECT).log
		[ "$CHAIN" == 'yes' ] && \
		ADDREP="CHROOT_PM_OPTS=$CHROOT_PM_OPTS  --nogpgcheck ${PM_addrep_opt} notamocks,file://$CHAINREP"
		echo "notamock -v $ADDREP $notamock_vars" >> $LOGDIR/$(basename $PROJECT).log
		notamock -v $ADDREP $notamock_vars >> $LOGDIR/$(basename $PROJECT).log 2>&1
		ecode="$?"
		if [ "$ecode" -eq 0 ] ; then
			echo $(basename $1) >> ${LOGDIR}/$SUCCESLOG
		else
			echo "$(basename $1): $ecode" >> ${LOGDIR}/$FAILLOG
		fi 
	popd >/dev/null
}

# check that one of pids is alive
check_pids(){
	for a in $@ ; do
		[ -e "$a" ] && checked="$checked $a"
	done
	echo "$checked"
}

# wait pids animation
waitall() {
    while [ "$(echo $RPIDS |wc -w)" -ne 0 ] ; do
	RPIDS=$(check_pids $RPIDS)
	aaa=$(slash $aaa)
	echo -e "${REWRITE}${aaa}> waiting:  $(for fproc in $RPIDS ; do
		echo -n "$(basename ${procs[$fproc]}):$(basename $fproc) "
	done)"
	sleep "$TIMEOUT"
    done
}

# update repository for chain build
mkrep() {
	while read rpm ; do
		[ "${rpm##*.}" = "rpm" ] && cp $rpm ${CHAINREP}/
	done
	$CREATE_REPO ${CHAINREP} >> ${LOGDIR}/$REPOLOG 2>&1
}

# create repo for chain build
initrep(){
	mkdir -p $CHAINREP
	$CREATE_REPO $CHAINREP >> ${LOGDIR}/$REPOLOG 2>&1
	sleep 5
}

mkdir -p $LOGDIR
LOGDIR=$(realpath $LOGDIR)
:> ${LOGDIR}/$SUCCESLOG
:> ${LOGDIR}/$FAILLOG
:> ${LOGDIR}/$NOTAMOCKSLOG
:> ${LOGDIR}/$CHAINLOG
:> ${LOGDIR}/$REPOLOG

ftrap() {
    echo "waiting bg processes: $RPIDS"
    waitall
    echo -e "${REWRITE}Warning: aborted!"
    rm -rf  "$CHAINREP"
    exit
}

echo $notamock_vars >> ${LOGDIR}/$NOTAMOCKSLOG
trap 'ftrap' 1 2 3 15

[ "$CHAIN" == 'yes' ] && initrep
for a in $(seq $MAXITER) ; do
	for PROJECT in $DIRS; do
		echo $PROJECT |grep -q $REGEXP || continue
		PROJECT=$(realpath $PROJECT)
		[ "$PROJECT" == "$LOGDIR" ] && continue
		while [ "$(echo $RPIDS |wc -w)" -gt "$PARALLEL" ] ; do
			sleep $TIMEOUT
			RPIDS=$(check_pids $RPIDS)
		done
		( run_notamock "$PROJECT" ) &
		proc="/proc/$!"
		echo ${PROJECT}:$proc >> ${LOGDIR}/$NOTAMOCKSLOG
		RPIDS="$RPIDS $proc"
		procs[$proc]="$(basename $PROJECT)"
		echo -e "===> processing: ${procs[$proc]}:$(basename $proc)"
		sleep "$TIMEOUT"
	done

	# line to be rewrited
	echo ''
	waitall
	echo -e "${REWRITE}done."

	[ "$CHAIN" != 'yes' ] && break
	for PROJECT in $DIRS; do
		if  find ${PROJECT}/RPMS/ -type f -name '*.rpm' 2>/dev/null |egrep -q '\.rpm$' ; then 
			sed  's/ /\n/g' ${LOGDIR}/$CHAINLOG	 |grep -qx "$(basename $PROJECT)" || \
			echo -n "$(basename $PROJECT) " >> ${LOGDIR}/$CHAINLOG
		fi
	done
	echo >> ${LOGDIR}/$CHAINLOG
	[ -z "$(cat ${LOGDIR}/$CHAINLOG |tail -n1)" ] && break
	find $DIRS -type f -name '*.rpm' | mkrep
	SKIP_BUILT='yes'
	echo $SEPARATOR >> ${LOGDIR}/$SUCCESLOG
	echo $SEPARATOR >> ${LOGDIR}/$FAILLOG
	echo $SEPARATOR >> ${LOGDIR}/$NOTAMOCKSLOG
	echo $SEPARATOR >> ${LOGDIR}/$REPOLOG
done
 
[ -d "$CHAINREP" ] && rm -rf  "$CHAINREP"
