#!/bin/sh -e
#
# $Id: cache_chroot,v 1.20 2004/07/22 09:53:10 ldv Exp $
# Copyright (C) 2003, 2004  Dmitry V. Levin <ldv@altlinux.org>
# 
# The chroot cache functions for the initroot
#
# This file 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
# (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, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#

rebuild_chroot_cache=

archive_chroot_cache()
{
	[ -n "$rebuild_chroot_cache" ] || return 0

	local rpmdb_archive="cache/chroot/rpmdb.tar"
	local chroot_archive="cache/chroot/chroot.cpio"

	trap 'rm -f -- "$rpmdb_archive" "$chroot_archive"' EXIT HUP INT QUIT TERM

	# rpmdb
	tar -cf "$rpmdb_archive" -C aptbox/var/lib/rpm/ . &&
		Verbose "RPM database archivation complete" ||
		Fatal "RPM database archivation failed."

	# chroot
	local list
	list=`ls -1 chroot/ |grep -v ^dev` && [ -n "$list" ] &&
		list=`printf %s "$list" |tr '[:space:]' ' '` ||
		Fatal "chroot is not ready for archivation."

	cat >"$entry" <<__EOF__
#!/bin/sh -e
cd /

list="\$(/.host/find $list)"
printf %s "\$list" |
	/.host/cpio --create --quiet --format=newc
__EOF__

	wlimit_time_elapsed=300 wlimit_time_idle=300 \
	"$chrootuid1" $number "$chroot" /.host/entry >"$chroot_archive" &&
		Verbose "chroot archivation complete" ||
		Fatal "chroot archivation failed."

	trap - EXIT HUP INT QUIT TERM
} # archive_chroot_cache

check_chroot_cache()
{
	[ -z "$no_cache" ] || return 0

	local f n
	local bad="cache/chroot/list.new/bad"
	rm -f "$bad"
	cat cache/chroot/list.new/{init,build} |
		while read f; do
			[ -n "$f" ] || continue
			n="${f##*/}"
			if ! touch -r "$f" "cache/chroot/package.new/$n"; then
				printf %s\\n "$n" >"$bad"
				break
			fi
		done
	[ ! -f "$bad" ] || Fatal "failed to check chroot cache."

	while :; do
		for f in cache/chroot/{rpmdb.tar,chroot.cpio}; do
			if [ ! -s "$f" ]; then
				Verbose "missing $f archive, invalidating chroot cache"
				rebuild_chroot_cache=1
				break 2
			fi
		done

		if ! cmp -s cache/chroot/list{.new,}/init; then
			Verbose "init list changed, invalidating chroot cache"
			rebuild_chroot_cache=1
			break
		fi

		if ! cmp -s cache/chroot/list{.new,}/build; then
			Verbose "build list changed, invalidating chroot cache"
			rebuild_chroot_cache=1
			break
		fi

		rm -f "$bad"
		cat cache/chroot/list.new/{init,build} |
			while read f; do
				n="${f##*/}"
				if [ "cache/chroot/package.new/$n" -nt "cache/chroot/package/$n" -o \
				     "cache/chroot/package.new/$n" -ot "cache/chroot/package/$n" ]; then
					Verbose "package $n changed, invalidating chroot cache"
					printf %s\\n "$n" >"$bad"
					break
				fi
			done
		if [ -f "$bad" ]; then
			rebuild_chroot_cache=1
			break
		fi
		break
	done

	# Regenerate data for later cache validation.
	mv -f $verbose cache/chroot/list{.new,}/init
	mv -f $verbose cache/chroot/list{.new,}/build
	rm -f cache/chroot/package/*
	mv -f cache/chroot/package.new/* cache/chroot/package/
} # check_chroot_cache

unpack_chroot_cache()
{
	# rpmdb
	local f="cache/chroot/rpmdb.tar"
	rm -f aptbox/var/lib/rpm/*
	tar -xf "$f" -C aptbox/var/lib/rpm/ &&
		Verbose "unpacked $f" ||
		Fatal "unpack of $f failed."
		
	# chroot
	local f="cache/chroot/chroot.cpio"
	cat "$f" |wlimit_time_elapsed=300 wlimit_time_idle=300 "$chrootuid1" $number "$chroot" /.host/cpio --extract --make-directories --sparse --quiet &&
		Verbose "unpacked $f" ||
		Fatal "unpack of $f failed."
} # unpack_chroot_cache

create_chroot()
{
	copy_chroot_incoming $initlist

	local f
	for f in $initlist; do
		rpm2cpio "$f" |wlimit_time_elapsed=300 wlimit_time_idle=300 "$chrootuid1" $number "$chroot" /.host/cpio --extract --make-directories --sparse --quiet &&
			Verbose "unpacked ${f##*/}" ||
			Fatal "unpack of ${f##*/} failed."
	done
	Verbose "unpacked initial package list."

	cat >"$entry" <<__EOF__
$entry_fakeroot_header

export DURING_INSTALL=1
# WORKAROUND: mtab is missing in setup-2.2.2-alt1
touch /etc/mtab
# /WORKAROUND
# WORKAROUND: filesystem < 2.1.7-alt1 doesn't provide /sys
mkdir -p /sys
# /WORKAROUND
rm -f /etc/rpm/macros.db1
# WORKAROUND: glibc-locales is too large
echo '%_install_langs $install_langs' >>/etc/rpm/macros
# /WORKAROUND
rpmdb --initdb
__EOF__
	chmod 755 "$entry"
	Verbose "created entry point: $entry"

	wlimit_time_elapsed=60 wlimit_time_idle=60 wlimit_bytes_written=65536 \
	"$chrootuid1" $number "$chroot" /.host/entry &&
		Verbose "created RPM database." ||
		Fatal "failed to create RPM database."

	cat >"$entry" <<__EOF__
$entry_fakeroot_header

export DURING_INSTALL=1
rpmi -i $verbose $exclude_docs --justdb --nodeps $(for f in $initlist; do printf %s "\"$(quote_arg "${f##*/}")\" "; done)
__EOF__

	wlimit_time_elapsed=300 wlimit_time_idle=60 \
	"$chrootuid1" $number "$chroot" /.host/entry &&
		Verbose "installed initial package list." ||
		Fatal "failed to install initial package list."

	purge_chroot_in
	update_RPM_database --nodeps $initlist

	for f in /etc/host.conf /etc/hosts /etc/resolv.conf; do
		if [ -r "$f" -a -s "$f" ]; then
			cat >"$entry" <<__EOF__
$entry_fakeroot_header

cat >$f
__EOF__

			cat $f |wlimit_time_elapsed=60 wlimit_time_idle=60 wlimit_bytes_written=65536 \
				"$chrootuid1" $number "$chroot" /.host/entry &&
				Verbose "installed $f file." ||
				Fatal "failed to install $f file."
		fi
	done

	# At this stage, RPM inside chroot is fully functional.

	if [ "$buildlist" ]; then
		copy_chroot_incoming $buildlist

		cat >"$entry" <<__EOF__
$entry_fakeroot_header

export DURING_INSTALL=1
# WORKAROUND: dev shouldn't be installed
rpmi -i $rpm_verbose $hash $exclude_docs --nodeps $(for f in $buildlist; do f="${f##*/}"; [ -z "${f##dev[-_][0-9]*}" ] || printf %s "\"$(quote_arg "$f")\" "; done)
rpmi -i $verbose $exclude_docs --nodeps --justdb $(for f in $buildlist; do f="${f##*/}"; [ -n "${f##dev[-_][0-9]*}" ] || printf %s "\"$(quote_arg "$f")\" "; done)
# /WORKAROUND
__EOF__

		wlimit_time_elapsed=300 wlimit_time_idle=60 \
		"$chrootuid1" $number "$chroot" /.host/entry &&
			Verbose "installed build package list." ||
			Fatal "failed to install build package list."

		purge_chroot_in
		update_RPM_database $buildlist

		# First time scripts.

		cat >"$entry" <<__EOF__
$entry_fakeroot_header

ldconfig
adjust_kernel_headers
groupadd -g $gid2 builder
useradd -M -u $uid2 -g $gid2 -d /usr/src builder
chmod 1777 /usr/src
__EOF__

		wlimit_time_elapsed=60 wlimit_time_idle=60 wlimit_bytes_written=65536 \
		"$chrootuid1" $number "$chroot" /.host/entry &&
			Verbose "first time initialization complete." ||
			Fatal "first time initialization failed."
	fi # $buildlist

	archive_chroot_cache
} # create_chroot
