#!/bin/busybox ash

# update-everything v9.0 (December 21, 2023)
# by Bruno "GNUser" Dantas, with special thanks to jazzbiker, Rich, Paul_123
# GPLv3

# Purpose: Do a full TCL system update as quickly and efficiently as possible, leaving custom extensions intact 
# Usage: $ update-everything

PATH="/bin:/sbin:/usr/bin:/usr/sbin"
export PATH

main()
{
	rm -rf "$TMPDIR"; mkdir "$TMPDIR"; cd "$TMPDIR"
	. /etc/init.d/tc-functions
	getMirror

	echo "Downloading and preparing databases..."
	download "$MD5DBGZ"; extract "$MD5DBGZ"; sanity_check_md5db
	download "$DEPDBGZ"; extract "$DEPDBGZ"; generate_depdir; sanity_check_depdir

	echo "Syncing .dep files..."
	fix_missing_and_extraneous_dep_files
	update_dep_files

	if $DEP_FILES_CHANGED; then
		echo "Building package database..."
		tce-audit builddb
		echo "Looking for missing dependencies..."
		tce-audit fetchmissing
	fi

	echo "Updating extensions..."
	tce-update --skip-dependency-check

	rm -rf "$TMPDIR"
	exit 0
}

download()
{
	if ! wget -q "$MIRROR/$1"; then
		echo "Download of $1 failed. Aborting."
		exit 1
	fi
}

extract()
{
	if ! gunzip -kf "$1"; then
		echo "Error extracting $1. Aborting."
		exit 1
	fi
}

sanity_check_md5db()
{
	if ! grep -q " zstd.tcz" "$MD5DB"; then
		echo "$MD5DB is missing or incomplete. Aborting."
		exit 1
	fi
}

generate_depdir()
{
	mkdir "$DEPDIR"
	cp "$DEPDB" "$DEPDIR"
	awk -v DEPDIR="$DEPDIR" 'BEGIN {FS="\n";RS=""} { out=DEPDIR"/"$1".dep"; for (i=2; i<=NF; i++) printf("%s\n", $(i)) >out; close(out) }' "$DEPDB"
}

sanity_check_depdir()
{
	if ! [ -f "$DEPDIR/zstd.tcz.dep" ]; then
		echo "$DEPDIR is missing or incomplete. Aborting."
		exit 1
	fi
}

fix_missing_and_extraneous_dep_files()
{
	for md5file in $(find -L "$OPTIONALDIR" -name '*.md5.txt' -exec basename {} \;); do
		depfile="${md5file%.md5.txt}.dep"
		tczfile="${md5file%.md5.txt}"
		if [ -f "$DEPDIR/$depfile" ] && [ ! -f "$OPTIONALDIR/$depfile" ]; then
			echo "$depfile is missing, adding it..."
			cp "$DEPDIR/$depfile" "$OPTIONALDIR"
			DEP_FILES_CHANGED=true
		elif [ ! -f "$DEPDIR/$depfile" ] && [ -f "$OPTIONALDIR/$depfile" ] && grep -q " $tczfile" "$MD5DB"; then
			echo "$depfile is extraneous, removing it..."
			rm "$OPTIONALDIR/$depfile"
		fi
	done
}

update_dep_files()
{
	for md5file in $(find -L "$OPTIONALDIR" -name '*.md5.txt' -exec basename {} \;); do
		depfile="${md5file%.md5.txt}.dep"
		if [ ! -f "$OPTIONALDIR/$depfile" ] || [ ! -f "$DEPDIR/$depfile" ]; then # nothing to compare
			continue
		# echo is used in the comparison to eat whitespace (e.g., trailing spaces and blank lines):
		elif [ "$(echo $(cat "$OPTIONALDIR/$depfile"))" = "$(echo $(cat "$DEPDIR/$depfile"))" ]; then
			continue
		else
			echo "$depfile has changed, updating it..."
			cp "$DEPDIR/$depfile" "$OPTIONALDIR"
			DEP_FILES_CHANGED=true
		fi
	done
}

# internal variables, do not touch:
OPTIONALDIR="/etc/sysconfig/tcedir/optional"
TMPDIR="/tmp/update-everything"
DEPDIR="$TMPDIR/depfiles"
DEPDB="dep.db"
DEPDBGZ="$DEPDB.gz"
MD5DB="md5.db"
MD5DBGZ="$MD5DB.gz"
DEP_FILES_CHANGED=false

main
