#!/bin/bash

mydir=$(dirname $0)
max_level=5
yellow='\e[0;33m'
green='\033[32m'
blue='\033[34m'
red='\033[31m'
NC='\e[0m'

function usage()
{
	echo -e "`basename $0` [OPTION]... upstream-commit-id[s]"
	echo
	echo "[OPTION]:"
	echo -e "  -h, --help\t\t\tshow this help info"
	echo -e "  -f, --focus-file\t\tfocus on file or path"
	echo
	echo "  In normal cases, refer to Example-1."
	echo "  Example-1:"
	echo "  found-commit-all-deps upstream-commit-id1... upstream-commit-idN"
	echo
	echo "  If you want to focus on a particular file(path), refer to Example-2."
	echo "  Example-2:"
	echo -e "  found-commit-all-deps --focus-file init/main.c upstream-commit-id1 ... upstream-commit-idN"
	echo
	echo "  Note: In either case, N must >= 1"
}

ARGS=`getopt -o hf: -a --long help,focus-file: -- "$@"`
if [ $? != 0 ]; then
	echo "Terminating..."
	usage && exit -1
fi

eval set -- "${ARGS}"

while true
do
	case $1 in
		-h|--help)
			usage
			exit -1;;
		-f|--focus-file)
			focus_file="$2"
			shift 2;;
		--)
			shift
			break;;
	esac
done

[ $# -lt 1 ] && usage && exit -1
[ ! -f $focus_file ] && [ ! -d $focus_file ] && echo -e "${red}$focus_file${NC} is not regular file or path.\n" && usage && exit -1

commits="$@"
$(dirname $0)/../stable-tools/stable commit-in-tree $1
[ $? == 1 ] && echo -e "${green}In-tree, not need.${NC}" && exit 1;

# Need git-deps
command -v git-deps >/dev/null 2>&1 || echo "git-deps not found, run 'pip install git-deps' first"

# args:
#   $1 => commit
#   $2 => level file
function commit-deps () {
	single_commit_deps=$(git deps $1...$1^)
	echo $1 >> $_commitlisttmpfile

	local inner_found=0
	for l_commit in $single_commit_deps
	do
		if [ ! -z $focus_file ]; then
			git diff-tree --no-commit-id --name-only -r $l_commit |
				grep "$focus_file" > /dev/null
			[ $? -eq 1 ] && continue
		fi

		$mydir/../stable-tools/stable commit-in-tree $l_commit
		if [[ $? != 1 ]]; then
			tag=$(git tag --sort=taggerdate --contains $l_commit | head -n 1)
			# for next level
			echo "$1 : $l_commit : $tag" >> $_patchlisttmpfile
			# print
			echo "$1 : $l_commit : $tag"
			inner_found=1
		fi
	done

	[ $inner_found = 1 ] && return 1
	return 0
}

# temp file for depend founding
_patchlisttmpfile=$(mktemp)
_commitlisttmpfile=$(mktemp)

for ((level=0; level < max_level; level++))
do
	need_print_level="true"

	for commit in $commits
	do
		# sanity check commitid
		if test -z "$(git log -1 --pretty=%s $commit 2> /dev/null)"
		then
		        echo -e "${yellow}Skipping: Bad commit ID: ${commit}${NC}"
		        continue
		fi

		grep -rn "$commit" $_commitlisttmpfile &> /dev/null
		# Not search before
		if [ $? = 1 ];
		then
			if [ x"$need_print_level" == x"true" ]; then
				# Insert empty line
				[ $level != 0 ] && echo
				echo -e "${blue}Level $level:${NC}"
				need_print_level="false";
			fi
			commit-deps $commit
			[ $? = 0 ] && echo -e "$commit : ${green}done.${NC}"
		fi
	done

	# have next level?
	if [ -f $_patchlisttmpfile ]; then
		commits=$(cat $_patchlisttmpfile | awk -F':' '{print $2}' | uniq)
		[ -z "$commits" ] && break
	else
		break;
	fi

	# clean
	[ -f $_patchlisttmpfile ] && rm -f $_patchlisttmpfile
done

[ -f $_commitlisttmpfile ] && rm -f $_commitlisttmpfile

if [ $level = $max_level ]; then
	echo -e "${yellow}The dependency level exceeds $max_level, I suggest you to split the search,"
	echo -e "or change the max_level value of this script.${NC}"
fi

# Level value is for working with scripts like sync-stable.
# For example, when found-commit-all-deps exit with 0, you can use sync-stable
# to apply the commit right away.
#
# When found-commit-all-deps exit with value above 0, you need to check each
# dependency manually.
exit $level
