#!/usr/bin/env bash
#
# UBM module creator 
#

HELP_MKUBM(){
    echo "Usage: ${0#*/} <list of sources> -o out.$EXT"
    echo "Examples:"
    echo "${0#*/} ./dir 			-make dir.ubm from dir"
    echo "${0#*/} 1.$EXT 2.$EXT -o 3.$EXT	-collect 1.$EXT and 2.$EXT to container 3.$EXT"
    echo "${0#*/} * -o ./big.$EXT		-collect all dirs and squashfs modules from current dir to big.$EXT" 
    echo
    echo "Параметры (ключи):"
    echo "  -o / --out-file - указывает название выходного файла (если указать без расширения .$EXT на выходе будет каталог)."
    echo "  -w - сохранить тени AUFS"
    echo "  -l / --local - сборка на месте, без использования aufs."
    echo "  -f / --fast - быстрая компрессия (размер .$EXT больше, но создается быстрее)."
#    echo "  --mkilst  add files list to simple (non container) module"
    echo "  --save-duplicates  при сборке контейнеров сохранять одноименные файлы из разных источников если они отличаются, "
    echo "                     при распаковке файлы будут возвращены на место"
    echo "  --mksqfs / параметры для mksquashfs, компрессия размер блока и проч.(Внимание параметр должен быть последним)"
#    echo "  --spec ./file  -  Добавить файл с информацией. Только для атомарных модулей"
#    echo "  --deps aaa,bbb,ccc - Добавить список зависимостей.  Только для атомарных модулей"
    echo ""
    echo "Алиасы (сокращения):"
    echo " -d | -D - Только каталоги"
    echo "	${0#*/} -d dir ---> ${0#*/}" '$(find dir -maxdepth 1 -mindepth 1 -type d ) -o dir.$EXT'
    echo " -m | -M - Только модули"
    echo "	${0#*/} -m dir ---> ${0#*/}" '$(find dir -maxdepth 1 -mindepth 1 -type f ) -o dir.$EXT'
    exit 1
}

D(){
    sourcelist="$(find "$1" -maxdepth 1 -mindepth 1 -type d |sort)"
    sourcelist=$(echo $sourcelist |sed 's/\ /#/g')
    [ "$sourcelist" ] || exitmsg "no directory in '$2'" 1
    ondir=
    [ "${userout}_" = "_" ] && [ ! "`echo "$arglist" |grep "\-o "`" ] && userout="./$(basename "$1").$EXT"
}
M(){
    sourcelist="$(find "$1" -maxdepth 1 -mindepth 1 -type f |grep -E ".ubm$|.ubfs$|.pfs$|.xzm$|.sfs$|.squashfs$|.$EXT$" |sort)"
    sourcelist=$(echo $sourcelist |sed 's/\ /#/g')
    [ "$sourcelist" ] || exitmsg "no modules in '$2'" 1
    onmod=
    [ "${userout}_" = "_" ] && [ ! "`echo "$arglist" |grep "\-o "`" ] && userout="./$(basename "$1").$EXT"
}

#save_duplicates() {
#	echo "save_duplicates enabled"
#	for i in $bundles ; do
#    #uniqfiles=$(diff -rq $i $n |grep -v "[[:alnum:]]: [[:alnum:]]" | sed "s#^.*$i##" |cut -d" " -f1)
#    uniqfiles=$(LC_MESSAGES=en diff --no-dereference -rq  $i $n |grep "Files.*differ" | sed "s#^.*$i##" |cut -d" " -f1)
#	if [[ -n "$uniqfiles" ]] ; then
#		dpath=$(pwd)
#		dest_dir="$(realpath "$n")${UBMDIR}/mount/$(basename "${i%.$EXT}")/"
#		mkdir -p ${dest_dir}/unique
#		for file in $uniqfiles ; do 
#			cd ${i}
#			cp -fr  --parents ".$file" ${dest_dir}/unique/ && echo "$file -- saved as unique for $(basename $i) submodule" 
#		done
#		cd $dpath
#	fi
#	done
#}


check_kernel(){
    check_ubm >/dev/null 2>&1
    exitmsg "Kernel is not support squashfs/aufs. Work only 'mkubm -l'" $?
}

#mkinfo() {
#	local NAME PACKVER MODVER AUTHOR ALIAS
#	info=$1/${UBMDIR}/INFO
#	mkdir -p $(dirname $info)
#	[ -f "$info" ] && source $info
#	> "$info"
#	for a in NAME PACKVER MODVER MODREV AUTHOR ALIAS; do
#		eval echo -n \""Please enter $a (current: \$$a): "\"
#		read newstr
#		if ! [ -z "$newstr" ] ; then
#			eval $a="$newstr"
#		fi
#		eval echo "$a=\$$a" >> $info
#		unset newstr 
#	done
#}

    [[ -f $(dirname $0)/ubm ]] && . $(dirname $0)/ubm || . $(which ubm) || exit 1    


# parsing for "--mksqfs" arg
    if  echo "$@" |grep -q "\-*mksqfs .*" ; then
	MKSQFS_ARGS=" $(echo "$@" |sed 's/^.*\-*mksqfs//')"
    fi

#get opts
    sourcelist=""
    inplace=""
    sep=''
    for arg in "$@"; do
	[ "$arg" = '-mksqfs' -o "$arg" = '--mksqfs' ] && break
	case "$arg" in
	    "-o" | "--out-file") 	onuserout="on" ;;
#	    "--mkinfo")			mkinfo='yes' ;;
	    "-d" | "-D") 		ondir="on" ;;
	    "-m" | "-M") 		onmod="on" ;;
	    "-h" | "--help")  		HELP_MKUBM; exit 1 ;;
	    "-q" | "--quiet") 		devnull='>/dev/null' ;;
	    "-t" | "--trim") 		TRIM="yes" ;;
	    "-no-progress" | "--no-progress") 	noprogress="-no-progress" ;;
	    "-processors" | "--processors") 	numproc="on" ;;
#	    "-save-duplicates" | "--save-duplicates") save_dups=on ;;
	    "-w" | "--wh") 	WH="yes" ;;
	    "-l" | "--local") 	inplace=yes ;;
#	    "--mklist") 	make_list=yes ;;
#	    "--spec") 		make_list=yes ; spec=yes ;;
#	    "--depends") 	make_list=yes ; deps=yes ;; 
	    "-f" | "--fast") [[ -n ${compression_fast} ]] && compression="${compression_fast}" ;;
	    "-"*[A-Za-z]*) echo "$(basename "$0"): invalid option -- '$(echo ${arg} | tr -d '-')'" >&2; HELP_MKUBM; exit 1 ;;
	    *)	if [ "${usepkname}" = "on" ]; then packname="${arg}"
	        elif [ "${ondir}" = "on" ]; then D "${arg}"
	        elif [ "${onmod}" = "on" ]; then M "${arg}"
	        elif [ "${onuserout}" = "on" ]; then userout="${arg}"
#	        elif [ "${spec}" = "yes" ]; then SPEC="${arg}"
#	        elif [ "${deps}" = "yes" ]; then DEPENDS="${arg}"
	        elif [ "${numproc}" = "on" ]; then useproc="-processors ${arg}"
		else 
		    sourcelist="${sourcelist}${sep}"${arg}""
	            sep='#' 
		fi
	        onuserout="off"; usepkname="off"; usindlib="off"; numproc="off"; deps="off"; spec="off" 
	    ;;
	esac
    done

    [ "$sourcelist" ] || HELP_MKUBM 

#echo "Sources: $sourcelist"
    [ "$inplace" = "yes" -a  "$WH"  != "yes" ] && wh='-wildcards -e "... /.wh.*"'

    allow_only_root

    [ "$inplace" ] || check_kernel
    
    [[ -z ${MKSQFS_ARGS} ]] || compression+=" ${MKSQFS_ARGS}"

    if [ "${userout}_" = "_" ] ; then 
	first="$(basename "$(echo "$sourcelist" | awk -F# '{print $1}')")"  	#"
	userout="$(echo ${first%.$EXT}).$EXT" 
    fi
#1 dir, in place mode
    if [ -d $sourcelist 2>/dev/null -a "$inplace" = "yes" ]; then
	eval echo "==== In place mode ====" $devnull
	[ "$wh" ] ||  eval  echo "=== save aufs whiteout \(.wh*\) ===" $devnull
	[ ! "$(ls -a $sourcelist)" ] && exitmsg "directory '$sourcelist' empty" 1
#	[ $make_list ] && mklist source_root=$sourcelist dest_root=$sourcelist pack_name=${userout%.$EXT} spec_file="$SPEC" depends="$DEPENDS" 
	[ $TRIM ] && trim $sourcelist
	if echo ${userout} | grep -q "^.*\.$EXT$" ; then 
	    mksqmod $sourcelist "${userout}" && exit 0 
	    exitmsg "mkubm error" 2
	else
	    echo "Please wait..."
	    rm -rdf ${userout}/* 2>/dev/null
#	    rmdir ${userout} 2>/dev/null
	    [ -d "${userout}" ] && exitmsg "Output diectory already exist" 6
	    mkdir -p "$(dirname ${userout})"
	    cp -fax $sourcelist "${userout}" && exit 0
	    exitmsg "copy files error" 2
	fi
	exit
    fi

#test sources, source must be dir or squashfs module
    echo $sourcelist |sed 's/#/\n/g' | while read source; do
	[ -d "$source" ] && continue
	[ "$(fs_type "$source")" = "squashfs" ] && continue
	exitmsg "Type of source \"$source\" is not correct" 2
    done	

    [ -d "$sourcelist" ] && { ls "$sourcelist" |grep -q . 2>/dev/null || exitmsg "\"`echo $sourcelist`\" is empty" 2 ; }

#make root aufs
    n="$(make_aufs || exitmsg "make_aufs error" 2)"
    nn="$(echo "$n" | sed -n 's/^.*\([0-9]\)$/\1/p')"
    [ -d "$n" ] || exitmsg "error mounting aufs" 3

#add sources as aufs layers

    echo $sourcelist |sed 's/#/\n/g' |while read i ; do
	eval add_layer "$nn" "$i" "$devnull" || exitmsg "can't insert layer to aufs $nn" 5
    done 

#if ! echo $sourcelist |grep '#' ;then
  # if source is only one - submodule name is $userout with no prefix (ubm,pfs,xzm,etc)
#  pack_name=$(echo ${userout%.$EXT} |sed -e 's/_comma_/,/g' -e 's/_equal_/=/g' -e 's/_asterisk_/\*/g' -e 's/_hash_/\#/g' )
#  [ $make_list ] && mklist source_root="$i" dest_root="$n" pack_name="$pack_name" spec_file="$SPEC" depends="$DEPENDS" 
#else	
#  bundles=$(find $(echo $n |sed 's#aufs#bundles#') -maxdepth 1 -mindepth 1 -type d )
  #mklist for modules, submodule name is basename source with no prefix
#  for i in $bundles ;do
#	  name="$(basename "${i%.$EXT}" |sed -e 's/_comma_/,/g' -e 's/_equal_/=/g' -e 's/_asterisk_/\*/g' -e 's/_hash_/\#/g')" 
#	  mklist source_root="$i" dest_root="$n" pack_name="$name"
#  done
#  [ $save_dups ] && save_duplicates
#fi

[ $TRIM ] && trim $n
if [ $WH ] ; then
	echo ".wh..*" > /tmp/mkubm_excludes
	find $n |sed "s:$n/:/:" > /tmp/allfiles-wh
	mount -t aufs -o remount,shwh $n
	for line in $(find $n  |sed -re 's:/.wh.|/.wh..wh.:/:' -e "s:$n/:/:"  |sort |uniq -d) ; do
		grep $line /tmp/allfiles-wh |sed -re 's:^(.*/)(.*$):\1.wh.\*\2:' -e 's:^/::' >> /tmp/mkubm_excludes
	done
	rm /tmp/allfiles-wh
fi



if echo "${userout}" | grep -q "^.*\.$EXT$" ; then
#	if [ $mkinfo ] ;then 
#		mkinfo "$n"
#	else
#		rm -f $n/${UBMDIR}/INFO
#	fi 
	mksqmod "${n}" "${userout}" noexit
else
	echo "Please wait..."
	rmdir ${userout} 2>/dev/null
	if [ -d "${userout}" ] ; then 
		delete_aufs "$nn" 
		exitmsg "Output diectory already exist" 6
	fi
	mkdir -p "$(dirname ${userout})"
	cp -fax "${n}" "${userout}"
fi
rm -rf $SYSMNT/lost_wh$N 2>/dev/null
exitmsg "mksqmod error" $?  noexit
delete_aufs "$nn"
exitmsg "delete_aufs error" $?
