#!/bin/zsh

local prog=$(basename $0)
set -e
zmodload zsh/pcre

declare -A info
function read_info {
        local rev=$1
        info=()
        while read line ; do
               local var=${line%%:*}
               if [ "$var" = "message" ] ; then
                       read line
                       info[subject]=$line
                       info[message]=$(sed -e's/^  //')
                       return
               elif [[ "$var" != "$line" ]] ; then
                       local val=${line#*: }
                       info[$var]="$val"
               fi
        done < <( bzr log -r $rev )
}

function gen_header {
        cat <<END
revno ${info[revno]}
From: ${info[committer]}
Date: ${info[timestamp]}
Branch-Nick: ${info[branch nick]}
Subject: ${info[subject]}

${info[message]}

---
END
}

function gen_stat {
        local rev=${info[revno]}
        local from=$(( $rev - 1 ))
        bzr diff -r $from..$rev | diffstat -p0
        echo
}

function gen_diff {
        local rev=${info[revno]}
        local from=$(( $rev - 1 ))
        bzr diff --prefix old/:new/ -r "$from..$rev" || true
}

function gen_trailer {
echo "-- "
echo "$prog ${info[revno]}"
echo
}

function gen_patch {
        gen_header
        gen_stat
        gen_diff
        gen_trailer
}

function gen_patch_for_rev {
        local rev=$1
        read_info $rev
        if [ -n "$to_stdout" ] ; then
                gen_patch $rev
        else
                local name=$(echo "${info[subject]}" | tr -c '[[:alnum:]]' '-')
                local file=$(printf "%05d-$name.patch" $rev)
                echo $file
                gen_patch $rev > $file
        fi
}

function gen_patches_for_range {
        local rev1=$1
        local rev2=$2
        for (( n=$rev1; n<= $rev2; n++ )) ; do
                gen_patch_for_rev $n
        done
}

function die {
        echo >&2 $@
        exit 1
}

function show_help {
        echo "$prog - export a revno as a patch"
        echo
        echo "$prog [ --stdout ] <revno>[..<revno>]"
}

if [ -z "$1" ] ; then
        show_help >&2
        exit 1
fi

to_stdout=

while [ -n "$1" ] ; do
        cmd=$1 ; shift
        case "$cmd" in
            -h|--help)
                show_help
                exit 0
                ;;
            --stdout)
                to_stdout=1
                ;;
            *..*)
                [[ "$cmd" -pcre-match '^[0-9]+\.\.[0-9]+$' ]] || die "not a valid looking revision: $cmd"
                rev1=${cmd%%..*}
                rev2=${cmd#*..}
                gen_patches_for_range "$rev1" "$rev2"
                ;;
            *)
                [[ "$cmd" -pcre-match '^[0-9]+$' ]] || die "not a valid looking revision: $cmd"
                gen_patch_for_rev $cmd
                ;;
        esac
done

[ -z "$1" ] && exit 1

gen_patch $1