#!/bin/sh

## live-build(7) - System Build Scripts
## Copyright (C) 2006-2014 Daniel Baumann <mail@daniel-baumann.ch>
##
## This program 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
[ -e "${LIVE_BUILD}/scripts/build.sh" ] && . "${LIVE_BUILD}/scripts/build.sh" || . /usr/lib/live/build.sh

# Setting static variables
DESCRIPTION="$(Echo 'install local packages into binary')"
HELP=""
USAGE="${PROGRAM} [--force]"

Arguments "${@}"

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

Echo_message "Begin installing local package lists..."

# Requiring stage file
Require_stagefile .build/config .build/bootstrap

# Checking stage file
Check_stagefile .build/binary_package-lists

# Checking lock file
Check_lockfile .lock

# Creating lock file
Create_lockfile .lock

# The function Download_file() was copied from installer_debian-installer
# and changed to Download_file_or_quit() and Download_file_or_ignore()

# Set absolute directory for caching; we require it when we call Download_file
# from a non-standard cwd.
_LB_CACHE_DIR="$(pwd)/cache/binary_package-lists"

Download_file_2 () {
	local _LB_TARGET
	_LB_TARGET="${1}"

	local _LB_URL
	_LB_URL="${2}"

	local _LB_EXIT_ON_ERROR
	_LB_EXIT_ON_ERROR="${3}"

	_LB_CACHE_FILE="${_LB_CACHE_DIR}/$(echo "${_LB_URL}" | sed 's|/|_|g')"

	if [ ! -f "${_LB_CACHE_FILE}" ]
	then
		mkdir -p ${_LB_CACHE_DIR}
		if ! wget ${WGET_OPTIONS} -O "${_LB_CACHE_FILE}" "${_LB_URL}"
		then
			rm -f "${_LB_CACHE_FILE}"

			if [ "${_LB_EXIT_ON_ERROR}" = "true" ]; then
				Echo_error "Could not download file: %s" "${_LB_URL}"
				exit 1
			else
				Echo_warning "Could not download file: %s" "${_LB_URL}"
				return
			fi
		fi
	fi

	if [ "$(stat --printf %d "${_LB_CACHE_DIR}")" = "$(stat --printf %d ./)" ]
	then
		CP_OPTIONS="-l"
	fi

	cp -f ${CP_OPTIONS} -- "${_LB_CACHE_FILE}" "${_LB_TARGET}"
}

Download_file_or_quit() {
	local _LB_TARGET
	_LB_TARGET="${1}"

	local _LB_URL
	_LB_URL="${2}"

	Download_file_2 "${_LB_TARGET}" "${_LB_URL}" "true"
}

Download_file_or_ignore() {
	local _LB_TARGET
	_LB_TARGET="${1}"

	local _LB_URL
	_LB_URL="${2}"

	Download_file_2 "${_LB_TARGET}" "${_LB_URL}" "false"
}


case "${LB_MODE}" in
	progress-linux)
		DISTS="installer/dists"
		POOL="installer/pool"
		;;

	*)
		DISTS="dists"
		POOL="pool"
		;;
esac

if ls config/package-lists/*.list > /dev/null 2>&1 || \
   ls config/package-lists/*.list.binary > /dev/null 2>&1
then
	case "${LB_BUILD_WITH_CHROOT}" in
		true)
			# Restoring cache
			Restore_cache cache/packages.chroot

			# Check depends
			Check_package chroot/usr/bin/apt-ftparchive apt-utils
			Check_package chroot/usr/bin/grep-aptavail dctrl-tools

			# Installing depends
			Install_package
			;;

		false)
			if [ ! -e /usr/bin/apt-ftparchive ]; then
				# apt-utils
				Echo_error "/usr/bin/apt-ftparchive - no such file."
				exit 1
			fi

			if [ ! -e /usr/bin/grep-aptavail ]; then
				# dctrl-tools
				Echo_error "/usr/bin/grep-aptavail - no such file."
				exit 1
			fi
			;;
	esac

	if [ -e "${LIVE_BUILD}/share/bin/Packages" ]
	then
		cp "${LIVE_BUILD}/share/bin/Packages" chroot/bin
	else
		cp /usr/share/live/build/bin/Packages chroot/bin
	fi

	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

	for LIST in config/package-lists/*.list \
		    config/package-lists/*.list.binary
	do
		if [ -e "${LIST}" ]
		then
			# Generate package list
			Expand_packagelist "${LIST}" "config/package-lists" > chroot/root/"$(basename ${LIST})"

			# Downloading additional packages
			Chroot chroot "xargs --arg-file=/root/$(basename ${LIST}) apt-get ${APT_OPTIONS} -o Dir::Cache=/binary.deb --download-only install"

			# Remove package list
			rm chroot/root/"$(basename ${LIST})"
		fi
	done

	case "${LB_BINARY_USE_ORIGINAL_PACKAGES_LIST}" in
		false)
		# this is the default behaviour, determine the directory
		# tree based on the source package name
	for FILE in chroot/binary.deb/archives/*.deb
	do
		SOURCE="$(dpkg -f ${FILE} Source | awk '{ print $1 }')"
		SECTION="$(dpkg -f ${FILE} Section | 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

		if echo "${SECTION}" | grep -qs contrib
		then
			SECTION="contrib"
		elif echo "${SECTION}" | grep -qs non-free
		then
			SECTION="non-free"
		else
			SECTION="main"
		fi

		# Install directory
		mkdir -p binary/${POOL}/${SECTION}/"${LETTER}"/"${SOURCE}"

		# Move files
		mv "${FILE}" binary/${POOL}/${SECTION}/"${LETTER}"/"${SOURCE}"
	done
		;;

		true) # LB_BINARY_USE_ORIGINAL_PACKAGE_LIST
		# (mostly for Devuan); get Filename: information from
		# Packages file, because the pool is split between different
		# projects (DEBIAN/DEVUAN/MARILLAT)
		#
		# Using the original Packages file takes much more
		# room, but it's at least signed if you make your own
		# sub-distro.
		Echo_message "Use original Packages lists..."

		rm -f binary/tmp.packages_filenames

		mkdir -p binary/dists/${LB_DISTRIBUTION}
		cd binary/dists/${LB_DISTRIBUTION}
		# Download_file binary/dists/${LB_PARENT_DEBIAN_INSTALLER_DISTRIBUTION}/${_ARCHIVE_AREA}/binary-${LIVE_IMAGE_ARCHITECTURE}/Release "${LB_PARENT_MIRROR_CHROOT}"/dists/"${LB_PARENT_DEBIAN_INSTALLER_DISTRIBUTION}"/${_ARCHIVE_AREA}/binary-"${LIVE_IMAGE_ARCHITECTURE}"/Release
		# Fetching release
		Echo_message "Download_file_or_quit Release ${LB_MIRROR_CHROOT}/dists/${LB_DISTRIBUTION}/Release"
		Download_file_or_quit Release "${LB_MIRROR_CHROOT}"/dists/"${LB_DISTRIBUTION}"/Release
		# just download all three Packages.gz files?? TODO
		for _ARCHIVE_AREA in main contrib non-free; do
			rm -f tmp.Packages.gz
			Echo_message "Download_file_or_ignore tmp.Packages.gz ${LB_MIRROR_CHROOT}/dists/${LB_DISTRIBUTION}/${_ARCHIVE_AREA}/binary-${LIVE_IMAGE_ARCHITECTURE}/Packages.gz"
			Download_file_or_ignore tmp.Packages.gz "${LB_MIRROR_CHROOT}"/dists/"${LB_DISTRIBUTION}"/${_ARCHIVE_AREA}/binary-"${LIVE_IMAGE_ARCHITECTURE}"/Packages.gz
			if [ -f tmp.Packages.gz ]; then
				zcat tmp.Packages.gz |grep '^[Ff]ilename:' | awk '{print $2}' |sort >> ${OLDPWD}/binary/tmp.packages_filenames
				mkdir -p ${_ARCHIVE_AREA}/binary-${LIVE_IMAGE_ARCHITECTURE}/
				mv tmp.Packages.gz $_ARCHIVE_AREA/binary-${LIVE_IMAGE_ARCHITECTURE}/Packages.gz
			fi
		done # _ARCHIVE_AREA
		Echo_message "DBG: All downloaded. now placing the .debs."


		cd ${OLDPWD}

        Echo_message "moving chroot/binary.deb/archives .debs"

	# TODO with a for-loop is dead slow now with all the grepping
	for FILE in chroot/binary.deb/archives/*.deb
	do
		BASEFILE=$( basename "$FILE" )

		# The files in the pool directory can occur in many
		# different distros, so they have "normal" Debian package
		# versions.

		# But the downloaded ones may have an additional "epoch"
		# identifier that looks like <number>: pre-pended to
		# the actual version number. And then it's also URL-encoded,
		# of course, in case anyone wants to download it on VAX/VMS.
		# (debian-policy paragraph 5.6.12 Version. I made that up
		# about VAX/VMS :-) )
		EPOCHLESSFILE=$( echo "$BASEFILE" | sed -e 's/_[0-9][0-9]*%3a/_/;' )
		FOUND=$( grep '/'"$EPOCHLESSFILE"'$' binary/tmp.packages_filenames )
		if [ "$FOUND" = "" ]; then
			Echo_error "$FILE not found in Packages.gz"
		else
			PUTITHERE=$( dirname $FOUND )
#DBG#			Echo "DBG place $FILE in $PUTITHERE/$EPOCHLESSFILE"
			mkdir -p binary/$PUTITHERE
			mv $FILE binary/$PUTITHERE/$EPOCHLESSFILE
		fi
	done
        Echo_message "copying chroot/packages.bootstrap/ .debs"

	# TODO with a for-loop is dead slow now with all the grepping
	for FILE in cache/packages.bootstrap/*.deb
	do
		BASEFILE=$( basename "$FILE" )

		# The files in the pool directory can occur in many
		# different distros, so they have "normal" Debian package
		# versions.

		# But the downloaded ones may have an additional "epoch"
		# identifier that looks like <number>: pre-pended to
		# the actual version number. And then it's also URL-encoded,
		# of course, in case anyone wants to download it on VAX/VMS.
		# (debian-policy paragraph 5.6.12 Version. I made that up
		# about VAX/VMS :-) )
		EPOCHLESSFILE=$( echo "$BASEFILE" | sed -e 's/_[0-9][0-9]*%3a/_/;' )
		FOUND=$( grep '/'"$EPOCHLESSFILE"'$' binary/tmp.packages_filenames )
		if [ "$FOUND" = "" ]; then
			Echo_error "bootstrap $FILE not found in Packages.gz"
		else
			PUTITHERE=$( dirname $FOUND )
#DBG#			Echo "DBG place $FILE in $PUTITHERE/$EPOCHLESSFILE"
			mkdir -p binary/$PUTITHERE
			cp -p $FILE binary/$PUTITHERE/$EPOCHLESSFILE
		fi
	done

	Echo_message "binary_package-lists: all done"

		;;
	esac # LB_BINARY_USE_ORIGINAL_PACKAGE_LIST

	if [ "${LB_BINARY_USE_ORIGINAL_PACKAGE_LIST}" = "false" ]; then
		cd binary

		for SECTION in ${POOL}/*
		do
			SECTION="$(basename ${SECTION})"

			mkdir -p ${DISTS}/${LB_PARENT_DISTRIBUTION}/${SECTION}/binary-${LIVE_IMAGE_ARCHITECTURE}
			apt-ftparchive packages ${POOL}/${SECTION} > ${DISTS}/${LB_PARENT_DISTRIBUTION}/${SECTION}/binary-${LIVE_IMAGE_ARCHITECTURE}/Packages
			gzip -9 -c ${DISTS}/${LB_PARENT_DISTRIBUTION}/${SECTION}/binary-${LIVE_IMAGE_ARCHITECTURE}/Packages > ${DISTS}/${LB_PARENT_DISTRIBUTION}/${SECTION}/binary-${LIVE_IMAGE_ARCHITECTURE}/Packages.gz
		done

		cd "${OLDPWD}"
	fi # LB_BINARY_USE_ORIGINAL_PACKAGE_LIST

	rm -f chroot/bin/Packages

	rm -rf chroot/binary.deb
	mv chroot/var/lib/dpkg/status.tmp chroot/var/lib/dpkg/status

	case "${LB_BUILD_WITH_CHROOT}" in
		true)
			# Removing depends
			Remove_package

			# Saving cache
			Save_cache cache/packages.chroot
			;;
	esac

	# Creating stage file
	Create_stagefile .build/binary_package-lists
fi
