#!/bin/sh

# lh_binary_debian-installer(1) - install debian-installer into binary
# Copyright (C) 2006-2008 Daniel Baumann <daniel@debian.org>
#
# live-helper comes with ABSOLUTELY NO WARRANTY; for details see COPYING.
# This is free software, and you are welcome to redistribute it
# under certain conditions; see COPYING for details.

set -e

# Including common functions
LH_BASE="${LH_BASE:-/usr/share/live-helper}"

for FUNCTION in "${LH_BASE}"/functions/*.sh
do
	. "${FUNCTION}"
done

# Setting static variables
DESCRIPTION="install debian-installer into binary"
HELP=""
USAGE="${PROGRAM} [--force]"

Arguments "${@}"

# Reading configuration files
Read_conffile config/all config/common config/bootstrap config/chroot config/binary config/source
Set_defaults

if [ "${LH_QUIET}" = "enabled" ]
then
	WGET_OPTIONS="${WGET_OPTIONS} --quiet"
fi

# Check d-i configuration
case "${LH_DEBIAN_INSTALLER}" in
	enabled|cdrom|netinst|netboot|businesscard)
		;;

	disabled)
		exit 0
		;;

	live)
		case "${LH_PACKAGES_LISTS}" in
			stripped|minimal)
				Echo_error "live d-i installation is incompatbile with stripped and minimal"
				exit 1
			;;
		esac
		;;

	*)
		Echo_error "debian-installer flavour ${LH_DEBIAN_INSTALLER} not supported."
		exit 1
		;;
esac

Echo_message "Begin installing debian-installer..."

# Requiring stage file
Require_stagefile .stage/bootstrap

# Checking stage file
Check_stagefile .stage/binary_debian-installer

# Checking lock file
Check_lockfile .lock

# Creating lock file
Create_lockfile .lock

# Checking depends
Check_package chroot/usr/bin/wget wget
Check_package chroot/usr/bin/apt-ftparchive apt-utils

# Restoring cache
Restore_cache cache/packages_binary

# Installing depends
Install_package

# Setting destination directory
case "${LH_BINARY_IMAGES}" in
	iso)
		DESTDIR="binary/install"
		;;

	net)
		DESTDIR="tftpboot/debian-install/${LH_ARCHITECTURE}"
		;;

	tar|usb-hdd)
		DESTDIR="binary/install"

		# Workaround for syslinux (<< 3.36) which doesn't support long file/path names
		if [ "${LH_DISTRIBUTION}" = "etch" ] && [ "${LH_BOOTLOADER}" = "syslinux" ]
		then
			DESTDIR="binary"
		fi
		;;
esac

# Set d-i image type
case "${LH_DEBIAN_INSTALLER}" in
	businesscard|netboot|netinst)
		DI_IMAGE_TYPE="netboot"
		;;
	*)
		case "${LH_BINARY_IMAGES}" in
			iso)
				DI_IMAGE_TYPE="cdrom"
				;;

			*)
				DI_IMAGE_TYPE="netboot"
				;;
		esac
		;;
esac

case "${DI_IMAGE_TYPE}" in
	netboot)
		DI_REMOTE_BASE="netboot/debian-installer/${LH_ARCHITECTURE}"
		DI_REMOTE_BASE_GTK="netboot/gtk/debian-installer/${LH_ARCHITECTURE}"
		DI_REMOTE_KERNEL="linux"
		;;
	cdrom)
		DI_REMOTE_BASE="cdrom"
		DI_REMOTE_BASE_GTK="cdrom/gtk"
		DI_REMOTE_KERNEL="vmlinuz"
		;;
esac

case "${LH_ARCHITECTURE}" in
	powerpc)
		DI_REMOTE_BASE="${LH_ARCHITECTURE}/${DI_REMOTE_BASE}"
		;;
esac

Check_multiarchitecture

Install_file() {
	local FILE
	FILE="${1}"

	local TARGET
	TARGET="${2}"

	SOURCE="$(dpkg -f ${FILE} Source | awk '{ print $1 }')"

	if [ -z "${SOURCE}" ]
	then
		SOURCE="$(basename ${FILE} | awk -F_ '{ print $1 }')"
	fi

	case "${SOURCE}" in
		lib?*)
			LETTER="$(echo ${SOURCE} | sed 's|\(....\).*|\1|')"
			;;

		*)
			LETTER="$(echo ${SOURCE} | sed 's|\(.\).*|\1|')"
			;;
	esac

	# Install directory
	mkdir -p "${TARGET}"/"${LETTER}"/"${SOURCE}"

	# Move files
	cp "${FILE}" "${TARGET}"/"${LETTER}"/"${SOURCE}"
}

VMLINUZ_DI="vmlinuz"
INITRD_DI="initrd.gz"
DESTDIR_DI="${DESTDIR}"

VMLINUZ_GI="gtk/vmlinuz"
INITRD_GI="gtk/initrd.gz"
DESTDIR_GI="${DESTDIR}/gtk"

# Workaround for syslinux (<< 3.36) which doesn't support long file/path names
if [ "${LH_DISTRIBUTION}" = "etch" ]
then
	case "${LH_BINARY_IMAGES}" in
		usb-hdd|tar)
			VMLINUZ_DI="vmlinuz.di"
			INITRD_DI="initrddi.gz"
			DESTDIR_DI="${DESTDIR}"

			VMLINUZ_GI="vmlinuz.gi"
			INITRD_GI="initrdgi.gz"
			DESTDIR_GI="${DESTDIR}"
			;;
	esac
fi

if [ "${LH_DEBIAN_INSTALLER_DAILY}" = "enabled" ]
then
	# Debian Installer daily builds
	case "${LH_ARCHITECTURE}" in
		alpha)
			URL="http://people.debian.org/~vorlon/d-i/alpha/daily/"
			;;

		amd64)
			URL="http://people.debian.org/~aba/d-i/images/daily/"
			;;

		arm)
			URL="http://people.debian.org/~kmuto/d-i/images/daily/"
			;;

		hppa)
			URL="http://people.debian.org/~kyle/d-i/hppa/daily/"
			;;

		i386)
			URL="http://people.debian.org/~joeyh/d-i/images/daily/"
			;;

		ia64)
			URL="http://people.debian.org/~dannf/d-i/images/daily/"
			;;

		m68k)
			URL="http://people.debian.org/~smarenka/d-i/images-m68k/daily/"
			;;

		mips)
			URL="http://people.debian.org/~ths/d-i/mips/images/daily/"
			;;

		mipsel)
			URL="http://people.debian.org/~ths/d-i/mipsel/images/daily/"
			;;

		powerpc)
			URL="http://people.debian.org/~wouter/d-i/powerpc/daily/"
			;;

		s390)
			URL="http://lophos.multibuild.org/d-i/images/daily/"
			;;

		sparc)
			URL="http://people.debian.org/~stappers/d-i/images/daily/"
			;;

		*)
			Echo_error "No daily-builds found for your architecture."
			exit 1
			;;
	esac
else
	URL="${LH_MIRROR_CHROOT}/dists/${LH_DISTRIBUTION}/main/installer-${LH_ARCHITECTURE}/current/images/"
fi

# Downloading debian-installer
mkdir -p "${DESTDIR_DI}"
wget ${WGET_OPTIONS} -O "${DESTDIR}"/"${VMLINUZ_DI}" ${URL}/${DI_REMOTE_BASE}/${DI_REMOTE_KERNEL}
wget ${WGET_OPTIONS} -O "${DESTDIR}"/"${INITRD_DI}" ${URL}/${DI_REMOTE_BASE}/initrd.gz

# Downloading graphical-installer
case "${LH_ARCHITECTURE}" in
	amd64|i386|powerpc)
		mkdir -p "${DESTDIR_GI}"
		wget ${WGET_OPTIONS} -O "${DESTDIR}"/"${VMLINUZ_GI}" ${URL}/${DI_REMOTE_BASE_GTK}/${DI_REMOTE_KERNEL}
		wget ${WGET_OPTIONS} -O "${DESTDIR}"/"${INITRD_GI}" ${URL}/${DI_REMOTE_BASE_GTK}/initrd.gz
	;;
esac

# Only download additional packages if appropriate
if [ "${DI_IMAGE_TYPE}" != "netboot" ]
then
	# Downloading additional packages
	mkdir -p chroot/binary.deb/archives/partial
	mv chroot/var/lib/dpkg/status chroot/var/lib/dpkg/status.tmp
	touch chroot/var/lib/dpkg/status

	case "${LH_ARCHITECTURE}" in
		amd64)
			DI_PACKAGES="linux-image-2.6-amd64 lilo grub"
			;;

		i386)
			DI_PACKAGES="linux-image-2.6-486 linux-image-2.6-686 elilo lilo grub"
			;;

		powerpc)
			DI_PACKAGES="linux-image-2.6-powerpc linux-image-2.6-powerpc64 linux-image-2.6-powerpc-smp linux-image-2.6-prep yaboot" # FIXME bootloader?
			;;
	esac

	DI_PACKAGES="${DI_PACKAGES} cryptsetup lvm2"

	Chroot "apt-get ${APT_OPTIONS} -o Dir::Cache=/binary.deb --download-only install ${DI_PACKAGES}"
	mv chroot/binary.deb ./
	mv chroot/var/lib/dpkg/status.tmp chroot/var/lib/dpkg/status

	if ls binary.deb/archives/*.deb > /dev/null 2>&1
	then
		for FILE in binary.deb/archives/*.deb
		do
			Install_file "${FILE}" "binary/pool/main"
		done
	fi

	# Including base debian packages
	if [ -d cache/packages_bootstrap ]
	then
		for FILE in cache/packages_bootstrap/*.deb
		do
			Install_file "${FILE}" "binary/pool/main"
		done
	else
		Echo_error "E: Could not find cache/packages_bootstrap"
		exit 1
	fi

	# Including local debs
	if ls ../config/binary_local-debs/*_"${LH_ARCHITECTURE}".deb > /dev/null 2>&1
	then
		for FILE in ../config/binary_local-debs/*_"${LH_ARCHITECTURE}".deb
		do
			Install_file "${FILE}" "binary/pool/main"
		done
	fi

	if ls ../config/binary_local-debs/*_all.deb > /dev/null 2>&1
	then
		for FILE in ../config/binary_local-debs/*_all.deb
		do
			Install_file "${FILE}" "binary/pool/main"
		done
	fi

	# Generating deb indices
	mkdir -p binary/dists/${LH_DISTRIBUTION}/main/binary-${LH_ARCHITECTURE}

	cd binary
	apt-ftparchive packages pool/main > dists/${LH_DISTRIBUTION}/main/binary-${LH_ARCHITECTURE}/Packages
	gzip -9 -c dists/${LH_DISTRIBUTION}/main/binary-${LH_ARCHITECTURE}/Packages > dists/${LH_DISTRIBUTION}/main/binary-${LH_ARCHITECTURE}/Packages.gz
	cd "${OLDPWD}"

	# Fetching release
	wget ${WGET_OPTIONS} "${LH_MIRROR_CHROOT}"/dists/"${LH_DISTRIBUTION}"/main/binary-"${LH_ARCHITECTURE}"/Release -O binary/dists/${LH_DISTRIBUTION}/main/binary-${LH_ARCHITECTURE}/Release

	mkdir binary.udeb
	cd binary.udeb

	# Downloading udeb indices
	wget ${WGET_OPTIONS} "${LH_MIRROR_CHROOT}"/dists/"${LH_DISTRIBUTION}"/main/debian-installer/binary-"${LH_ARCHITECTURE}"/Packages.gz
	gunzip -c Packages.gz > Packages

	# Sorting udebs
	UDEBS="$(awk '/Filename: / { print $2 }' Packages)"

	# Downloading udebs
	for UDEB in ${UDEBS}
	do
		if [ -f ../cache/packages_debian-installer.udeb/"$(basename ${UDEB})" ]
		then
			# Copying cached udebs
			cp ../cache/packages_debian-installer.udeb/"$(basename ${UDEB})" ./
		else
			# Downloading udebs
			wget ${WGET_OPTIONS} "${LH_MIRROR_CHROOT}"/${UDEB}
		fi
	done

	# Caching udebs
	rm -rf ../cache/packages_debian-installer.udeb
	mkdir -p ../cache/packages_debian-installer.udeb
	cp *.udeb ../cache/packages_debian-installer.udeb

	# Including local udebs
	if ls ../config/binary_local-udebs/*_"${LH_ARCHITECTURE}".udeb > /dev/null 2>&1
	then
		for FILE in ../config/binary_local-udebs/*_"${LH_ARCHITECTURE}".udeb
		do
			Install_file "${FILE}" "pool/main"

			# Prefer local udebs over downloaded udebs
			rm -f "$(basename ${FILE} | awk -F_ '{ print $1 }')"_*.udeb
		done
	fi

	if ls ../config/binary_local-udebs/*_all.udeb > /dev/null 2>&1
	then
		for FILE in ../config/binary_local-udebs/*_all.udeb
		do
			Install_file "${FILE}" "pool/main"

			# Prefer local udebs over downloaded udebs
			rm -f "$(basename ${FILE} | awk -F_ '{ print $1 }')"_*.udeb
		done
	fi

	# Excluding udebs
	grep -v "^#" "${LH_BASE}"/data/debian-cd/"${LH_DISTRIBUTION}"/udeb_exclude > exclude
	grep -v "^#" "${LH_BASE}"/data/debian-cd/"${LH_DISTRIBUTION}"/exclude-udebs >> exclude
	grep -v "^#" "${LH_BASE}"/data/debian-cd/"${LH_DISTRIBUTION}"/exclude-udebs-${LH_ARCHITECTURE} >> exclude

	# Local exclude file
	if [ -e ../config/binary_debian-installer/udeb_exclude ]
	then
		cat ../config/binary_debian-installer/udeb_exclude >> exclude
	fi

	for EXCLUDE in $(cat exclude)
	do
		if [ "${LH_DEBIAN_INSTALLER}" = "live" ] && [ "${EXCLUDE}" = "live-installer" ]
		then
			continue
		fi

		rm -f "${EXCLUDE}"_*.udeb
	done

	# Enable live-installer
	if [ "${LH_DEBIAN_INSTALLER}" = "live" ]
	then
		# Remove local udebs
		rm -f pool/main/b/base-installer/bootstrap-base_*.udeb

		# Remove d-i udebs
		rm -f bootstrap-base_*.udeb
	fi

	# Moving udebs
	for UDEB in ${UDEBS}
	do
		if [ -f "$(basename ${UDEB})" ]
		then
			mkdir -p $(dirname ${UDEB})
			mv "$(basename ${UDEB})" "$(dirname ${UDEB})"
		fi
	done

	# Creating udeb indices
	mkdir -p dists/"${LH_DISTRIBUTION}"/main/debian-installer/binary-"${LH_ARCHITECTURE}"
	apt-ftparchive packages pool/main > dists/"${LH_DISTRIBUTION}"/main/debian-installer/binary-"${LH_ARCHITECTURE}"/Packages
	gzip -9 -c dists/${LH_DISTRIBUTION}/main/debian-installer/binary-${LH_ARCHITECTURE}/Packages > dists/${LH_DISTRIBUTION}/main/debian-installer/binary-${LH_ARCHITECTURE}/Packages.gz

	rm -f Packages* exclude
	find . | cpio -dmpu "${OLDPWD}"/binary
	cd "${OLDPWD}"

	rm -rf binary.udeb
	rm -rf binary.deb

	# Generating release file
	apt-ftparchive \
		-o APT::FTPArchive::Release::Origin="Debian" \
		-o APT::FTPArchive::Release::Label="Debian" \
		-o APT::FTPArchive::Release::Suite="${LH_DISTRIBUTION}" \
		-o APT::FTPArchive::Release::Version="4.0" \
		-o APT::FTPArchive::Release::Codename="${LH_DISTRIBUTION}" \
		-o APT::FTPArchive::Release::Date="$(date -R)" \
		-o APT::FTPArchive::Release::Architectures="${LH_ARCHITECTURE}" \
		-o APT::FTPArchive::Release::Components="main" \
		-o APT::FTPArchive::Release::Description="Last updated: $(date -R)" \
	release binary/dists/${LH_DISTRIBUTION} > binary/dists/${LH_DISTRIBUTION}/Release

	# Creating dist symlinks
	for DISTRIBUTION in frozen stable testing unstable
	do
		ln -s ${LH_DISTRIBUTION} binary/dists/${DISTRIBUTION}
	done

	if [ "${LH_BINARY_IMAGES}" != "usb-hdd" ]
	then
		ln -s . binary/debian
	fi

	# Including preseeding files
	if ls config/binary_debian_installer/preseed*.cfg > /dev/null 2>&1
	then
		cp config/binary_debian-installer/preseed*.cfg binary/install
	fi
fi

Repack_initrd()
{
	local TARGET_INITRD
	TARGET_INITRD="${1}"
	REPACK_TMPDIR="unpacked-initrd"

	# cpio does not have a "extract to directory", so we must change directory
	mkdir -p ${REPACK_TMPDIR}
	cd ${REPACK_TMPDIR}

	gzip -d < ../${TARGET_INITRD} | cpio -i --make-directories --no-absolute-filenames
	cp ../config/binary_debian-installer/preseed.cfg .
	find | cpio -H newc -o | gzip -9 > ../${TARGET_INITRD}

	cd ..
	rm -rf ${REPACK_TMPDIR}
}

# Preseed d-i by repacking the initrd in certain situations
if [ "${DI_IMAGE_TYPE}" = "netboot" ] && [ -e config/binary_debian-installer/preseed.cfg ]
then
	Repack_initrd "${DESTDIR}"/"${INITRD_DI}"

	if [ -e "${DESTDIR}"/"${INITRD_GI}" ]
	then
		Repack_initrd "${DESTDIR}"/"${INITRD_GI}"
	fi
fi

# Saving cache
Save_cache cache/packages_binary

# Removing depends
Remove_package

# Creating stage file
Create_stagefile .stage/binary_debian-installer