#!/bin/bash
# Either
#DL_URL=http://your_remote_pkg_host.tld/packages/
# Or
#DL_URL=file:///your/local/pkgbuild_folder/output/
# If local DL_URL is null then slapt-get --update will use SOURCE from /etc/slapt-get/slapt-getrc

# 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 2 of the License, or
# any later version.

# Updates:
# Originally from the author of slapt-get, below:
# http://software.jaos.org/git/slapt-get/plain/FAQ.html#slgFAQ17
# 20170204 step: speed up on multi-cores; fix/adapt for local pkgbuild repo
# 20260313 step: depend busybox; fix USIZE; allow symlinked packages; speed up
# 20260313 step: add PACKAGESTXT and CHECKSUMSMD5 envs, usage, "all-new" arg

MAX_PROCS=${MAX_PROCS:-4}
CHECKSUMSMD5=${CHECKSUMSMD5:-CHECKSUMS.md5} CHECKSUMSMD5=${CHECKSUMSMD5##*/}
PACKAGESTXT=${PACKAGESTXT:-PACKAGES.TXT}    PACKAGESTXT=${PACKAGESTXT##*/}

TAR='busybox tar'
TAR_BRE='\.t\(ar\.\)\?[gblx]z$'

function usage {
	cat <<- EOF
	Usage: ${0##*/} [pkg File|list|all|new|new-all|PACKAGESTXT|MD5]

	With PKGNAME = regex_glob(   File$TAR_BRE   ) :
	.	PKGNAME is considered new if PKGNAME.meta does not exist

	list		list all PKGNAMEs
	pkg File	overwrite PKGNAME.meta
	all		for each File in ./ : "pkg" PKGNAME
	new		for each new File in ./ : "pkg" the new PKGNAME
	new-all		do "all" for new PKGNAMEs only, then "MD5", "PACKAGESTXT"
	PACKAGESTXT	overwrite ./$PACKAGESTXT(.gz)
	MD5		overwrite ./$CHECKSUMSMD5(.gz)
EOF
}

function list_packages {
	if [ ! -e $TMPD/.cached_list ]; then
		busybox find . \( -type f -o -type l \) -regex ".*$TAR_BRE" |
			tee $TMPD/.cached_list
	else
		cat $TMPD/.cached_list
	fi
}

function gen_packages_txt {
	# concatenate file contents from a sorted list of file names,
	# printing an empty-line before the batch and between files contents.
	find . -type f -name '*.meta' | sort | xargs -r awk '
	BEGIN {
		print ""
		RS="@@@"
		for (i=1; i<ARGC; i++) {
			getline < ARGV[i]
			printf "%s", $0
			close(ARGV[i])
		}
		exit
	}' | tee "$PACKAGESTXT" | gzip -9 -c - > "$PACKAGESTXT".gz
}

function gen_md5_checksums {
	echo '' > "$CHECKSUMSMD5"
	list_packages | xargs -r -P$MAX_PROCS -n1 md5sum |
		tee -a "$CHECKSUMSMD5" | gzip -9 -c - > "$CHECKSUMSMD5".gz
}

function gen_meta {
	if [ ! -f $1 ]; then
		echo "$0: Error: \`$1' File not found" >&2
		exit 1
	fi
	case $1 in
		*-*[.-]*[.-]*.* )
			case $1 in
				*.tar.gz|*.tgz|*.tar.bz|*.tbz|*.tar.lz|*.tlz|*.tar.xz|*.txz)
					: "gen_meta process $1" ;;
				* ) return ;;
			esac
			;;
		* ) return ;;
	esac

	REQUIRED=$TMPD/install/slack-required
	CONFLICTS=$TMPD/install/slack-conflicts
	SUGGESTS=$TMPD/install/slack-suggests
	if ! error=$($TAR -xaf "$PWD/$1" -C $TMPD install 2>&1); then
		echo "$0: Error: \`$1': $error" >&2
		return 1
	fi

	NAME=${1##*/}
	LOCATION=${1%$NAME} LOCATION="${LOCATION%/}"
	SIZE=$(du -bk $1) SIZE=${SIZE%%[[:space:]]*}
	USIZE=$(( $($TAR -xOaf $1 | wc -c) / 1024 ))

	[ ! -e "$REQUIRED" ] && REQUIRED= ||
		REQUIRED="$(sed ':a;N;$!ba;s/\n/,/g' $REQUIRED)"

	[ ! -e "$CONFLICTS" ] && CONFLICTS= ||
		CONFLICTS="$(sed ':a;N;$!ba;s/\n/,/g' $CONFLICTS)"

	[ ! -e "$SUGGESTS" ] && SUGGESTS= ||
		SUGGESTS="$(sed ':a;N;$!ba;s/\n/,/g' $SUGGESTS)"

	METAFILE=${NAME%${1##*.}}meta
	exec 9>&1 > "$METAFILE"

	echo "PACKAGE NAME:  $NAME"
	if [ -n "$DL_URL" ]; then
		echo "PACKAGE MIRROR:  $DL_URL"
	fi
	echo "PACKAGE LOCATION:  $LOCATION"
	echo "PACKAGE SIZE (compressed):  $SIZE K"
	echo "PACKAGE SIZE (uncompressed):  $USIZE K"
	echo "PACKAGE REQUIRED:  $REQUIRED"
	echo "PACKAGE CONFLICTS:  $CONFLICTS"
	echo "PACKAGE SUGGESTS:  $SUGGESTS"
	echo "PACKAGE DESCRIPTION:"
	[ -e $TMPD/install/slack-desc ] &&
		awk '/[_[:alnum:]]+:/ && !/^#/' $TMPD/install/slack-desc
	echo ''

	exec 1>&9 9>&-
}

case "$1" in (-h|--help) usage; exit ;; esac

TMPD=/tmp/.pkg2repo.$$
trap "rm -rf $TMPD" EXIT
rm -fr $TMPD
mkdir -p $TMPD

case "$1" in
	pkg)
		if [ -e "$2" ]; then
			case $2 in
				/*) echo "$0: Warning: \`$2' not a relative pathname. Skipped" >&2 ;;
				*) gen_meta "$2" ;;
			esac
		else
			usage >&2
		fi
	;;
	all)
		list_packages | xargs -r -P$MAX_PROCS -n1 "$0" pkg
		gen_packages_txt
		gen_md5_checksums
	;;
	new)
		list_packages |
		while read pkg; do
			if [ ! -f ${pkg%${pkg##*.}}meta ]; then
				gen_meta $pkg
			fi
		done
	;;
	new-all)
		list_packages |
		while read pkg; do
			[ ! -f ${pkg%${pkg##*.}}meta ] && echo $pkg
		done |
		xargs -r -P$MAX_PROCS -n1 "$0" pkg
		gen_packages_txt
		gen_md5_checksums
	;;
	PACKAGESTXT)
		gen_packages_txt
	;;
	MD5)
		gen_md5_checksums
	;;
	list)
		list_packages

	;;
	*)
		usage >&2
	;;
esac
