#! /usr/bin/env bash

# Install the corresponding .lua file in monotone.  Its
# comments holds instructions on how to configure this
# notification system.
#
# Call this script from cron or similar to process files
# generated by the .lua file.
#
# Copyright (c) 2007, Matthew Sackman (matthew at wellquite dot org)
#                     LShift Ltd (http://www.lshift.net)
# Copyright (c) 2010, Richard Levitte <richard@levitte.org)
# License: GPLv2 or later

MTN="mtn"
HIGHLIGHT="source-highlight"
MIMECONSTRUCT="mime-construct"
BASE="/var/spool/monotone"

if [ -n "$1" ]; then BASE="$1"; fi

function processFile() {
    local fileBase=$1

    local dat="$fileBase.dat.txt"
    local hdr="$fileBase.hdr.txt"
    local rev="$fileBase.rev.txt"
    if [ ! -f $hdr ]
    then
	echo "Specified header file '$hdr' does not exist"
	exit 1
    fi

    if [ ! -f $rev ]
    then
	echo "Specified revision file '$rev' does not exist"
	exit 1
    fi

    if [ ! -f $dat ]
    then
	echo "Specified data file '$dat' does not exist"
	exit 1
    fi

    local server=
    local keydir=
    local key=
    . $dat
    # There must ALWAYS be a key, but it's possible to set things up to
    # allow for the null key.
    key="--key=$key";

    local mtn_cmd="$MTN -q -q --no-workspace --no-standard-rcfiles --keydir=$keydir $key automate remote --remote-stdio-host=$server --"

    local revision=$(cat $rev | grep '^revision:' | sed -e 's/^revision:[ ][ ]*//')

    local parts=()
    local files=()
    let fIdx=0
    let pIdx=0
    local parents=$($mtn_cmd parents $revision)
    if [ "x" = "x$parents" ]
    then
	local plainDiff="$revision.noparent.diff"
	local htmlDiff="$revision.noparent.html"
	local partFile="$revision.noparent.part"
	files[0]=$plainDiff
	files[1]=$htmlDiff
	parts[0]=$partFile

	local fn
	local content_id
	local l
	$mtn_cmd 2>/dev/null get_revision $revision | while read l; do
	    set $l;
	    case $1 in
		add_file)
		    fn=$(echo "$2" | cut -f2 -d'"')
		    content_id=
		    ;;
		content)
		    content_id=$(echo "$2" | cut -f2 -d'[' | cut -f1 -d']')
		    ;;
	    esac
	    if [ -n "$fn" -a -n "$content_id" ]; then
		(
		    $mtn_cmd 2>/dev/null get_file $content_id > ".tmp.$fn"
		    local lcnt=$(wc -l < ".tmp.$fn")
		    echo "============================================================"
		    echo "--- /dev/null	"
		    echo "+++ $fn	$content_id"
		    case $lcnt in
			0)
			    ;;
			1)
			    echo "@@ -0,0 +1 @@"
			    ;;
			*)
			    echo "@@ -0,0 +1,$lcnt @@"
			    ;;
		    esac
		    cat ".tmp.$fn" | sed -e 's/^/+/'
		    rm ".tmp.$fn"
		) > $plainDiff
		fn=
		content=
	    fi
	done
	cat $plainDiff | $HIGHLIGHT -s diff -f html > $htmlDiff
	$MIMECONSTRUCT --subpart --multipart multipart/alternative \
	    --type text/plain --part-header "Content-Type: text/plain" --encoding quoted-printable --file $plainDiff \
	    --type text/html --encoding quoted-printable --file $htmlDiff \
	    > $partFile
    else
	for p in $parents
	do
	  local plainDiff="$revision.$p.diff"
	  local htmlDiff="$revision.$p.html"
	  local partFile="$revision.$p.part"
	  files[$fIdx]=$plainDiff
	  files[$fIdx+1]=$htmlDiff
	  let fIdx+=2
	  $mtn_cmd 2>/dev/null content_diff --revision=$p --revision=$revision > $plainDiff
	  cat $plainDiff | $HIGHLIGHT -s diff -f html > $htmlDiff
	  $MIMECONSTRUCT --subpart --multipart multipart/alternative \
	      --type text/plain --part-header "Content-Type: text/plain" --encoding quoted-printable --file $plainDiff \
	      --type text/html --encoding quoted-printable --file $htmlDiff \
	      > $partFile
	  parts[$pIdx]=$partFile
	  let pIdx+=1
	done
    fi

    local margs=""
    for p in ${parts[@]}
    do
      margs="$margs --subpart-file $p"
    done

    local hdrargs=$(cat $hdr)
    $MIMECONSTRUCT --embedded-to --header "$hdrargs" --multipart multipart/mixed \
	--type text/plain --part-header "Content-Type: text/plain" --encoding quoted-printable --file $rev \
	$margs

    for p in ${parts[@]}
    do
      rm $p
    done

    for f in ${files[@]}
    do
      rm $f
    done

    rm $dat
    rm $hdr
    rm $rev
}

if [ "x" = "x$(ls $BASE)" ]
then
    echo >&2 "monotone-mail-notify: no files in $BASE, exiting"
    exit 0
fi

cwd=$(pwd)
if cd $BASE; then

    mkdir -p .notify.redo
    mkdir .notify.lock || \
	(echo 'Mail notifier locked by another process'; exit 1) && \
	(
	while [ -d .notify.redo ]; do
            rmdir .notify.redo
	    ls | grep '\.hdr\.txt$' | while read f
	    do
		name=$(basename "$f" '.hdr.txt')
		processFile "$name"
	    done
	done
	rmdir .notify.lock
    )

fi
cd "$cwd"
