#! /bin/bash

die () {
	echo >&2 "$@"
	exit 1
}

warn () {
	echo >&2 "$@"
	return 1
}

usage () {
	die "$(basename $0) $kdist_command $USAGE"
}

#
# kdist general stuff
#
kdist__check_kernel () (
	[ -d scripts ] && [ -d scripts/kconfig ] &&
	[ -d arch ] && [ -d arch/x86 ] &&
	[ -r Makefile ] &&
	[ -d .git ] ||
	warn "Invalid kernel directory: $(pwd -P)"
)

kdist__cd_kernel_topdir () {
	#
	# Linux tree must be tracked by git
	#
	git__check_inside_worktree &&
	git__cd_topdir &&
	kdist__check_kernel 2>/dev/null ||
	warn "You must be inside a kernel repository."
}

kdist__configs () {
	mkdir -p $HOME/.kdist &&
	echo $HOME/.kdist/configs
}

kdist__architecture () {
	local arch=$(uname -m)
	case $arch in
	i?86)		arch=i386 ;;
	esac
	echo $arch
}

#
# This function returns the kernel version details throught several
# KERNEL_VERSION_xxx variables
#
kdist__setup_kernel_version () {
	local p

	#
	# The kernel version is given by 'make kernelversion'.
	#
	# Note: this may not be the same as the version given by
	# 'uname -r' since it doesn't have the auto local version
	# stuff.
	#
	KERNEL_VERSION=$(make -s kernelversion)

	#
	# Extract the package num version if any. The package num
	# always starts with a '-' sign. Note that -rcX doesn't match
	# the pattern.
	#
	KERNEL_VERSION_PACKAGE=$(expr $KERNEL_VERSION : ".*-\([0-9]\+\)")

	#
	# KERNEL_VERSION_BASE is the kernel version without the
	# package version stuff.
	#
	KERNEL_VERSION_BASE=${KERNEL_VERSION%-$KERNEL_VERSION_PACKAGE}
}

#
# uname -r
#
kdist__setup_kernel_release () {

	if ! test $KERNEL_VERSION; then
		die "BUG: kdist__setup_kernel_version() must be called first"
	fi

	#
	# Start oldconfig first so if the .config is not uptodate, the
	# next call to it through kernelrelease target will be quiet.
	#
	make -s silentoldconfig &&
	KERNEL_RELEASE=$(make -s kernelrelease) ||
	return

	#
	# Retrieve the localversion (LOCALVERSION + scm + NAME)
	#
	KERNEL_VERSION_LOCAL=${KERNEL_RELEASE#$KERNEL_VERSION}
}

kdist__make_tag () {
	[ $KERNEL_VERSION ] ||
		die "BUG: kdist__make_tag(): kernel version is not set"
	echo v${KERNEL_VERSION_BASE}-$1
}

version__is_released () {
	expr $1 : ".*-\([1-9][0-9]\+\)" >/dev/null
}

#
#
#
config__lookup_symbol_quotes () {
	local sym=$1 file=$2
	local line

	line=$(grep "CONFIG_$sym[= ]" "$file") &&
	case $line in
	*"is not set")	;;
	*=*)		echo ${line#*=} ;;
	esac
}

config__lookup_symbol () {
	local val

	val=$(config__lookup_symbol_quotes "$1" "$2") &&
	case $val in
	\"*\")	val=${val#\"}
		val=${val%\"}
	esac &&
	echo "$val"
}

config__set_symbol () {
	local line

	line=$(grep "CONFIG_$2[= ]" "$3") || {
		#
		# symbol doesn't exist: just happen the new value at
		# the end of the file and let kbuild fix this later.
		#
		echo "CONFIG_$2=$1" >>"$3"
		return
	}
	sed -i "s/$line/CONFIG_$2=$1/" "$3"
}

config__unset_symbol () {
	local sym=$1 file=$2

	if ! val=$(config__lookup_symbol_quotes $sym $file); then
		# Symbol is missing
		echo "# CONFIG_$sym is not set" >>"$file"
		return
	fi

	case $val in
	"")	;;
	\"*\")	sed -i "s/CONFIG_$sym=.*/CONFIG_$sym=\"\"/" "$file" ;;
	*)	sed -i "s/CONFIG_$sym=.*/# CONFIG_$sym is not set/" "$file" ;;
	esac
}

config__append_symbol () {
	local old new=$1

	old=$(config__lookup_symbol_quotes $2 "$3")
	case $old in
	"")	# value is not set or doesn't exist yet: 'new' is
		# already initialized.
		;;
	\"*\")
		# append inside the quotes
		new=${old%\"}
		new=$new$1\" ;;
	*)
		warn "trying to append to a no string value for symbol '$2'"
		return
	esac
	config__set_symbol "$new" $2 "$3"
}

config__get_architecture () {
	local arch

	for arch in X86_64 X86_32; do
		case $(config__lookup_symbol $arch "$1") in
		y)
			case $arch in
			X86_64)		echo x86_64 ;;
			X86_32)		echo i386 ;;
			esac
			return
		esac
	done
	false
}

config__get_flavour () {
	config__lookup_symbol NAME "$1"
}

configs__check_repository () {
	[ -d "$1" ] && 	[ -d "$1"/.git ] &&
	ls -d "$1"/v2.6.[[:digit:]][[:digit:]]/* >/dev/null ||
	warn "Invalid config directory: $1"
}

configs__get_repository () {
	local repo=$(kdist__configs)

	[ -L $repo ] &&
		repo="$(readlink $repo)" ||

	[ -d "$repo" ] || {
		warn "No configs repository is currently tracked."
		return
	}
	configs__check_repository "$repo" &&
	echo $repo
}

config__sanitize_version () {
	case $1 in
	v2.6.*)	expr $1 : "\(v2.6.[0-9]\+\).*" ;;
	*)	expr $1 : "\(v[0-9]\+\.[0-9]\+\).*"
	esac
}

configs__check_clean_db () {
	local repo
	repo=$(configs__get_repository) && (
		cd "$repo"; git__check_clean_work_tree
	)
}

configs__list_db () {
	local vers="$1" arch="$2" name="$3"
	local repo

	vers=$(config__sanitize_version v$vers) &&
	repo=$(configs__get_repository) && (
		cd "$repo"
		git ls-files "$vers/$arch/$name" | while read f
		do
			echo "$repo/$f"
		done
	)
}

#
# kdist command wrappers
#
kdist__run_make () {
	make ${ARCH:+ARCH=$ARCH} ${CC:+CC=$CC} ${CFLAGS:+CFLAGS=$CFLAGS} $KDIST_JOBS "$@"
}

#
# Include all other libs now
#
for lib in $libexecdir/kdist--lib-*; do
	source $lib || exit
done