#!/bin/sh
#
# Sat - SliTaz ARM Tool
#
# Copyright (C) 2012-2014 SliTaz ARM - BSD License
# Author: Christophe Lincoln <pankso@slitaz.org>
#
. /lib/libtaz.sh
#. /usr/lib/slitaz/libpkg.sh
. /etc/slitaz/slitaz.conf

# Internal variables: libtaz.sh set: --work= --init=
[ "$work" ] || work="$(pwd)"
[ "$init" ] || init="gz"
initramfs="slitaz-arm.$init"
packages="$work/packages"
distro="$work/distro"
flavors="$work/flavors"
rootfs="$distro/rootfs"
cache="$distro/cache"

# http://mirror.slitaz.org/packages/cooking/arm/
mirror="http://cook.slitaz.org/cross/arm/packages/"

#
# Functions
#

# Help and usage
usage() {
	cat << EOT

$(boldify "Usage:") $(basename $0) [command|--options]

SliTaz ARM Tool - http://arm.slitaz.org

$(boldify "Commands:")
  gen        Generate a distro cpio/gzip initramfs
  flavors    List and give info about flavors
  ckpkgs     Distro packages dependencies check
  clean      Clean up the work directory
  emu        Emulate the distro with qemu-system-arm
  mirror     Download or sync the SliTaz ARM mirror

$(boldify "Options:")
  --kmap     Include the system keymap config in the distro
  --spk      Clean or include Spk package manager in the distro
  --noinit   Don't create the compressed initramfs
  --work=    Path to work dir with packages and rootfs
  --size=    Specify optional vdisk size (default 50Mb)
  --init=    Specify the initramfs compression: gz bz2 xz
  --flavor=  Generate specific SliTaz ARM flavor
  --append=  SliTaz and Kernel bootime arguments for Qemu
  --debug    Keep cache dir and display debugging info

EOT
}

error() {
	echo "[ $(colorize 31 'ERROR') ] $@"
}

# --> use libpkg.sh when released (function is shared with spk)
# Check mirror ID: return 1 if no changes or mirror unreachable
check_mirror_id() {
	[ "$forced" ] && rm -f ID
	[ -f "ID" ] || echo $$ > ID
	mv ID ID.bak
	if busybox wget -qs ${mirror%/}/ID 2>/dev/null; then
		busybox wget -q ${mirror%/}/ID
	else
		echo "Mirror is unreachable"; newline
		return 1
	fi
	if [ "$(cat ID)" == "$(cat ID.bak)" ]; then
		echo "Mirror is up-to-date"; newline
		return 1
	fi
}

#
# Commands
#

case "$1" in
	gen)
		time=$(date +%s)
		check_root
		newline && boldify "Generating SliTaz ARM distro"
		separator
		rm -rf ${distro} && mkdir -p ${rootfs} ${cache}
		
		# We need a valid flavor
		if [ "$flavor" ] && [ ! -f "$flavors/$flavor/packages.list" ]; then
			error "Missing '$flavor' flavor packages.list" 
			newline && exit 1
		fi
		
		# Get --flavor= packages lists
		if [ "$flavor" ]; then
			echo -n "Getting $flavor packages.list..."
			cp -f $flavors/$flavor/packages.list ${cache} 2>/dev/null &&
			cp -f $flavors/$flavor/flavor.conf ${cache} 2>/dev/null
			status
		fi

		# Packages
		rm -f ${cache}/packages.full
		if [ -f "${cache}/packages.list" ]; then
			for pkg in $(cat ${cache}/packages.list)
			do
				IFS="|"
				grep "^$pkg |" $work/mirror/packages.desc | while read pkg version desc
				do
					echo ${pkg}-${version}-arm.tazpkg | sed s'/ //'g \
						>> ${cache}/packages.full
				done
				unset IFS
			done
			cd ${work}/mirror
		else
			if [ ! -d "$packages" ]; then
				echo "Missing distro/packages.list or packages/ directory"
				echo "" && exit 1
			fi
			echo -n "Using packages directory..."
			cd $packages && ls -1 >${cache}/packages.full
			status
		fi
		
		# Deps install is not well handled by tazpkg/spk actually.
		# So simply install all packages and don't resolve deps.
		for pkg in $(cat ${cache}/packages.full)
		do
			pkgdir=$(basename $pkg .tazpkg)
			db=${rootfs}/var/lib/tazpkg
			echo -n "Installing: $(basename $pkg)"
			tazpkg extract $pkg >/dev/null
			. $pkgdir/receipt
			mkdir -p $db/installed/$PACKAGE
			cp $pkgdir/receipt $pkgdir/files.list \
				$db/installed/$PACKAGE
			cp -a $pkgdir/fs/* $distro/rootfs && rm -rf $pkgdir
			md5sum $(basename $pkg) >> $db/installed.md5
			status
		done

		# Install spk Hg if requested. Spk multiarch support must be tested
		if [ "$spk" ]; then
			hg=http://hg.slitaz.org
			echo -n "Installing: spk ($hg)"
			cd $work
			[ -d "spk" ] || hg clone $hg/spk >/dev/null 2>/dev/null
			cd $work/spk
			[ "$noup" ] || hg pull -u >/dev/null
			make DESTDIR=${rootfs} install >/dev/null
			status
		fi

		# SLITAZ_ARCH
		if [ -f "${rootfs}/etc/slitaz/slitaz.conf" ]; then
			echo -n "Setting SliTaz arch to: arm"
			sed -i s"/SLITAZ_ARCH=.*/SLITAZ_ARCH=\"arm\"/" \
				${rootfs}/etc/slitaz/slitaz.conf
			status
		else
			echo -n "Missing distro: /etc/slitaz/slitaz.conf"; false
			status && exit 1
		fi

		# Mirror
		echo "$mirror" > ${rootfs}/var/lib/tazpkg/mirror

		# /init & /var/run
		cd ${rootfs}
		rm init var/run && ln -s /bin/busybox init
		mkdir -p run var/run

		# Update modules.dep
		if [ -f "var/lib/tazpkg/installed/linux/receipt" ]; then
			. var/lib/tazpkg/installed/linux/receipt
			depmod -b . ${VERSION}-slitaz
		fi
		
		# CGI Admin
		if [ -d "$work/cgi-adm" ]; then
			echo -n "Installing SliTaz ARM CGI Admin interface..."
			mkdir -p ${rootfs}/var/www/adm
			cp -a ${work}/cgi-adm/* ${rootfs}/var/www/adm
			status
		fi

		# Custom rootfs: make sure all files belong to root
		if [ -d "$work/rootfs" ]; then
			size=$(du -sh $work/rootfs | awk '{print $1}')
			echo -n "Copying custom ARM rootfs: $size"
			tmp=$distro/tmp-$$
			mkdir -p $tmp
			cp -r $work/rootfs/* $tmp
			chown -R root.root $tmp
			cp -a $tmp/* ${rootfs} && rm -rf $tmp
			status
		fi
		
		# Custom flavor rootfs
		if [ -f "${cache}/flavor.conf" ]; then
			. ${cache}/flavor.conf
		fi
		if [ -d "$flavors/${FLAVOR}/rootfs" ]; then
			size=$(du -sh $flavors/${FLAVOR}/rootfs | awk '{print $1}')
			echo -n "Copying ${FLAVOR} ARM rootfs: $size"
			tmp=$distro/tmp-$$
			mkdir -p $tmp
			cp -r $flavors/${FLAVOR}/rootfs/* $tmp
			chown -R root.root $tmp
			cp -a $tmp/* ${rootfs} && rm -rf $tmp
			status
		fi
		
		# --kmap
		if [ "$kmap" ]; then
			echo -n "Copying local: /etc/keymap.conf"
			cp -f /etc/keymap.conf ${rootfs}/etc
			status
		fi
		
		# Distro: /etc/slitaz/flavor.conf
		if [ -f "${cache}/flavor.conf" ]; then
			echo -n "Including $FLAVOR: flavor.conf"
			echo "BUILD_DATE=\"$(date '+%Y%m%d')\"" >> ${cache}/flavor.conf
			cp -f ${cache}/flavor.conf ${rootfs}/etc/slitaz
			status
		fi
		
		# Move /boot outside the rootfs
		mkdir -p ${rootfs}/boot
		if [ "$(ls $rootfs/boot | wc -l)" != 0 ]; then
			echo -n "Moving /boot outside the rootfs..."
			mkdir -p ${distro}/boot
			mv -f ${rootfs}/boot/* ${distro}/boot
			status
			
			# ! wok/linux pkg must be modified to install /boot/kernel.img
			if ls ${distro}/boot/linux-* >/dev/null 2>/dev/null; then
				mv ${distro}/boot/linux-* ${distro}/boot/kernel.img
				chmod -x ${distro}/boot/kernel.img
			fi
			
		fi

		# Rootfs cpio: gzip xz --> /usr/lib/slitaz/liblive.sh ???
		if [ ! "$noinit" ]; then
			echo -n "Compressing initramfs: $initramfs"
			case "$initramfs" in
				*.bz2) find . | cpio -o -H newc | bzip2 > ../$initramfs ;;
				*.gz) find . | cpio -o -H newc | gzip -9 > ../$initramfs ;;
				*.xz) find . | cpio -o -H newc | xz -9 --format=lzma > ../$initramfs ;;
			esac
			status
		fi
		
		# Clean if no debug mode
		[ "$debug" ] || rm -rf ${cache}
		
		# Summary
		time=$(($(date +%s) - $time))
		rootfs_size="$(du -sh ${rootfs} | awk '{print $1}')"
		pkgs_count="$(ls $db/installed | wc -l)"
		[ "$noinit" ] || \
			initramfs_size="$(du -sh $distro/$initramfs | awk '{print $1}')"
		separator && newline
		boldify "SliTaz ARM distro summary"
		separator
		[ "$FLAVOR" ] && echo "Flavor name    : $FLAVOR"
		echo "Build time     : ${time}s"
		[ "$noinit" ] || echo "Initramfs      : $initramfs"
		[ "$noinit" ] || echo "Initramfs size : $initramfs_size"
		echo "Rootfs size    : $rootfs_size" 
		echo "Packages       : $pkgs_count"
		separator
		[ "$rpi" ] || newline ;;
		
	flavors)
		newline
		echo -n "$(boldify 'Flavor')" && 
		echo -n "$(indent 12 $(boldify 'Packages'))"
		indent 24 $(boldify 'Description')
		separator
		for flavor in $(ls $flavors)
		do
			. $flavors/$flavor/flavor.conf
			pkgs=$(cat $flavors/$flavor/packages.list | wc -l)
			echo -n "$flavor" && 
			echo -n "$(indent 12 $pkgs)" && indent 24 "$SHORT_DESC"
			unset SHORT_DESC
		done
		newline ;;
	
	ckpkgs)
		installed="${rootfs}/var/lib/tazpkg/installed"
		SLITAZ_ARCH="arm"
		count=0
		if [ ! -d "$installed" ]; then
			echo "Missing distro rootfs" && exit 1
		fi
		echo ""
		echo -n "$(boldify 'Package name')"
		indent 24 "$(boldify 'Missing dependencies')"
		separator
		for pkg in ${installed}/*
		do
			. $pkg/receipt
			for dep in $DEPENDS
			do
				if [ ! -d "${installed}/$dep" ]; then
					if [ ! "$raw" ]; then
						echo -n "$(colorize 34 $PACKAGE)" && indent 24 "$dep"
					else
						echo "$dep"
					fi
					count=$(($count + 1))
				fi
			done
			unset DEPENDS
		done
		if [ "$count" == 0 ]; then
			echo "No missing dependencies" 
		fi
		separator
		echo -n "Installed packages: "; colorize 32 $(ls $installed | wc -l)
		newline ;;
	
	clean)
		check_root
		echo -n "Cleaning: distro"
		rm -rf $distro && status
		if [ "$spk" ]; then
			echo -n "Cleaning: spk"
			rm -rf $work/spk && status
		fi ;;
	
	emu)
		cd $work
		[ -f "vdisk.img" ] && opts="-hda vdisk.img"
		[ "$append" ] && append="-append ${append}"
		qemu-system-arm -m 256 ${opts} \
			-M versatilepb -cpu arm1176 \
			-kernel ${distro}/boot/kernel.img \
			-initrd ${distro}/${initramfs} ${append} ;;
	
	mirror)
		#
		# --> spk-mirror $mirror --sync --dest=/path ???
		#
		count=0
		newline && boldify "Syncing SliTaz ARM mirror"
		separator
		mkdir -p $work/mirror && cd $work/mirror
		
		echo -n "URL: " && colorize 34 "$mirror"
		if ! check_mirror_id; then
			exit 0
		fi
		for list in packages.list packages.desc packages.md5; do
			echo -n "Fetching: $list"
			rm -f $list && wget -q ${mirror%/}/$list
			status
		done
		echo -n "Checking packages $SUM..."
		for pkg in $(cat $work/mirror/packages.list); do
			pkg=${pkg}.tazpkg
			if [ ! -f "$pkg" ]; then
				count=$(($count + 1))
				[ "$count" == 1 ] && newline
				echo -n "Fetching: ${pkg}"
				wget -q ${mirror%/}/$pkg
				status
			fi
			pkgsum=$($CHECKSUM $pkg)
			debug "$pkgsum"
			[ "$pkgsum" ] || pkgsum=$$
			mirsum=$(fgrep -h $pkgsum packages.$SUM)
			debug "$mirsum"
			if [ ! "$pkgsum" == "$mirsum" ]; then
				count=$(($count + 1))
				[ "$count" == 1 ] && newline
				echo -n "Fetching: ${pkg}.tazpkg"
				rm -f $pkg
				wget -q ${mirror%/}/$pkg
				status
			fi
		done
		[ "$count" == 0 ] && status 
		separator && newline ;;
	
	*) usage ;;
esac
exit 0
