#!/bin/bash
#######################################
# Inspiration from bug #34921
# Thanks to Paul Varner

# Distributed under the GPL v2
# Written by John Mylchreest (johnm@gentoo.org)

# This version is based on module-rebuild-0.5

# Changed for vdrplugins by Matthias Schwarzott (zzam@gentoo.org)
# Copyright Gentoo Authors

# Changed to a new db-format with seperate files for each ebuild.

if [[ `id -u` != 0 ]]; then
	echo "This application must be ran as root."
	exit 1
fi

R_VERSION="0.5"
R_DBPATH="${ROOT}/usr/share/vdr/vdrplugin-rebuild"
R_PORTAGEQ="`type -p portageq 2>/dev/null`"
if [[ -z ${R_PORTAGEQ} ]]; then
	echo "** FATAL: Unable to find portageq."
	exit 1
fi
R_PORTDIR=$(${R_PORTAGEQ} get_repo_path $(${R_PORTAGEQ} envvar EROOT) gentoo)
R_VDBPATH=`${R_PORTAGEQ} vdb_path`
R_OPTION_X=0;
R_OPTION_C=0;
R_OPTION_ENABLED=0;
R_OPTION_SKIPPED=0;
R_OPTION_PATCHLEVEL=0;
R_OPTION_PM="portage";

R_PLUGIN_ENABLE="${ROOT}/etc/conf.d/vdr.plugins"
VDR_USER_HOME=$(eval echo ~vdr)
R_PLUGINS_SKIPPED="${ROOT}${VDR_USER_HOME}/tmp/plugins_skipped_ALL"

eerror() {
	echo -e "${C_BOLD}${C_RED}** ${@}.${C_NORM}"
}

package_valid() {
	local package=${1}
	[[ -z ${package} ]] && return 1
	[[ -z ${package/*\/*} ]] && return 0 || return 1
}

package_valid_strict() {
	local package=${1}
	package_valid ${package} && [[ -z ${package%%*-[0-9]*} ]] && return 0 || return 1
}

package_exists() {
	local package=${1}

	package=${package%-[0-9]*}
	if $(${R_PORTAGEQ} has_version / ${package}); then
		return 0
	else
		return 1
	fi
}

db_plug_exists() {
	local package=${1} dbfile=${R_DBPATH}/${package/\//-}

	[[ -e ${dbfile} ]] && grep -q VDRPLUGIN_DB "${dbfile}" && return 0
	return 1
}

db_plug_is_good() {
	local package=${1} dbfile=${R_DBPATH}/${package/\//-}
	grep -q ^EBUILD= "${dbfile}" && return 0
	return 1
}

db_plug_list() {
	local dbfile line auto pkg a=0 b=0 ebuild ebuild_v plugins shortname

	for dbfile in $(find "${R_DBPATH}" -type f); do
		grep -q VDRPLUGIN_DB=1 "${dbfile}" || continue
		ebuild=""
		ebuild_v=""
		plugins=""
		eval $(. "${dbfile}"; echo ebuild=\"${EBUILD}\"; echo ebuild_v=\"${EBUILD_V}\"; echo plugins=\"${PLUGINS}\")

		auto=1

		if [[ -z ${ebuild} ]]; then
			{
				eerror "Error in pkg database detected"
				echo "You need to run \"vdrplugin-rebuild populate\""
			} >&2
			exit 1
		fi

		shortname=${ebuild#*/}

		if [[ ${plugins} == "" ]]; then
			plugins=${shortname}
		fi

		set -- ${plugins}
		firstplug="$1"

		if [[ ${R_OPTION_ENABLED} == 1 ]]; then
			# look if any of all plugins installed by this ebuild is enabled
			local p= match=0
			for p in ${plugins}; do
				# match fixed strings, whole line
				if fgrep -q -x ${p#vdr-} "${R_PLUGIN_ENABLE}"
				then
					match=1
				fi
			done
			if [[ $match = 0 ]]; then
				# do not merge if not enabled
				auto=0
			fi
		fi

		if [[ ${R_OPTION_SKIPPED} == 1 ]]; then
			local p= match=0
			for p in ${plugins}; do
				if fgrep -q -x ${p#vdr-} "${R_PLUGINS_SKIPPED}"
				then
					match=1
				fi
			done

			# not merge when not in list of skipped plugins
			if [[ $match = 0 ]]; then
				auto=0
			fi
		fi

		if [[ ${R_OPTION_PATCHLEVEL} == 1 ]]; then
			local p_chksum="${vdr_checksum_dir}/header-md5-${firstplug}"
			if cmp -s "${vdr_checksum}" "${p_chksum}"; then
				# do not merge when patchlevel is equal
				auto=0
			fi
		fi

		if [[ ${R_OPTION_X} == 1 ]]; then
			pkg=${ebuild}
			package_valid ${pkg}
		else
			pkg=${ebuild}-${ebuild_v}
			package_valid_strict ${pkg} && pkg="=${pkg}"
		fi

		if [[ ${auto} = 1 ]]; then
			tomerge[${a}]=${pkg}
			a=$((${a} + 1))
		else
			toignore[${b}]=${pkg}
			b=$((${b} + 1))
		fi
	done

	pkg="${tomerge[@]}${toignore[@]}"
	if [[ -z ${pkg} ]]; then
		echo -e "${C_BOLD}${C_RED}** There are no known plugins. Quitting.${C_NORM}"
		exit 1
	fi

	if [[ -n ${tomerge[@]} ]]; then
		echo -e "${C_BOLD}${C_GREEN}** Packages which I will emerge are:${C_NORM}"
		for pkg in ${tomerge[@]}; do
			echo -e "\t${pkg}"
		done
	fi

	#if [[ -n ${toignore[@]} ]]; then
	#	echo -e "${C_BOLD}${C_GREEN}** Packages which I will ignore are:${C_NORM}"
	#	for pkg in ${toignore[@]}; do
	#		echo -e "\t${pkg}"
	#	done
	#fi
}

# legacy stuff - should not be needed normally

db_plug_add() {
	local package=${1} dbfile=${R_DBPATH}/${package/\//-}

	if db_plug_exists ${package} && db_plug_is_good ${package}; then
		echo -e "${C_BOLD}** Plugin ${package} already exists in vdrplugindb.${C_NORM}"
		return 0
	else
		if package_exists ${package}; then
			if [[ -f ${dbfile} ]]; then
				rm -f "${dbfile}"
				echo -e "${C_BOLD}${C_GREEN}** Fixing db entry for ${package}.${C_NORM}"
			else
				echo -e "${C_BOLD}${C_GREEN}** Adding ${package} to vdrplugindb.${C_NORM}"
			fi
			local ebuild=${package%-[0-9]*}
			local ebuild_v="${package#${ebuild}-}"
			cat <<-EOT > "${dbfile}"
				VDRPLUGIN_DB=1
				CREATOR=vdrplugin-rebuild-POPULATE
				EBUILD=${ebuild}
				EBUILD_V=${ebuild_v}
			EOT
			return 0
		else
			echo -e "${C_RED}** Unable to locate an available ebuild for ${package}.${C_NORM}"
			echo "** Please manually emerge ${package} first."
		fi
	fi
	return 1
}

db_plug_populate() {
	local i x=0 pkg version list pad

	echo -e "${C_BOLD}${C_GREEN}** Populating database with installed Packages.${C_NORM}"
	# Lets find them all
	# chances are we will get a few dupes in here.
	for pkg in $(grep -l ${vdr_plugin_dir}/libvdr ${R_VDBPATH}/*/*/CONTENTS); do
		pad=""; x=0;

		if [[ -z ${pkg//${R_VDBPATH}*} ]]; then
			for((i=0;i<=${#pkg};i++)); do
				[[ ${pkg:${i}:1} = / ]] && x=$((${x} + 1));
				[[ ${x} == 4 ]] || [[ ${x} == 5 ]] && pad="${pad}${pkg:${i}:1}";
			done
			pname="${pad:1}"
			db_plug_add "${pname}"
		fi
	done
}

db_plug_merge() {
	local i pkg

	echo -e "${C_BOLD}** Preparing to merge plugins:${C_NORM}"
	db_plug_list >/dev/null

	if [[ -z ${tomerge[@]} ]]; then
		echo -e "${C_BOLD}${C_RED}** No packages to merge. Quitting.${C_NORM}"
		exit 1
	fi

	echo -e "${C_BOLD}${C_GREEN}** Packages which I will emerge are:"${C_NORM}
	for pkg in ${tomerge[@]}; do
		echo -e "\t${pkg}"
	done

	for((i=1;i<6;i++)); do
		echo -en "${C_BOLD}${C_RED}$((6 - ${i})) ${C_NORM}"
		sleep 1
	done
	echo

	case ${R_OPTION_PM} in
		portage) emerge --ignore-default-opts --oneshot --nodeps --keep-going ${R_PM_OPTS} ${tomerge[@]};;
		paludis) cave resolve -1x -Cs ${R_PM_OPTS} ${tomerge[@]};;
		*) echo "** Unsupported package manager"; phelp; exit 1;;
	esac
}

get_vdr_plugin_dir() {
	local d include_dir=/usr/include/vdr
	d="$(awk '/^PLUGINLIBDIR/{ print $3 }' ${include_dir}/Make.config)"
	if [ -n "${d}" ]; then
		d="$(pkg-config --variable=libdir vdr)"
	fi

	echo "${d}"
	return 0
}

phelp() {
cat << EOF
vdrplugin-rebuild [options] action [options to emerge]
Version: ${R_VERSION}

Where options are:
	-X       - Emerge based on package names,
	           not exact versions.
	-C       - Disable all coloured output.
	-e       - Only merge enabled plugins.
	-s       - Only merge plugins that were skipped at last vdr start.
	-p       - Only merge plugins that are not compiled against this vdr.
	-P <pm>	 - Specify package manager: portage(default) or paludis

Where action is one of:
	list     - List packages to auto-rebuild.
	rebuild  - Rebuild packages.
	populate - Populate the database with any
	           packages which currently install
	           plugins for vdr (should not be necessary).

EOF

}

while [ -n "$1" ]; do
	case "$1" in
		-X) R_OPTION_X='1';;
		-C) R_OPTION_C='1';;
		-e) R_OPTION_ENABLED='1';;
		-s) R_OPTION_SKIPPED='1';;
		-p) R_OPTION_PATCHLEVEL='1';;
		-P) R_OPTION_PM="$2"; shift;;
		-*) phelp; exit 1;;
		*) break;;
	esac
	shift
done

if [[ ${R_OPTION_C} == 0 ]]; then
	C_BOLD='\e[1m'
	C_NORM='\e[0m'
	C_GREEN='\e[32m'
	C_RED='\e[31m'
else
	C_BOLD=''
	C_NORM=''
	C_GREEN=''
	C_RED=''
fi

vdr_plugin_dir=$(get_vdr_plugin_dir)

if [[ ${R_OPTION_SKIPPED} == 1 && ! -f ${R_PLUGINS_SKIPPED} ]]; then
	echo -e "${C_BOLD}${C_GREEN}No Plugins skipped, nothing todo${C_NORM}"
	exit 0
fi

if [[ ${R_OPTION_PATCHLEVEL} == 1 ]]; then
	# needed for plugin patchlevel check
	vdr_checksum_dir="${vdr_plugin_dir%/plugins}/checksums"
	vdr_checksum="${VDR_USER_HOME}/tmp/rebuild-vdr-checksum"
	if ! vdr-get-header-checksum > "${vdr_checksum}"; then
		echo -e "${C_BOLD}${C_RED}Could not get vdr header checksum${C_NORM}"
		exit 1
	fi
fi

R_CMD="$1"
shift
R_PM_OPTS="$@"

# If the vdrplugindb doesnt exist, lets populate it automatically.
if [[ ! -d ${R_DBPATH} ]]; then
	echo -e "${C_BOLD}${C_RED}No vdrplugindb found...${C_NORM}"

	mkdir -p ${R_DBPATH}

	echo -e "${C_BOLD}Populating vdrplugindb...${C_NORM}"
	if [[ ${R_CMD} != populate ]]; then
		db_plug_populate
	fi
fi

case ${R_CMD} in
	list)		db_plug_list;;
	rebuild)	db_plug_merge;;
	populate)	db_plug_populate;;
	*)			phelp; exit 1;;
esac
