#!/bin/sh

if [ -z "${__included_girar_sh_functions-}" ]; then
__included_girar_sh_functions=1

[ -z "${PATH##/usr/libexec/girar:*}" -o -z "${PATH%%*:/usr/libexec/girar}" ] ||
	PATH="/usr/libexec/girar:$PATH"

. shell-error
. girar-sh-config

project_dir_regexp='^packages$|^private$|^public$|^/projects$|^/projects/[A-Za-z0-9][-A-Za-z0-9_.]+$'
project_name_regexp='^[A-Za-z0-9][-A-Za-z0-9_.]+$'
pocket_name_regexp='^[a-z0-9][-a-z0-9_.]+$'
user_name_regexp='^[a-z][a-z_0-9]+$'

prefix_packages()
{
	local fmt='%s' dirname="${1%/*}"
	[ "$dirname" != "$1" ] ||
		fmt='packages/%s'
	printf "$fmt" "$1"
}

prefix_dir()
{
	PREFIX=${DEFAULT_PREFIX_DIR-packages}
	local fmt='%s' dirname="${1%/*}"
	[ "$dirname" != "$1" ] ||
		fmt="$PREFIX/%s"
	printf "$fmt" "$1"
}

add_git_suffix()
{
	local arg="$1"
	[ -z "${arg##*.git}" ] ||
		arg="$arg.git"
	printf %s "$arg"
}

validate_packages_dir()
{
	local dir0 dirname dir
	dir0="$(prefix_dir "$1")"; shift
	dirname="${dir0%/*}"
	printf %s "$dirname" |egrep -qs "$project_dir_regexp" ||
		fatal "$dir0: invalid directory name"
	dir="$(printf %s "${dir0##*/}" |sed -e 's,/\+$,,' -e 's,\.git$,,')"
	printf %s "$dir" |egrep -qs "$project_name_regexp" ||
		fatal "$dir0: invalid directory name"
	printf %s\\n "$dirname/$dir"
}

validate_pocket_name()
{
	local name="$1"; shift
	printf %s "$name" |egrep -qs "$pocket_name_regexp" ||
		fatal "$name: invalid pocket name"
	printf %s\\n "$name"
}

validate_config_name()
{
	local cfg
	cfg="$1"; shift
	printf %s\\n "girar.$cfg"
}

validate_config_value()
{
	local val
	val="$1"; shift
	printf %s\\n "$val"
}

sudo_init()
{
	[ -n "${SUDO_USER-}" ] ||
		fatal 'Environment variable $SUDO_USER not found'

	SUDO_HOME="$(getent passwd "$SUDO_USER" |cut -d: -f6)" ||
		fatal "sudo user '$SUDO_USER' not found"

	SUDO_HOME="$(readlink -ev "$SUDO_HOME")" &&
	[ -d "$SUDO_HOME" ] ||
		fatal "sudo user \`$SUDO_USER' home directory \`$SUDO_HOME' not available"
}

load_identity()
{
	local IDFILE="$1"; shift

	[ -n "$IDFILE" ] ||
		usage 'not specified: IDENTITY FILE'

	IDFILE="$(readlink -ev "$IDFILE")" ||
		fatal "identity file '$IDFILE' not available"

	[ -z "${IDFILE##$SUDO_HOME/*}" ] ||
		fatal "identity file '$IDFILE' out of directory range"

	IDENTITY=$(cat "$IDFILE") ||
		fatal "$IDFILE: error reading identity file"

	local type
	type="$(printf %s "$IDENTITY" |head -c7)"
	case "$type" in
		ssh-dss|ssh-rsa) ;;
		*) fatal "$IDFILE: invalid identity file: unrecognized key type" ;;
	esac
	[ "$(echo "$IDENTITY" |wc -l)" = 1 ] ||
		fatal "$IDFILE: invalid identity file: too many lines"

	local size
	size="$(ssh-keygen -l -f "$IDFILE")"
	size="${size%% *}"
	case "$type" in
		ssh-dss) [ "$size" = 1024 -o "$size" = 2048 -o "$size" = 4096 ] ||
				fatal "$IDFILE: invalid $type key size: $size" ;;
		ssh-rsa) [ "$size" = 2048 -o "$size" = 4096 ] ||
				fatal "$IDFILE: invalid $type key size: $size" ;;
	esac
}

set_name()
{
	NAME="$1"; shift
	[ -n "$NAME" ] ||
		usage 'not specified: NAME'
	printf %s "$NAME" |egrep -qs "$user_name_regexp" ||
		fatal "$NAME: invalid NAME specified"
}

gear_nums()
{
	find gears -mindepth 2 -maxdepth 2 -path 'gears/[1-7]*/userid' -type f 2>/dev/null |
		cut -d/ -f2 |sort -n
}

check_task_modifiable()
{
	local state
	state=$(cat task/state)
	case "$state" in
		AWAITING|EPERM|FAILED|NEW|PENDING|POSTPONED|TESTED)
			;;
		BUILDING|COMMITTING)
			fatal "task #$id is a work in progress" ;;
		DONE)
			fatal "task #$id is already successfully processed" ;;
		*)
			fatal "task #$id is in unrecognized state \"$state\"" ;;
	esac
}

set_repo()
{
	repo="$(girar-normalize-repo-name ${1:-sisyphus})"
}

# get_package_info [<commit>]
#
# Use "gear --describe" to get package name/version/release and place the
# result in global variables: $pkg_name, $pkg_version, $pkg_release.
#
get_package_info()
{
	local commit="${1-HEAD}"

	local output
	output="$(gear --describe -t "$commit" | xargs)" ||
		fatal "'gear --describe -t $commit' failed"
	[ -n "$output" ] ||
		fatal "'gear --describe -t $commit' gave empty output"
	[ -z "${output##* * *}" ] && [ -n "${output##* * * *}" ] ||
		fatal "'gear --describe -t $commit' gave invalid output"
	[ -n "${output##*%*}" ] ||
		fatal "'gear --describe -t $commit' did not expand macros"

	pkg_name="${output%% *}"
	output="${output#* }"
	pkg_version="${output%% *}"
	pkg_release="${output##* }"
}

check_merges()
{
	local merge_base
	local oldrev="$1"
	local newrev="$2"

	if [ "$oldrev" = '0000000000000000000000000000000000000000' ]; then
		merge_base=$(git log --pretty=format:%H --reverse $newrev | head -1)
	else
		merge_base=$(git merge-base $oldrev $newrev)
	fi

	local merge_commit=$(git rev-list -n 1 --merges $merge_base..$newrev)

	if [ -n "$merge_commit" ]; then
		echo "Merge commit detected: $merge_commit"
		return 1
	fi
}

fi #__included_girar_sh_functions
