#!/bin/bash
# --- T2-COPYRIGHT-NOTE-BEGIN ---
# This copyright note is auto-generated by ./scripts/Create-CopyPatch.
# 
# T2 SDE: misc/vserver/install
# Copyright (C) 2006 Juergen "George" Sawinski
# Copyright (C) 2006 The T2 SDE Project
# 
# More information can be found in the files COPYING and README.
# 
# 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; version 2 of the License. A copy of the
# GNU General Public License can be found in the file COPYING.
# --- T2-COPYRIGHT-NOTE-END ---


# TODO:
#  - implement "update" mode
#  - add "check" mode
#  - implement $admdir outside $root
#  - post-installation methods
#  - add rootfs alike copy_and_parse functionality

# root directory defaults
root=./test #FIXME
vdirbase=/etc/vservers/.defaults/vdirbase
guest=

# files (selections) to install
files=
selection=

# installer defaults
method=install
installer=mine

# misc defaults
verbose=0

pkgdir=
pkgs=

admdir=

templates=
templatedir=./${0%/*}/templates #FIXME /etc/vserver/.distributions/t2/templates
patterndir=./${0%/*}/patterns   #FIXME /etc/vserver/.distributions/t2/patterns

#############################################################################
usage() {
cat << EOF
vserver-guest-install [options] [packages]

Options:
  Methods
    -i,-install                Install packages (default)
    -u,-update                 Update packages
    -r,-remove                 Remove packages
    -c,-check                  Check packages

  VServer setup
    -g,-guest <name of guest>  Name of the vserver guest
    -R,-root <root>            Root installation directory (./test)

  Package selection
    -t,-template <template>    Template name or file

  Miscellaneous:
    -v                         Increase verbosity level
    -pkgdir                    Package directory
    -admdir                    Set alternate /var/adm directory 
                               (a link into the install root is created)
EOF
}

# parse options
while [ "$1" ]; do
	case "$1" in
	-i|-install)  method=install ;;
	-u|-update)   method=update  ;;
	-r|-remove)   method=remove  ;;

	-g|-guest)    guest=$2 ; root=$vdirbase/$2 ; shift ;;
	-R|-root)     root=$2 ; shift ;;

	-t|-template) templates="$templates $2" ; shift ;;

	-v)           verbose=$(( $verbose + 1 )) ;;
	-vv)          verbose=$(( $verbose + 2 )) ;;
	-vvv)         verbose=$(( $verbose + 3 )) ;;
        -pkgdir)      pkgdir=$2 ; shift ;;
	-admdir)      admdir=$2 ; shift ;;

	-*)           usage ; exit ;;
	
	*)            pkgs="$pkgs $1" ;;
	esac
	shift
done

#############################################################################
# screen logging
dbg() {
	[ $1 -le $verbose ] || return
	msg info "$@"
}

msg() {
	local lvl;
	local t=$1 ; shift
	case "$t" in
	head) echo "=== $*" 1>&2 ;;
	status) echo "-> $*" 1>&2 ;;
	warn) echo "!!! $*"  1>&2 ;;
	error) echo "*** $*" 1>&2 ;;
	info) lvl=$1; shift ; echo "[$lvl] $*" 1>&2 ;;
	esac
}

#############################################################################
# parse templates
parse_template() {
	local line

	dbg 2 "  Parsing template \`$1'"

	while read line; do 
		if [[ $line = .include* ]]; then
			parse_template ${line/.include/}	
		else
			echo $line
		fi
	done < <(egrep -v '(#.*|^)$' $templatedir/$1)
}

dbg 1 "Assembling templates...."
pfile=`mktemp`
tmpfile=`mktemp`
for tmpl in $templates; do
	parse_template $tmpl >> $tmpfile
done
echo $pkgs >> $tmpfile
sort -u < $tmpfile > $pfile
pkgs=" `cat $pfile` "
rm -f $tmpfile $pfile

dbg 1 "Done."

#############################################################################
# parse package.db
pkgdb=$pkgdir/packages.db

block_end=$'\004'
entry_end=$'\027'

# _pkgdb_node pkg
_pkgdb_node() {
	zcat $pkgdb | egrep "^$1$" -A 10000 | grep "$block_end" -m 1 -B 10000
}

# extract_package_node <package> <dir>
extract_pkg_node() {
	local state=0
	local line

	_pkgdb_node $1 | while read line; do
		if [ "$line" = "$entry_end" -o "$line" = "$block_end" ]; then
			state=$(( $state + 1 ))
		else
			case "$state" in
			1) echo $line >> $2/$1.desc ;;
			2) echo $line >> $2/$1.deps ;;
			3) echo $line >> $2/$1.md5 ;;
			esac
		fi
	done
}

#############################################################################
# exclude pattern

# pattern <pkg>
pattern() {
	local f pat
	(
		for f in default $*; do
			[ -f $patterndir/$f ] && egrep -v "(^|#.*)$" $patterndir/$f
		done
	) | while read pat; do
		case "$installer" in
		mine) echo -n "-x '$pat' " ;;
		esac
	done
}

#############################################################################
# find the tar file

# archive <package>
archive() {
	local ext
	local ver

	for ext in tar.bz2; do # FIXME list of extensions!!!
		if [ -f $pkgdir/$1.$ext ]; then
			echo $pkgdir/$1.$ext
			return
		else
			ver="`_pkgdb_node $1 | fgrep '[V]'`" ; ver=${ver##* }
			if [ -f $pkgdir/$1-$ver.$ext ]; then
				echo $pkgdir/$1-$ver.$ext
				return
			fi
		fi
	done

	msg error "Package archive of \`$1' not found."
}

#############################################################################
# install, update, remove packages

msg head "Installing..."
case "$method" in
install)
	case "$installer" in
	mine)
		[ $verbose -gt 2 ] && v="-v"

		for p in $pkgs; do
			pkg=${p/\%*/}
			msg status "  $pkg"
			dbg 2 mine -i -R $root $( pattern $p ) $( archive $pkg )
			eval mine -i $v -R $root $( pattern $p ) $( archive $pkg )
		done
		;;
	esac
	;;
remove)
	case "$installer" in
	mine)
		for p in $pkgs; do
			pkg=${p/\%*/}
			echo mine -r -R $vdirbase/$guest $pkg
		done
		;;
	esac
	;;
*)
	echo "Not implemented: $method"
esac
