#!/bin/sh
set -e
. /usr/share/debconf/confmodule

# Avoid perl warnings in any of the chroot calls below
export LANG=C

DIVERTS='/usr/bin/scrollkeeper-update /usr/bin/scrollkeeper-rebuilddb /usr/bin/fc-cache /usr/sbin/update-initramfs'

log() {
	logger -t pkgsel "$@"
}

cleanup () {
	for divert in $DIVERTS; do
		rm -f "/target$divert"
		log-output -t pkgsel chroot /target dpkg-divert \
			--package pkgsel --rename --quiet --remove "$divert"
	done
}

langsupport_on_cd () {
	for l; do
		if ! [ "$(chroot /target apt-cache -n search "^language-support-$l\$")" ]; then
			return 1
		fi
	done
	return 0
}

have_networking () {
	# This is a nasty way to check whether we ought to have a network
	# connection; if we don't, it isn't worthwhile to ask whether to
	# download language support. We should really change netcfg to write
	# out a flag somewhere.
	! db_get netcfg/dhcp_options || [ "${RET#Do not configure}" = "$RET" ]
}

load_cd1() {
	if [ "$MULTICD" ]; then
		load-install-cd "/target" || true
	fi
}

# Check if we have multiple CDs listed in sources.list
MULTICD=""
if [ $(grep "^deb cdrom:" /target/etc/apt/sources.list | wc -l) -gt 1 ]; then
	MULTICD=1
fi

db_progress START 0 1000 debian-installer/pkgsel/title
db_progress INFO pkgsel/progress/init

# d-i debconf variables used by packages
debconf-copydb -p \
	"^(debian-installer/language|debian-installer/country|debian-installer/keymap|passwd/username)$" \
	configdb target_configdb

# temporarily divert programs that take a long time
for divert in $DIVERTS; do
	log-output -t pkgsel chroot /target dpkg-divert --package pkgsel \
		--rename --quiet --add "$divert"
	ln -sf /bin/true "/target$divert"
done

# get debconf-apt-progress config, which will make it run properly later
config=$(chroot /target debconf-apt-progress --config| sed "s/$/;/")

db_progress STEP 10

# Unmount the installation CD to allow CD changing; as it may be needed
# again after pkgsel, make sure it is reloaded before exiting
if [ "$MULTICD" ]; then
	log-output -t pkgsel umount /cdrom || true
fi

partsdir="/usr/lib/pre-pkgsel.d"
if [ -d "$partsdir" ]; then
	for script in `ls "$partsdir"/* 2>/dev/null`; do
		base=$(basename $script | sed 's/[0-9]*//')
		if ! db_progress INFO pkgsel/progress/$base; then
			db_subst pkgsel/progress/fallback SCRIPT "$base"
			db_progress INFO pkgsel/progress/fallback
		fi
		if [ -x "$script" ] ; then
			# be careful to preserve exit code
			if log-output -t pkgsel "$script"; then
				:
			else
				warning "$script returned error code $?"
			fi
		else
			error "Unable to execute $script"
		fi
	done
fi

# Work out what we need to install.

if db_get pkgsel/language-packs && [ "$RET" ]; then
	langpacks="$(echo "$RET" | sed 's/,//g')"
elif db_get localechooser/supported-locales && [ "$RET" ]; then
	langpacks="$(for loc in $(echo "$RET" | sed 's/,//g'); do
		echo "${loc%%_*}"
	done | sort -u)"
else
	db_get debian-installer/locale
	langpacks="${RET%%_*}"
fi

if [ -f /cdrom/.disk/base_installable ] && \
   ! langsupport_on_cd $langpacks; then
	log "language-support packages not available on CD"
	if have_networking; then
		db_capb
		db_input high pkgsel/install-language-support || true
		db_go || true
		db_capb backup
	else
		log "... but no network is available"
	fi
fi
db_get pkgsel/install-language-support
langsupport="$RET"

if [ "$langpacks" ]; then
	db_get pkgsel/language-pack-patterns
	lppatterns="$RET"
	numpacks="$(set -- $langpacks; echo $#)"
	numpatterns="$(set -- $lppatterns; echo $#)"
	if [ "$langsupport" = true ]; then
		numpatterns="$(($numpatterns + 1))"
	fi
	numlangs="$(($numpacks * $numpatterns))"
fi

# Install basic language packs, required to get localisation working at all.
# We install these almost unconditionally; if you want to get rid of even
# these, you can preseed pkgsel/language-packs to the empty string.
curlang=0
for lp in $langpacks; do
	min="$((10 + 10 * $curlang / $numpacks))"
	curlang="$(($curlang + 1))"
	max="$((10 + 10 * $curlang / $numpacks))"
	ret=0
	in-target sh -c "$config debconf-apt-progress --from $min --to $max --logstderr -- apt-get -o APT::Install-Recommends=false -q -y install 'language-pack-$lp'" || ret=$?
	if [ "$ret" != 0 ]; then
		# In case packages failed to install, try to clean up.
		in-target dpkg --configure -a || true
	fi
done

db_get pkgsel/include
if [ "$RET" ]; then
	tasksel_end=800
else
	tasksel_end=850
fi

db_progress INFO pkgsel/progress/tasksel
ret=0
in-target sh -c "$config tasksel --new-install --debconf-apt-from 20 --debconf-apt-to $tasksel_end --debconf-apt-progress='--logstderr'" || ret=$?
if [ "$ret" != 0 ]; then
	# In case packages failed to install, try to clean up.
	in-target dpkg --configure -a || true
	
	# TODO useful error message here (for ret != 30)
	db_progress INFO pkgsel/progress/cleanup
	if ! cleanup; then
		log "cleanup failed"
	fi
	db_progress STOP
	load_cd1
	exit $ret
fi

# Move final sources.list into place, if necessary, so that language packs
# and pkgsel/include items that aren't on the CD can be installed.
if [ -f /target/etc/apt/sources.list.apt-setup ]; then
	mv -f /target/etc/apt/sources.list.apt-setup \
		/target/etc/apt/sources.list
	in-target apt-get update || true
fi

db_get pkgsel/include
if [ "$RET" ]; then
	# Allow comma-separation so that this can more easily be preseeded
	# at the kernel command line.
	RET="$(printf '%s' "$RET" | sed 's/,/ /g')"
	in-target sh -c "$config debconf-apt-progress --from 800 --to 850 --logstderr -- apt-get -o APT::Install-Recommends=false -q -y install -- $RET" || ret=$?
	if [ "$ret" != 0 ]; then
		# In case packages failed to install, try to clean up.
		in-target dpkg --configure -a || true

		# TODO useful error message here (for ret != 30)
		db_progress INFO pkgsel/progress/cleanup
		if ! cleanup; then
			log "cleanup failed"
		fi
		db_progress STOP
		load_cd1
		exit $ret
	fi
fi

curlang=0
for lp in $langpacks; do
	for pattern in $lppatterns; do
		min="$((850 + 100 * $curlang / $numlangs))"
		curlang="$(($curlang + 1))"
		max="$((850 + 100 * $curlang / $numlangs))"
		pack="$(echo "$pattern" | sed "s/\\\$LL/$lp/g")"
		ret=0
		in-target sh -c "$config debconf-apt-progress --from $min --to $max --logstderr -- apt-get -o APT::Install-Recommends=false -q -y install '$pack'" || ret=$?
		if [ "$ret" != 0 ]; then
			# In case packages failed to install, try to clean up.
			in-target dpkg --configure -a || true
		fi
	done
	if [ "$langsupport" = true ]; then
		min="$((850 + 100 * $curlang / $numlangs))"
		curlang="$(($curlang + 1))"
		max="$((850 + 100 * $curlang / $numlangs))"
		ret=0
		in-target sh -c "$config debconf-apt-progress --from $min --to $max --logstderr -- apt-get -o APT::Install-Recommends=false -q -y install 'language-support-$lp'" || ret=$?
		if [ "$ret" != 0 ]; then
			# In case packages failed to install, try to clean up.
			in-target dpkg --configure -a || true
		fi
	fi
done
if [ -z "$langpacks" ]; then
	db_progress SET 950
fi

db_progress INFO pkgsel/progress/cleanup
if ! cleanup; then
	log "cleanup failed"
fi
db_progress STEP 20

# Mark any pending update notifications as seen.
if [ -d /target/var/lib/update-notifier/user.d ]; then
	mkdir -p /target/etc/update-notifier
	chroot /target find /var/lib/update-notifier/user.d/ -type f \
		-printf '%P %C@ 0\n' \
		> /target/etc/update-notifier/hooks_seen
fi

if [ -x /target/usr/bin/scrollkeeper-update ]; then
	log-output -t pkgsel chroot /target scrollkeeper-update -q || true
fi
if [ -x /target/usr/bin/fc-cache ]; then
	chroot /target fc-cache -f -v >/target/var/log/fontconfig.log 2>&1 \
		|| true
fi
if [ -x /target/usr/sbin/update-initramfs ]; then
	# get UUIDs for any devices formatted after partitioning
	update-dev

	# make UUIDs etc. available in the target system
	mount -o bind /dev /target/dev
	mount -o bind /sys /target/sys
	mount -o bind /proc /target/proc
	
	chroot /target /usr/sbin/update-initramfs -u || true
	
	umount /target/proc
	umount /target/sys
	umount /target/dev
fi

db_progress STEP 30
db_progress STOP

load_cd1
