#!/bin/sh
# visit Ypnose - http://ywstd.fr
set -e

# It's advised to use the following script before running 'rypp-mk'
# https://github.com/Ypnose/dotfiles/blob/master/bin/grabmusl

####################
# NEVER FINAL... ALWAYS MOVING.
p_err() {
	printf '\033[31mERR\033[0m: %s\n' "$@" >&2
	exit 1
}
p_msg() {
	printf '\033[1m=>\033[0m %s\n' "$@" >&2
}
p_warn() {
	printf '\033[1;33mWARN\033[0m: %s\n' "$@" >&2
}
p_dbg() {
	exit $(
	 printf '%s\n' "$1"
	 shift 1
	 printf "\033[32m [*] %s\033[0m\n" "$@" >&2
	)
}

sub_task() {(
	RYPP_SUB=1 rypm "$1"
)}

RYPP_UTIL="${0##*/}"
SOLCUR="${1%/}"
if [ -z "${SOLCUR:+s}" ]; then
	SOLCUR=.
	p_msg "reverting to ./SOLTASK"
fi
if [ -f "$SOLCUR" ]; then
	SOLTASK=$(printf '%s\n' "$SOLCUR" |grep -o '[^/]*$')
	SOLCUR=$(printf '%s\n' "$SOLCUR" |grep -o '^.*/') ||\
	 SOLCUR=.
	SOLCUR=${SOLCUR%/}
	SOLTASK="${SOLCUR}/${SOLTASK}"
elif [ -d "$SOLCUR" ]; then
	SOLTASK="${SOLCUR}/SOLTASK"
else
	p_err "malfunc PKG path: $SOLCUR"
fi
p_msg "base $SOLCUR : $SOLTASK"
RYPP_UPKG=$(cd "$SOLCUR" >/dev/null 2>&1; printf "%s\n" "$PWD")
# Environment
RYPP_ROOT="${RYPP_ROOT:-/opt/rypp}"
SOLBASE="$RYPP_ROOT"
RYPP_PKG="${RYPP_ROOT}/pkg"
RYPP_BUILD="${RYPP_ROOT}/src"
# Architecture (musl ONLY)
RYPP_TARGET="x86_64-unknown-linux-musl"
# Pseudo nproc(1) implementation (grep -c is POSIX)
RYPP_MKJOBS="$(grep -c 'model name' /proc/cpuinfo)"
SOLOPT="-Os"
CFLAGS="$SOLOPT -pipe -fstack-protector-strong"
LC_ALL=C
export CFLAGS LC_ALL

####################

# like in solyste/rc/libs/gfuncs
chk_path() {
	# Return binaries ONLY. POSIX 'command' builtin returns functions.
	# local isn't specified by POSIX!
	local IFS
	local p

	IFS=':'
	for p in $PATH; do
		if [ ! -d "$p" ]; then
			continue
		fi
		if [ -x "${p}/${1}" ]; then
			printf "?=> %s\n" "${p}/${1}" >&2
			return 0
		fi
	done
	p_err "PATH, $1 - not found"
}
chk_h() {
	if [ ! -f "${RYPP_ROOT}/include/${1}" ]; then
		p_err " include/$1 is missing..."
	else
		printf "?.h=> %s\n" "include/${1}" >&2
	fi
}
chk_a() {
	if [ ! -f "${RYPP_ROOT}/lib/${1}" ]; then
		p_err " lib/$1 is missing..."
	else
		printf "?.a=> %s\n" "lib/${1}" >&2
	fi
}
chk_dir() {
	if [ ! -d "$1" ]; then
		p_err "$1 directory is missing"
	fi
}

chk_vars() {
	#no SOLVER, p_err check
	if [ -z "${SOLSRC:+s}" ]; then
		SOLSRC=:here
		p_msg " SOLSRC=:here (reside&audit)"
		return 1
	fi
	if [ -z "${SOLSUM:+s}" ]; then
		p_err "SOLSUM is not defined in $SOLTASK"
	fi
	if ! type run_task | grep -q 'function'; then
		p_err "run_task is not defined in $SOLTASK"
	fi
}

get_url() {(
	fil="${RYPP_PKG}/${SOLSRC##*/}"
	if [ -e "$fil" ]; then
		chk_sums
		ext_tarb
		return 0
	fi
	mkdir -p "$RYPP_PKG"

	src="$SOLSRC"
	if printf '%s\n' "$SOLSRC" |grep -q '^https\?://'; then
		p_msg "Downloading from URL, $src..."
		curl -f -L "$src" -o "$fil"
		chk_sums
		ext_tarb
	else
	src="${RYPP_UPKG}/${SOLSRC}"
		if [ -f "$src" ]; then
			p_msg "local file-archive -> $fil"
			cp "$src" "$fil"
			chk_sums
			ext_tarb
		else
			p_err "$src - file-archive non-existsing"
		fi
	fi
)}

chk_sums() {(
	if [ "$SOLSUM" = "PASS" ]; then
		return 0
	fi
	DL_SRC="${RYPP_PKG}/${SOLSRC##*/}"
	DL_SUM="$(sha256sum "$DL_SRC")"
	p_msg "Verifying ${DL_SRC##*/} sums..."
	if [ "${DL_SUM%% *}" != "$SOLSUM" ]; then
		p_err "${DL_SRC} - checksums differ!"
	fi
)}

ext_tarb() {(
	ex="${RYPP_PKG}/${SOLSRC##*/}"
	p_msg "Extracting ${ex##*/}..."
	mkdir -p "$RYPP_BUILD"
	case "$ex" in
		*.t*bz2) tar -jxf "$ex" -C "$RYPP_BUILD" ;;
		*.t*gz)  tar -zxf "$ex" -C "$RYPP_BUILD" ;;
		*.t*xz)  tar -Jxf "$ex" -C "$RYPP_BUILD" ;;
		*)      p_err "$ex archive is not supported" ;;
	esac
)}

pre_task() {
	# non-POSIX
	local PK_PAT

	# source Patch directory...
	PK_PAT="${RYPP_UPKG}"
	# Check Task Working Directory
	if [ "$SOLSRC" = :here ]; then
		:
	elif [ -n "${SOLTWD:+s}" ]; then
		chk_dir "${RYPP_BUILD}/${SOLTWD}"
		cd "${RYPP_BUILD}/${SOLTWD}"
	else
		# Default location: src/foo-1.0
		# 'foo' is defined thanks to the base dir ('pkgs/foo/SOLTASK')
		chk_dir "${RYPP_BUILD}/${RYPP_UPKG##*/}${SOLVER:+-$SOLVER}"
		cd "${RYPP_BUILD}/${RYPP_UPKG##*/}${SOLVER:+-$SOLVER}"
	fi
	p_msg "Building @ ${RYPP_BUILD}/${SOLTWD}"
	p_msg " <-(betray the way, call in the frey: spirits; hear and belong to me)"
}

####################

get_configs() {( :
#	for c in config.guess config.sub; do
#		curl -Ss -f -L "http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=${c}" \
#			-o "$c"
#	done
)}

set_flag() {
	export PREFIX="${RYPP_ROOT}"
	export CFLAGS="$CFLAGS -I${PREFIX}/include" \
	 LDFLAGS="$LDFLAGS -L${PREFIX}/lib" \
	 PKG_CONFIG_PATH="" \
	 PKG_CONFIG_LIBDIR="${PKG_CONFIG_LIBDIR:+$PKG_CONFIG_LIBDIR:}${PREFIX}/lib/pkgconfig"
}

def_configure() {
	export PREFIX="${RYPP_ROOT}"
	./configure \
		--host="$RYPP_TARGET" \
		--prefix="$PREFIX" \
		--bindir="${PREFIX}/bin" \
		--sbindir="${PREFIX}/bin" \
		--mandir="${PREFIX}/share/man" \
		--libdir="${PREFIX}/lib" \
		--libexecdir="${PREFIX}/libexec" \
		--includedir="${PREFIX}/include" \
		--sysconfdir="/etc" \
		--localstatedir="/var" \
		"$@"
}

def_make() {
	make -j"${RYPP_MKJOBS:-1}" "$@"
}

lib_task() {
	p_msg "${RYPP_UPKG##*/} library is installed"
	printf "%s\n" "DONE"
	exit
}

cp_sol() {
	if [ ! -f "$1" ] &&[ ! -d "$1" ]; then
		p_err "$1 not of file or folder"
	fi
	p_msg "Copying $1 to ${RYPP_ROOT}/${2:+$2/}$3"
	mkdir -p "${RYPP_ROOT}/$2"
	cp -r "$1" "${RYPP_ROOT}/${2:+$2/}$3"
}

cp_bin() {
	if [ ! -x "$1" ]; then
		p_err "$1 is not executable or simply missing"
	fi
	cp_sol "$1" "bin" "$2"
}

ln_bin() {
	if [ ! -x "${RYPP_ROOT}/bin/${1}" ]; then
		p_err "${RYPP_ROOT}/bin/${1} is missing or not executable"
	fi
	( cd "${RYPP_ROOT}/bin"; ln -sf "$1" "$2" )
}

cp_man() {(
	SE_MAN="${1%%*.gz}"
	SE_MAN="${SE_MAN##*.}"
	p_msg "Copying $1 to ${RYPP_ROOT}/share/man/man${SE_MAN}/${2}"
	mkdir -p "${RYPP_ROOT}/share/man/man${SE_MAN}"
	cp "$1" "${RYPP_ROOT}/share/man/man${SE_MAN}/${2}"
)}

####################

chk_bins() {(
	err=''
	strip=''
	chk_dir "${RYPP_ROOT}/bin"
	for b in "${RYPP_ROOT}/bin/"*; do
		i=$(file "$b")
		if ! printf '%s\n' "$i" | grep -q 'ELF'; then
			continue
		fi
		if printf '%s\n' "$i" | grep -q 'not stripped'; then
			strip="$strip"'
'" strip -s $b" 
		fi
		if ! printf '%s\n' "$i" | grep -q 'statically'; then
			err="$err"'
'" $b"
		fi
	done
	if [ -n "${strip:+s}" ]; then
		p_msg "following binaries could use$strip"
	fi
	if [ -n "${err:+s}" ]; then
		p_err "following binaries are not statically linked!$err"
	fi
)}

ryp_files() {(
	RP_DIR="${RYPP_ROOT}/var/rypp/${RYPP_UPKG##*/}"
	mkdir -p "$RP_DIR"
	find "$RYPP_ROOT" ! -type d \
		| sed "s|${RYPP_ROOT}/||g" \
		| sort >"${RYPP_BUILD}/FILES"
	cp "${RYPP_BUILD}/FILES" "$RP_DIR"

	# gcc prints everything on stderr
	printf "%s\n" "$SOLVER $(date '+%Y%m%d') $("${CC:-gcc}" --version 2>&1 | awk 'NR==1{print $1}')" \
		>"${RP_DIR}/META"
	chmod 444 "${RP_DIR}/FILES" "${RP_DIR}/META"
)}

gen_tarb() {(
	RP_TAR="$(tar --version | awk 'NR==1{print $1}')"
	RP_ARC="${RYPP_ROOT}/${RYPP_UPKG##*/}${SOLVER:+_$SOLVER}.rypp.tgz"
	# --uname + --gname?
	if [ "$RP_TAR" = "bsdtar" ]; then
		RP_OPT="--uid=0 --gid=0"
	# Assume it is GNU tar (NAME[:UID]?)
	elif [ "$RP_TAR" = "tar" ]; then
		RP_OPT="--owner=0 --group=0"
	fi
	p_msg "Creating and verifying package archive..."

	# Do not want to use '-C' from tar(1)
	cd "$RYPP_ROOT" #(localiz'd cd)
	tar $RP_OPT -czf "$RP_ARC" *
	# Make sure local uid and gid are not leaking
	# bsdtar output: -rwxr-xr-x  0 foo    bar
	# GNU tar output: -rwxr-xr-x foo/bar
	if tar -vtf "$RP_ARC" | egrep "$(id -un)[\/\t ]+$(id -gn)"; then
		p_err "Wrong owner or group in archive"
	fi
)}

####################

if [ "$#" -gt 1 ] || [ "$1" = "-?" ]; then
	printf "%s\n" "usage: $RYPP_UTIL [PKG]"
	exit
fi

# Vital checks...
if [ "$(id -u)" -eq 0 ]; then
	p_err "$RYPP_UTIL cannot be used as root"
fi
if [ ! -r "$SOLTASK" ]; then
	p_err "$SOLTASK is either missing or unreadable"
fi
if [ -x "$SOLTASK" ]; then
	p_err "$SOLTASK shouldn't be executable"
fi
chk_dir "$RYPP_ROOT"
if [ ! -w "$RYPP_ROOT" ]; then
	p_err "Write permission is not allowed in $RYPP_ROOT"
fi

rm -rf "$RYPP_BUILD"

####################

. "$SOLTASK"
if chk_vars; then
	mkdir -p "${RYPP_BUILD}"
	get_url
fi
# Launch the build now
(
	cd "${SOLCUR}"
	SOLCUR="$PWD"
	#p_dbg 7 "$PWD"
	pre_task
	run_task
)
if [ -n "${RYPP_LIB:+s}" ]; then
	lib_task
fi

if [ -z "${RYPP_SUB:+s}" ]; then
 chk_bins
fi
#ryp_files
#gen_tarb

####################

printf "%s\n" "DONE"
exit