#!/bin/bash

log()
{
	echo "$myname: $@"
}

channel_present()
{
	if smart channel --show $1 2>&1 | grep -q baseurl >/dev/null; then
		return 0
	fi
	return 1
}

usage()
{
cat << EOT

  $myname [global options] command [options] [package ...]

  command is one of

    help:                 show this help screen
    init:                 initialize
    uninit:               undo initialization
    install:              install packages in [arguments]
    update:               update all jannet software on the system
    restore:              restore a previous jannet software version state
    list:                 query information about installed software packages
    list-projects:        query information about installed software projects
    checklog:             update the installation log file if necessary
    rpmnew:               remove superfluous rpmnew files and show conflicts
                          for others
    build-date:           show installed janware packages along with build date
    built-today:          show installed janware packages built today
    list-templates:       list templates
    list-template-tables: list templates tables
    list-template-output: list template output files
    rm-template-output:   remove template output files
    compile-templates:    compile templates

  global options are

     -v                   be verbose

  package

    optional whitespace-separated list of package names, generally limiting the
    scope of the command to the specified packages, defaults to all installed
    janware packages

EOT
	[ "$1" ] && exit $1
}

create_ldconfig_state()
{
	echo "=== automatically created by $myname update script"
	echo "--- files"
	ls /etc/ld.so.conf.d
	echo "--- directories"
	find /etc/ld.so.conf.d -type f | xargs cat | sort -u
}

check_ldconfig()
{
	local state=/var/log/jw-build-ldconf.state
	[ -f $state ] && create_ldconfig_state | diff $state - >/dev/null 2>&1 && return
	echo -n "running ldconfig ... "
	/sbin/ldconfig
	create_ldconfig_state > $state
	echo "done."
}

list_packages()
{
	local query_tags=""

	eval set -- `getopt -- VPNUD "$@"`
	while [ "$1" != -- ]; do
	case $1 in
		-V)
			query_tags="$query_tags %{Vendor}"
			;;
		-P)
			query_tags="$query_tags %{Packager}"
			;;
		-U)
			query_tags="$query_tags %{URL}"
			;;
		-D)
			query_tags="$query_tags %{Distribution}"
			;;
		*)
			echo -e "Unexpected argument >$1<\n" >&2
			usage 1
			;;
	esac
	shift
	done
	shift

	[ "$query_tags" ] || query_tags="%{URL}"

	local names="$1"
	local rpm_args
	if [ -n "$names" ]; then
		rpm_args="$rpm_args $names"
	else
		rpm_args="$rpm_args -a"
	fi
	rpm -q --queryformat "%{Name}: $query_tags\n" $rpm_args | \
		grep -i '^[^ ]\+:.*\(jannet\|janware\)' | \
		sed 's/\(^[^ ]\+\) *:.*/\1/; s/[	 ]*$//' |\
		sort -u
}

list_projects()
{
	list_packages "$@" | xargs -r rpm -q --queryformat '%{SOURCERPM}\n' | \
		sed 's/[	]*//; s/-[0-9]\+.*//' |\
		sort -u
}

cmd_rpmnew()
{
	local file

	list_packages "$@" |
	xargs -r rpm -ql |
	while read file; do
		if [ -e "$file.rpmnew" ]; then
			if diff -q $file $file.rpmnew; then
				if [ -L "$file" ]; then
					echo ========== skipping link $file
					diff $file.rpmnew $file
					continue
				fi
				echo mv $file.rpmnew $file
				sudo mv $file.rpmnew $file
			else
				echo =========== $file
				diff $file.rpmnew $file
			fi
		fi
	done
}

cmd_diff()
{
	local file

	list_packages "$@" |
	xargs -r rpm -qV |
	sed '/^....L\|^..5/ !d; s%[^/]*/%/%' |
	while read file; do
		if diff -q $file $file.rpmnew; then
			if [ -L "$file" ]; then
				echo ========== skipping link $file
				diff $file.rpmnew $file
				continue
			fi
			echo mv $file.rpmnew $file
			sudo mv $file.rpmnew $file
		else
			echo =========== $file
			diff $file.rpmnew $file
		fi
	done
}

cmd_build_date()
{
	list_packages "$@" |
		xargs -r rpm -q --queryformat '%{BUILDTIME} %{NAME}\n' |
		sort -n |
		sed 's/-run\|-devel//' |
		sort -u |
		while read t p; do
			echo `date --date=@$t --rfc-3339=seconds` $p
		done
}

cmd_list_templates()
{
	local ext_from="$template_exts" # TODO: support more than one
	local ext_from_re=`echo $ext_from | sed 's/\./\\./g'`
	local f
	list_packages "$@" | xargs -r rpm -ql | while read f; do
		[ -f "$f" ] || continue
		echo $f | grep -q "$ext_from_re$" || continue
		echo $f
	done
}

cmd_list_template_tables()
{
	local ext_from="$table_exts"
	local e f
	list_packages "$@" | xargs -r rpm -ql | while read f; do
		[ -f "$f" -o -L "$f" ] || continue
		for e in $ext_from; do
			[ -f "${f%.*}$e" ] || continue
			echo $f
		done
	done
}

cmd_list_template_output()
{
	local re=`echo $template_exts | sed 's/\./\\\\./g; s/^ *//; s/ *$//; s/  */$\\\\|/g; s/\(.*\)/\\\\(\1$\\\\)/'`
	local f
	list_packages "$@" | xargs -r rpm -ql | sed "/$re/ !d; s/$re//" | while read f; do
		[ -f "$f" -o -L "$f" ] || continue
		echo $f
	done
}

cmd_rm_template_output()
{
	local restore=0
	while [ "${1:0:1}" = '-' ]; do
	case "$1" in
	-r)
		restore=1
		;;
	*)
		usage 1
		;;
	esac
	shift
	done

	local f
	cmd_list_template_output $@ | while read f; do
		log "removing $f"
		rm $f
		bak=$f$template_bak_ext
		if [ "$restore" = 1 -a -f "$bak" ]; then
			log "restoring $f from $bak"
			mv $bak $f
		fi
	done
}

cmd_compile_templates()
{
	local ext_from="$template_exts" # TODO: support more than one
	local ext_from_re=`echo $template_exts | sed 's/\./\\./g'`
	local ext_to=""
	local ext_tables="$table_exts"
	local group=root
	local owner=root
	local mode=600
	local conf_patt="^[ 	]*# *conf:"
	local missing_table=0
	local backup=0

	umask 0077

	while [ "${1:0:1}" = '-' ]; do
	case "$1" in
	-o)
		owner="$2"
		shift
		;;
	-m)
		mode="$2"
		shift
		;;
	-g)
		group="$2"
		shift
		;;
	-b)
		backup=1
		;;
	*)
		usage 1
		;;
	esac
	shift
	done

	local f
	while read f; do
		local base=`echo $f | sed "s/$ext_from_re$//"`
		local to=$base$ext_to
		local table=""
		local ext
		for ext in $ext_tables; do
			table=$base$ext
			[ -f "$table" ] && break
		done
		[ -f $table ] || {
			log "WARNING: No key-value table found for template $f, not compiling." >&2
			((missing_table++))
			continue
		}
		# TODO: use mktemp -d and keep temporary files in read-only dir
		local tmp=$to.tmp
		log "Applying macros in $table to $f."
		eval `sed "/$conf_patt/ !d; s/$conf_patt//" $table`
		sed 's|^[ 	]*#.*||; s|\([^ 	=]\+\)[ 	=]\+\(.*\)|s/\1/\2/g|' $table | sed -f - $f > $tmp
		chmod $mode $tmp
		chown $owner $tmp
		chgrp $group $tmp
		local bak=$to$template_bak_ext
		if [ "$backup" = 1 -a -f $to ] && ! diff -q $to $bak >/dev/null 2>&1; then
			log "Saving backup to $to to $bak"
			cp -p $to $bak
		fi
		mv $tmp $to
	done <<< $(cmd_list_templates "$@")

	if [ "$missing_table" != 0 ]; then
		log "WARNING: $missing_table missing tables found. You might want to add them and run sudo $cmdline again."
	fi
}

cmd_built_today()
{
	local today=`date +'%Y-%m-%d'`
	cmd_build_date | grep $today | cut -d' ' -f3
}

# ----- here we go

cmdline="$0 $@"
myname=`basename $0`
longname=$0
opts="v"
table_exts=".jw-secret .jw-vars"
template_exts=".jw-tmpl"
template_bak_ext=".jw-pkg.bak"

while [ "${1:0:1}" = '-' ]; do
case "$1" in
-v)
	opt_verbose=true
	shift
	;;
*)
	usage 1
	;;
esac
shift
done

cmd="${1//-/_}"
shift

case $cmd in

init)
	if ! channel_present ftp.jannet.de; then
		echo -n "adding installation source ... "
		sudo smart channel -y --add ftp.jannet.de \
			type=yast2 \
			baseurl=ftp://dspadm:dspasswd@ftp.jannet.de/pub/packages/linux/suse/10.1/inst-source \
			>/dev/null 2>&1
		if channel_present; then echo done; else echo failed; fi
	fi
	;;

uninit)
	if channel_present ftp.jannet.de; then
		echo -n "removing installation source ... "
		sudo smart channel -y --remove ftp.jannet.de >/dev/null 2>&1
		echo done
	fi
	;;

update)
	sudo smart update ftp.jannet.de
	sudo smart upgrade -y
	check_ldconfig
	;;

install)
	sudo smart update ftp.jannet.de
	if [ -f $1 ]; then
		sudo smart install -y `cat $1`
	else
		sudo smart install -y $*
	fi
	check_ldconfig
	;;
restore)
	echo "not yet implemented, sorry" >&2
	;;
checklog)
	line=`jannet info | tr -s " "`
	echo $line
	;;
list)
	if [ "$opt_verbose" = true ]; then
		list_packages "$@" | xargs -r rpm -qi
	else
		list_packages "$@" | xargs -r rpm -q
	fi
	;;
list_projects)
	list_projects "$@"
	;;
cpp_glib)
	sudo rpm -U --replacefiles --replacepkgs --oldpackage \
		ftp://dspadm@ftp.jannet.de/pub/packages/linux/suse/10.1/inst-source/rpm/i586/glib2-2.8.5-19.i586.rpm
	check_ldconfig "$@"
	;;
compile_templates|list_templates|list_template_tables|list_template_output|rm_template_output|diff|build_date|built_today|rpmnew)
	cmd_$cmd "$@"
	;;
help)
	usage 0
	;;
*)
	usage 1
	;;
esac
