#!/bin/sh -e
# $Id: sisyphus_relink,v 1.3 2004/05/13 14:49:07 ldv Exp $

. /etc/sisyphus/config

cd "$PREFIX"

: ${debug:=}
: ${verbose:=}

PROG="${0##*/}"
WORKDIR=

exit_handler()
{
	local rc=$?
	trap - EXIT
	[ -z "$WORKDIR" ] || rm -rf -- "$WORKDIR"
	exit $rc
}

trap exit_handler SIGHUP SIGINT SIGQUIT SIGTERM EXIT

WORKDIR="$(mktemp -d -t "$PROG.XXXXXXXXXX")"

unlink_symlinked()
{
	local dir=$1
	shift
	[ -d "$dir" ] || return 0
	echo "Unlinking in $dir"
	find "$dir/" -type l -delete
}

check_arch_dups()
{
	local arch=$1
	shift

	echo "Checking layout dups for $arch"
	local out
	out=$(cut -f1 "files/list.$arch".* |sort |uniq -c |awk '{if ($1!=1) print $2}')
	if [ -n "$out" ]; then
		echo "ERROR: duplicated names found in $arch layout:" >&2
		echo "$out" >&2
		return 1
	fi
}

calc_arch_pkgnames()
{
	local arch=$1
	shift
	local rpms=$1
	shift

	echo "Calculating pkgnames in files/$rpms for $arch"
	find "files/$rpms/" -type f -name \*.rpm -print0 |
		xargs -r0 rpmquery -p --qf '%{NAME} %{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}.rpm\n' -- |
		sort -u >"$WORKDIR/$arch"
}

calc_arch_srcnames()
{
	local arch=$1
	shift
	local rpms=$1
	shift

	echo "Calculating srcnames in files/$rpms for $arch"
	find "files/$rpms/" -type f -name \*.rpm -print0 |
		xargs -r0 rpmquery -p --qf '%{NAME} %{NAME}-%{VERSION}-%{RELEASE}.src.rpm\n' -- |
		sort -u >"$WORKDIR/$arch"
}

check_arch_missing()
{
	local arch=$1
	shift

	local list="$WORKDIR/$arch"
	[ -s "$list" ] || return 0

	echo "Checking layout misses for $arch"
	local out
	out=$(cut -f1 "files/list.$arch".* |sort -u |join "$list" - -v1 |cut -d' ' -f1 |sort -u)
	if [ -n "$out" ]; then
		echo "ERROR: missing names found in $arch layout:" >&2
		echo "$out" >&2
		return 1
	fi
	local f
	for f in "files/list.$arch".*; do
		out=$(cut -f1 "$f" |sort -u |join "$list" - -v2 |cut -d' ' -f1 |sort -u)
		if [ -n "$out" ]; then
			echo "WARNING: orphaned names found in ${f#files/list.} layout:" >&2
			echo "$out" >&2
		fi
	done
}

calc_comp()
{
	local arch=$1
	shift
	local comp=$1
	shift

	local list="files/list.$arch.$comp"
	[ -s "$list" ] || return 0

	echo "Calculating components: $arch/$comp"
	cut -f1 "$list" |sort -u |join "$WORKDIR/$arch" - |
		cut -d' ' -f2 |
		sort -u >"$WORKDIR/$arch.$comp"
}

relink_arch()
{
	local arch=$1
	shift
	local comp=$1
	shift
	local rpms=$1
	shift

	local list="$WORKDIR/$arch.$comp"
	[ -s "$list" ] || return 0

	echo "Relinking in $rpms.$comp"
	local rc=0
	local n f
	local full_d full_r full_n r

	local d="$rpms.$comp"
	[ -d "$d" ] || return 0
	full_d=`readlink -fv "$d"`

	[ -d "files/$rpms" ] || return 0
	full_r=`readlink -fv "files/$rpms"`

	r=`relative "$full_r" "$full_d/"`
	cat "$list" |while read n; do
		f="files/$rpms/$n"
		[ -f "$f" ] || continue
		$debug ln -s $verbose "$r/$n" "$d/" || rc=1
	done
	return $rc
}

problems_list=

# src
for arch in src; do
	check_arch_dups "$arch" || exit
	calc_arch_srcnames "$arch" "SRPMS" || exit
	check_arch_missing "$arch" || exit
	for comp in $LINKONLY_COMPONENTS $MIXED_COMPONENTS; do
		calc_comp "$arch" "$comp" || exit
		unlink_symlinked "SRPMS.$comp" || exit
		if ! relink_arch "$arch" "$comp" "SRPMS"; then
			echo "ERROR: $arch"
			problems_list="$problems_list $arch"
		fi
	done
done

# arch
for arch in $ARCHITECTURES; do
	check_arch_dups "$arch" || exit
	calc_arch_pkgnames "$arch" "$arch/RPMS" || exit
	check_arch_missing "$arch" || exit
	for comp in $LINKONLY_COMPONENTS $MIXED_COMPONENTS; do
		calc_comp "$arch" "$comp" || exit
		unlink_symlinked "$arch/RPMS.$comp" || exit
		if ! relink_arch "$arch" "$comp" "$arch/RPMS"; then
			echo "ERROR: $arch"
			problems_list="$problems_list $arch"
		fi
	done
done

if [ -n "$problems_list" ]; then
	echo "${0##*/}: problems in:$problems_list"
	exit 1
fi

echo "Updating classic..."
sisyphus_update_classic
