#!/bin/bash

# rpmbased-dist-chroot.sh - builds a simple chroot from a directory of .rpms
#                           best to feed it the RPMS directory of a particular
#                           distribution. Has been tested with FC4.
# Copyright (C) 2004 Brett Parker <iDunno@sommitrealweird.co.uk>
#
# This program 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

# Default to expecting a Fedora CD mounted at /media/cdrom
# and installing bash, coreutils and yum to /mnt/temp/fedora

RPMArchives=/media/cdrom/Fedora/RPMS
InstallRoot=/mnt/temp/fedora
installpackages="filesystem basesystem coreutils yum redhat-release"

ourcachedirectory=$(mktemp -d)

architecture=$(uname -m)
export ARCH=$architecture

case $architecture in
	x86_64)
		architecture="x86_64,i686,i586,i486,i386"
		;;
	i686)
		architecture="i686,i586,i486,i386"
		;;
	i586)
		architecture="i586,i486,i386"
		;;
	i486)
		architecture="i486,i386"
		;;
esac

function displayHelp() {
cat <<END
Usage: $0 [options]

Options:
	--install-root <directorytoinstallto>
	--rpm-archives <pathtorpms>
	--install-packages <listofpackagestoinstall>
END
	exit $1
}

function startswithmm() {
	if [ "${1##--*}" == "" ]; then
		return 0
	else
		return 1
	fi
}

function containsequals() {
	if [ "${1//*=*}" == "" ]; then
		return 0
	else
		return 1
	fi
}

argcommand=""
for option in $@; do
	if ( ! startswithmm $option ); then
		if [ "x$argcommand" == "xinstall-root" ]; then
			InstallRoot=$option
		elif [ "x$argcommand" == "xrpm-archives" ]; then
			RPMArchives=$option
		elif [ "x$argcommand" == "xinstall-packages" ]; then
			if [ "x$installpackages" == "x" ]; then
				installpackages=$option
			else
				installpackages="$installpackages $option"
			fi
		fi
	else
		if ( containsequals $option ); then
			argcommand=${option%%=*}
			argcommand=${argcommand##--}
			option=${option##*=}

			if [ "x$argcommand" == "xinstall-root" ]; then
				InstallRoot=$option
			elif [ "x$argcommand" == "xrpm-archives" ]; then
				RPMArchives=$option
			elif [ "x$argcommand" == "xinstall-packages" ]; then
				installpackages=$option
			else
				echo "Unknown option $option"
				exit 1
			fi
		else
			if [ "x$option" == "x--help" ]; then
				displayHelp 0
			elif [ "x$option" == "x--install-root" ]; then
				argcommand=${option##--}
			elif [ "x$option" == "x--rpm-archives" ]; then
				argcommand=${option##--}
			elif [ "x$option" == "x--install-packages" ]; then
				argcommand=${option##--}
				installpackages=""
			else
				echo "Unknown option $option"
				exit 1
			fi
		fi
	fi
done

echo "Install Packages: $installpackages"
echo "RPMArchives     : $RPMArchives"
echo "InstallRoot     : $InstallRoot"

function buildcache() {
	cd $RPMArchives

	for arch in noarch $(echo $architecture | sed -e 's/,/\n/g'); do
		for file in *.$arch.rpm; do
			rpm -qpl $file | sed 's#^#'$file':#' >> $ourcachedirectory/files-cache
			rpm -qp --provides $file | cut -d " " -f 1 | sed 's#^#'$file':#' >> $ourcachedirectory/package-cache
		done
	done
}

function findrpm() {
	name=$1
	if [ -z $name ]; then
		return
	fi
	cd $RPMArchives

	escapename=$(echo $name | sed -e 's#\+#\\+#g; s#\.#\\.#g; s#(#\\(#g; s#)#\\)#g;')

	if [ ${name:0:1} == "/" ]; then
		grep -E "^.*:$escapename\$" $ourcachedirectory/files-cache | cut -d ":" -f 1 | head -n 1
	else
		grep -E "^.*:$escapename\$" $ourcachedirectory/package-cache | cut -d ":" -f 1 | head -n 1
	fi
}

function getdependencies() {
	filename=$1
	name=$2

	rpm -qp --requires ${RPMArchives}/$filename | grep -v '^.*('$name')' | cut -d " " -f 1 | sort | uniq | grep -Ev '^[ 	]*$' | while read line; do
		if [ ! -z $line ]; then
			fname=$(findrpm $line)
			packagename=$(getpackagename $fname)
			if [ ! -z $name ] && [ ! -z $packagename ]; then
				if [[ $firstpackage == 0 ]]; then
					if ( ! grep '^'$fname' ' $ourcachedirectory/build-packagelist > /dev/null ) && ( ! rpm -r ${InstallRoot} -qv $packagename > /dev/null ); then
						echo $fname $packagename >> $ourcachedirectory/build-packagelist
						getdependencies $fname $packagename
					fi
				else
					if ( ! grep '^'$fname' ' $ourcachedirectory/build-packagelist > /dev/null ); then
						echo $fname $packagename >> $ourcachedirectory/build-packagelist
						getdependencies $fname $packagename
					fi
				fi
			fi
		fi
	done
}

function getpackagename() {
	filename=$1
	if [ ! -z $filename ]; then
		rpm -qp --queryformat "%{NAME}\n" ${RPMArchives}/$filename
	fi
}

cd ${InstallRoot}
mkdir -p var/lib/rpm
mkdir root
mkdir etc
mkdir usr
mkdir dev
cp /etc/resolv.conf etc/
mknod -m 666 dev/null c 1 3
touch etc/fstab

buildcache

rpm -r ${InstallRoot} --initdb

firstpackage=1

for package in $installpackages; do
	
	rm -f $ourcachedirectory/build-packagelist
	touch $ourcachedirectory/build-packagelist

	echo "Installing packages required for $package"
	
	if [[ "x$(findrpm $package)" != "x" ]]; then
		
		getdependencies $(findrpm $package) $package
		echo " RPM File    :" $(findrpm $package)
		echo " Dependencies:"
		cat $ourcachedirectory/build-packagelist | cut -d ' ' -f 2 | sed -e 's#^#  #;'
		
		echo rpm -r ${InstallRoot} --ignorearch --install $(cat $ourcachedirectory/build-packagelist | cut -d ' ' -f 1) >> $ourcachedirectory/install-log

		firstpackage=0
		
		cd ${RPMArchives} && rpm -r ${InstallRoot} --ignorearch --install $(cat $ourcachedirectory/build-packagelist | cut -d ' ' -f 1)
		if ( ! grep " $package\$" $ourcachedirectory/build-packagelist > /dev/null 2>/dev/null ); then
			packages="$(findrpm $package)"
			echo rpm -r ${InstallRoot} --ignorearch --install "${packages}" >> $ourcachedirectory/install-log
			echo "${packages}" >> $ourcachedirectory/packages-installed
			cd ${RPMArchives} && rpm -r ${InstallRoot} --ignorearch --install ${packages}
		fi
	else
		echo " Failed to find the RPM providing $package - skipping"
	fi
done

read -p "Remove cache directory ($ourcachedirectory)? [Yn]: " cleanup

cleanup=${cleanup:0:1}

if [ "$cleanup" == "N" ] || [ "$cleanup" == "n" ] ; then
	echo leaving logs in $ourcachedirectory
else
	echo removing logs directory
	rm -r $ourcachedirectory
fi
