#!/bin/sh
#
#  scratchpkg
#
#  Copyright (c) 2018 by Emmett1  (emmett1.2miligrams@gmail.com)
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
#

trap "interrupted" 1 2 3 15

export LC_ALL=C

interrupted() {
	echo
	ret 1
}

msg() {
	echo "==> $1"
}

msg2() {
	echo " -> $1"
}

msgerr() {
	echo "==> ERROR: $1" >&2
}

msgwarn() {
	echo "==> WARNING: $1" >&2
}

help() {	
	cat << EOF	
Usage:
  $(basename $0) [ <options> <package name> ]

Options:
  -h, --help            show this help message
  -v, --verbose         print removed files
      --no-preremove    don't run pre-remove script
      --no-postremove   don't run post-remove script
      --root=<path>     remove package from custom root directory
      
EOF
}

extract_opts() {
	while [ "$1" ]; do
		case $1 in
			--*) opts="$opts $1";;
			-*) char=${#1}; count=1
			    while [ "$count" != "$char" ]; do
					count=$((count+1))
					opts="$opts -$(echo $1 | cut -c $count)"
				done;;
			*) opts="$opts $1"
		esac
		shift
	done
	echo $opts
}

parse_opts() {
	if [ -z "$1" ]; then
		SHOWHELP=yes
	else
		while [ "$1" ]; do
			case $1 in
			-h |              --help) SHOWHELP=yes ;;
			-v |           --verbose) VERBOSE_REMOVE="-v" ;;
			          --no-preremove) NO_PREREMOVE=yes ;;
			         --no-postremove) NO_POSTREMOVE=yes ;;
			                --root=*) ROOT_DIR="${1#*=}" ;;
			                      -*) msg "Invalid option: ($1)"; exit 1 ;;
			                       *) RMNAME=$1 ;;
			esac
			shift
		done
	fi
}

ret() {
	# remove lock file on exit
	rm -f "$ROOT_DIR/$LOCK_FILE" "$reserve" "$dirs" "$remove" "$files"
	exit $1
}

isinstalled() {
	if [ -s "$ROOT_DIR/$PKGDB_DIR/$1/.pkginfo" ] && grep -q "$1" "$ROOT_DIR/$PKGDB_DIR/$1/.pkginfo"; then
		return 0
	else
		return 1
	fi
}

run_scripts() {
	if [ "$ROOT_DIR" ]; then
		xchroot "$ROOT_DIR" sh $@
	else
		sh $@
	fi
}

command -v pkgadd >/dev/null 2>&1 || {
	msgerr "'pkgadd' not found in \$PATH!"
	exit 1
}

parse_opts $(extract_opts "$@")

PKGDB_DIR="$(pkgadd --print-dbdir)"
PKGDB_DIR="${PKGDB_DIR##/}"              # remove leading /
LOCK_FILE="var/lib/scratchpkg/spkg.lock"

# show help page
[ "$SHOWHELP" ] || [ -z "$RMNAME" ] && {
	help
	ret 0
}

# check for root access
[ "$(id -u)" = "0" ] || {
	echo "Removing package need root access!"
	ret 1
}

# check for lock file
[ -f "$ROOT_DIR/$LOCK_FILE" ] && {
	msgerr "Cant install/remove package simultaneously."
	msgerr "remove '$ROOT_DIR/$LOCK_FILE' if no install/remove package process running."
	exit 1
}

touch "$ROOT_DIR/$LOCK_FILE" 2>/dev/null || {
	msgerr "Cant create lock file in '$ROOT_DIR/$LOCK_FILE'"
	exit 1
}

if ! isinstalled "$RMNAME"; then
	msgerr "Package '$RMNAME' not installed."
	ret 1
fi

name=$(grep ^name $ROOT_DIR/$PKGDB_DIR/$RMNAME/.pkginfo | cut -d " " -f3-)
version=$(grep ^version $ROOT_DIR/$PKGDB_DIR/$RMNAME/.pkginfo | cut -d " " -f3-)
release=$(grep ^release $ROOT_DIR/$PKGDB_DIR/$RMNAME/.pkginfo | cut -d " " -f3-)

if [ -z "$name" ] && [ -z "$version" ] && [ -z "$release" ]; then
	msgerr "Package '$RMNAME' not installed but exist in database."
	ret 1
fi

# create list for reserve and remove (dirs and files)
reserve="$ROOT_DIR/$SCRATCHPKG_DIR/.pkgdel_reserve"
remove="$ROOT_DIR/$SCRATCHPKG_DIR/.pkgdel_remove"
dirs="$ROOT_DIR/$SCRATCHPKG_DIR/.pkgdel_dirs"
files="$ROOT_DIR/$SCRATCHPKG_DIR/.pkgdel_files"

grep '/$' $ROOT_DIR/$PKGDB_DIR/*/.files \
	| grep -v "$ROOT_DIR/$PKGDB_DIR/$name" \
	| awk -F : '{print $2}' \
	| sort \
	| uniq > "$reserve"
grep '/$' "$ROOT_DIR/$PKGDB_DIR/$name/.files" > "$remove"
grep -Fxv -f "$reserve" "$remove" | tac > "$dirs"
grep -v '/$' "$ROOT_DIR/$PKGDB_DIR/$name/.files" | tac >> "$files"

echo "remove: $name-$version-$release..."

# pre-remove script
if [ ! "$NO_PREREMOVE" ] && [ -f "$ROOT_DIR/$PKGDB_DIR/$name/.pkginstall" ]; then
	(cd "$ROOT_DIR"/
		run_scripts "$PKGDB_DIR/$name/.pkginstall" pre-remove "$version"
	)
fi

# remove files and dirs
(cd "$ROOT_DIR"/
	[ -s $files ] && xargs -a $files -d'\n' rm $VERBOSE_REMOVE
	[ -s $dirs ]  && xargs -a $dirs -d'\n' rmdir $VERBOSE_REMOVE
)

rm -f "$reserve" "$dirs" "$remove" "$files"

# post-remove script
if [ ! "$NO_POSTREMOVE" ] && [ -f "$ROOT_DIR/$PKGDB_DIR/$name/.pkginstall" ]; then
	(cd "$ROOT_DIR"/
		run_scripts "$PKGDB_DIR/$name/.pkginstall" post-remove "$version"
	)
fi

# remove from database
rm -rf "$ROOT_DIR/$PKGDB_DIR/$name"

# running ldconfig
if [ -x "$ROOT_DIR"/sbin/ldconfig ]; then
	"$ROOT_DIR"/sbin/ldconfig -r "$ROOT_DIR"/
fi

ret 0
