#!/bin/sh

set -e

die()
{
    echo "ERROR: $1" >&2
    exit 1
}

db=$(notmuch config get database.path)
meta=$db/.notmuch
base=$meta/.lore
[ -d $db -a -d $meta ] || die "Please run 'notmuch setup' first."
mkdir -p $base

getvar() {
    # From the INI file $1, get the value of key $3 in section $2.
    awk -vsect=$2 -vvar=$3 -F= '
    	/^\[.*\]$/ {
		accept = $1 == "[" sect "]";
	}
	/=/ {
		if (accept && $1 == var) {
			print($2);
			exit(0);
		}
        }' $1
}

import()
{
    local git="git --git-dir=$2"

    # Make sure the Maildir exists
    mkdir -p $db/$1/tmp -p $db/$1/new $db/$1/cur

    # Extract the message from each commit in the range and store it
    # in the Maildir for notmuch to consume.
    $git rev-list $3 | while read sha; do
	$git show $sha:m >$db/$1/new/$sha
    done
}

sync()
{
    local gitdir=$base/git/$1

    # Fetch new messages from all epochs and inject them to the
    # corresponding Maildir.
    for epoch in $(ls -v $gitdir/); do
	local git="git --git-dir=$gitdir/$epoch"
	local head=$($git rev-list -n1 master)

	echo "  epoch$epoch: syncing" >&2
	$git fetch --quiet
	import $1 $gitdir/$epoch $head..master

	# Basically we now want to `git fetch --depth=1`, but that
	# would race against new messages that came in during the
	# import. So instead we "manually" move the shallow boundary
	# to HEAD, and then get rid of all objects beyond it.
	echo $head >$gitdir/$epoch/shallow
	$git gc --quiet --prune=all
    done
}

initialize()
{
    local gitdir=$base/git/$1
    local epoch=$(ls -v $gitdir/ 2>/dev/null | tail -n1)
    local url=$(getvar $base/sources $1 url)
    local since=$(getvar $base/sources $1 since)

    epoch=${epoch:--1}
    since=${since:-3 months ago}

    echo "$1: initialize ($url)" >&2

    # Try to fetch newer epochs until there are no more.
    while git clone --quiet --depth 1 --mirror \
	      $url/$(($epoch + 1)) $gitdir/$(($epoch + 1)) 2>/dev/null; do
	epoch=$(($epoch + 1))

	echo "  epoch$epoch: initial import" >&2
	if ! git --git-dir=$gitdir/$epoch fetch --quiet \
	     --shallow-since="$since" 2>/dev/null; then
	    if [ $epoch -eq 0 ]; then
		# retry without separate git fetch, e.g. linuxppc-dev
		rm -rf "${gitdir:?}/$epoch"
		if ! git clone --mirror --shallow-since="$since" "$url/0" "$gitdir/0"; then
		    echo "    failed cloning repo $url"
		    continue
		fi
	    else
		echo "    no messages in range." >&2
		continue
	    fi
	fi

	import $1 $gitdir/$epoch master
    done

    if [ $epoch -lt 0 ]; then
	echo "  WARN: no epochs found." >&2
	return 1
    fi
}

sources=$(grep -e '^\[.*\]$' <$base/sources | tr -d '[]')

for source in $sources; do
    if ! initialize $source; then
	continue
    fi

    sync $source
done