#!/bin/sh
#
# /usr/local/bin/localwebgalleryupdate
# Copyright 2008 Jonas Smedegaard <dr@jones.dk>
#
# $Id: localwebgallerydaemon,v 1.2 2008-03-20 20:35:51 jonas Exp $
#
# (Re)generate web gallery whenever source directory changes
#
# TODO: Implement options:
#   --init (create targetdir if missing, fail if exists and non-empty)
#
# TODO: implement ask() and the following options:
#   --reset (purge output dir -- use with --init to always build from scratch)
#   --force
#
# TODO: Support more gallery engines
#
# TODO: Support system-wide and per-user config overrides
#

set -e

# Defaults options
SOURCEDIR="$HOME/public_media"
TARGETDIR="$HOME/public_html/gallery"
GENERATOR="lazygal"
THEME=""

PRG=$(basename "$0")

showhelp() {
	cat <<EOF
Usage:   $PRG [ SOURCEDIR [ TARGETDIR ] ]

Options:
  -g, --generator Gallery generator to use (default: $GENERATOR)
  -t, --theme     Gallery theme to use (default: ${THEME:-no theme})
  -w, --watch     Watch source, updating each time something changes
  -n, --now       Update once
  -v, --verbose   Print activities to stderr while running
  -h, --help      This text

The following directories are used if not provided on commandline:
    SOURCEDIR: $SOURCEDIR
    TARGETDIR: $TARGETDIR

If --watch is not supplied, --now is implied.

Use --generator=list to get a list of locally supported generators.

Examples:
    $PRG ~/my/images /var/www/gallery
    daemon -u me -n gallery-me -- $PRG --watch

EOF
}

exit1()	{
	echo >&2 "Error: $1"
	echo >&2 "Exiting..."
	exit 1
}

TEMP="`getopt -s sh -o g:t:wnvh -l generator:,theme:,,watch,now,verbose,help -n "$PRG" -- "$@"`"
if [ $? != 0 ] ; then exit1 " Internal getopt error."; fi
eval set -- "$TEMP"

watch=
now=
verbose=
while true ; do
	case "$1" in
		-g|--generator) generator="$2"; shift 2;;
		-t|--theme) theme="$2"; shift 2;;
		-w|--watch) watch="yes"; shift;;
		-n|--now) now="yes"; shift;;
		-v|--verbose) verbose="yes"; shift;;
		-h|--help) showhelp; exit 0;;
		--) shift; break;;
		*) exit1 "Internal error resolving options.";;
	esac
done

# Use defaults if not overridden
generator="${generator:-$GENERATOR}"
theme="${theme:-$THEME}"
sourcedir="${1:-$SOURCEDIR}"
targetdir="${2:-$TARGETDIR}"

generators="lazygal"
if [ "list" = "$generator" ]; then
	echo "The following gallery generators are supported on this system:"
	echo
	for generator in $generators; do
		if which $generator >/dev/null; then
			echo "    $generator"
		fi
	done
	echo
exit 0
fi

# Check if generator is supported and declare needed external programs
case $generator in
	lazygal)
		which "$generator" >/dev/null \
			|| exit1 "Unsupported generator \"$generator\" (try --generator=list)."
		which "mispipe" >/dev/null \
			|| exit1 "Helper tool \"mispipe\" (part of \"moreutils\") is unavailable."
		;;
	*) exit1 "Unsupported generator \"$generator\".";;
esac

# Static defaults
lazygal_opts="--quiet --check-all-dirs --clean-destination ${theme:+--theme $theme}"

# Sanity checks
[ -d "$sourcedir" ] || exit1 "Source directory \"$sourcedir\" is not a directory"
[ -d "$targetdir" ] || exit1 "Target directory \"$targetdir\" is not a directory"
[ -z "$watch" ] || which fileschanged >/dev/null \
	|| exit1 "Helper tool \"fileschanged\" needed for --watch mode is unavailable."

# TODO: Make it work to signal status to parent proces
#trap 'echo >&2 "Starting gallery update as requested."' USR1
updategallery() {
	onemoretime=yes
	trap 'onemoretime=yes' USR1
	while [ -n "$onemoretime" ]; do
#		[ -z "$verbose" ] || kill -USR1 $PPID
		onemoretime=
		case "$generator" in
		    lazygal)
			mispipe \
				"lazygal $lazygal_opts -o \"$targetdir\" \"$sourcedir\" 2>&1" \
				"egrep -v '^(Error: Directory Makernote with 5376 entries considered invalid; not read.|Warning: Failed to read Makernote, rc = 6)$'" \
				|| onemoretime=yes
			;;
		esac
		[ "--once" = "$1" ] || sleep 10
	done
}

started=
# Update immediately if requested or if watch mode isn't requested
if [ -n "$now" ] || [ -z "$watch" ]; then
	if [ -z "$watch" ]; then
		[ -z "$verbose" ] || echo >&2 "Starting gallery update once."
		updategallery --once
	else
		started=yes
		[ -z "$verbose" ] || echo >&2 "Starting gallery update before invoking watch mode."
		updategallery &
	fi
fi
[ -z "$watch" ]	|| [ -z "$verbose" ] || echo >&2 "Invoking watch mode."
[ -z "$watch" ] || fileschanged -r -s created,changed,deleted "$sourcedir" | while read file; do

	# Ignore hidden files (used for temporary files by rsync)
	case "$file" in
	    .*)
		continue
		;;
	esac

	# Invoke update if not active or telling to take another spin fails
	[ -z "$verbose" ] || echo >&2 "Update request triggered by \"$file\""
	if [ -z "$started" ] || ! kill -USR1 $(jobs -p) 2>/dev/null; then
		started=yes
		[ -z "$verbose" ] || echo >&2 "Request gallery update."
		updategallery &
	fi
done

exit 0