#!/bin/bash
# -*- indent-with-tabs: 1 -*-

version=0.10
program=${0##*/}
progdir=${0%/*}
if [ "$progdir" = "$program" ]; then progdir="."; fi

# ----------------------------------------------------------------------
function usage() {
    cat <<EOF
NAME
	$program - given a list of changed files, create a patch diff

SYNOPSIS
	$program [OPTIONS] PATHS

DESCRIPTION
	Given a list of changed file, run svn diff to create a patch
	suitable for the patch command, named with the current date and
	the given patch name.  Place this in the local patch directory.
	

EOF
    echo -e "OPTIONS"
    if   [ "$(uname)" = "Linux" ]; then
        egrep "^[	]+[-][A-Za-z| -]+\*?\)[	]+[A-Za-z].+#" $0 | tr -s "\t|" "\t," | sed -r -e 's/\)[ \t]+([A-Z]+)=\$2[^#]*#/=\1\t/' -e 's/\)[^#]*#/\t/'
    else
        egrep "^[	]+[-][A-Za-z| -]+\*?\)[	]+[A-Za-z].+#" $0 | sed 's/\|.*\$2[^#]*#/	/'| sed -E 's/\|.*\)[^#]*#/	/'
    fi
    cat <<EOF

AUTHOR
	Written by Henrik Levkowetz, <henrik@tools.ietf.org>

COPYRIGHT
	Copyright 2013 Henrik Levkowetz.

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or (at
	your option) any later version. There is NO WARRANTY; not even the
	implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
	PURPOSE. See the GNU General Public License for more details.
	
EOF

}

# ----------------------------------------------------------------------
function die() {
    echo -e "\n$program: error: $*" > /dev/stderr
    exit 1
}

function note() { 
	if [ -n "$VERBOSE" ]; then echo -e "$*"; fi
}

# ----------------------------------------------------------------------
function version() {
	echo -e "$program $version"
}

# ----------------------------------------------------------------------
trap 'echo "$program($LINENO): Command failed with error code $? ([$$] $0 $*)"; exit 1' ERR


# ----------------------------------------------------------------------
# Option parsing

# Options
shortopts=c:n:or:hvV
longopts=change=,name=,overwrite,revision=,help,verbose,version

# Default values

if   [ "$(uname)" = "Linux" ]; then
    args=$(getopt -o "$shortopts" --long "$longopts" -n "$program" -- $SV "$@")
    if [ $? != 0 ] ; then die "Terminating..." >&2 ; exit 1 ; fi
    eval set -- "$args"
    sed="sed -r"
    date="date -d"
else
    # Darwin, BSDs
    args=$(getopt -o$shortopts $SV $*)
    if [ $? != 0 ] ; then die "Terminating..." >&2 ; exit 1 ; fi
    set -- $args
    sed="sed -E"
    date="date -j -f %Y-%m-%d"
fi

while true ; do
    case "$1" in
	-c| --change)	CHG="$2"; shift;;	# Use the change made by revision ARG
	-n| --name)	NAME="$2"; shift;;	# Patch name
	-o| --overwrite)	OVER=1;;        # Overwrite any existing patch file
	-h| --help)	usage; exit;;           # Show this help, then exit
	-v| --verbose)	VERBOSE=1;;             # Be more talkative
	-V| --version)	version; exit;;		# Show program version, then exit
	--)		shift; break;;
	*) die "Internal error, inconsistent option specification: '$1'";;
    esac
    shift
done

# ----------------------------------------------------------------------
# The program itself

if   [ "$CHG" ]; then
  if [ "$NAME" ]; then
    name="${NAME//_/-}-c$CHG"
  else
    name=$(echo $(svn log -c $CHG | sed -r -e '/^---/d' -e '/^r[0-9]+/d' -e '/^$/d' -e 's/Merged in \[[0-9]+\] from [^:]+..//' ) | sed -r -e 's/(.*)/\L\1/' -e 's/[^[:alnum:]]/-/g' -e 's/-+/-/g' -e's/-$//' | cut -c 1-40)
    name="$name-c$CHG"
  fi
else
  if [ "$NAME" ]; then  
    if [ $# -lt 1 ]; then die "Expected file list on the command line."; fi
    name="${NAME//_/-}"
  else
    die "Please use the -n switch to provide a patch name"
  fi
fi

patchfile=$progdir/../../patches/$(date +%Y-%m-%d)-$name.patch
if [ -e $patchfile -a ! -n "$OVER" ]; then die "Patchfile $patchfile already exists"; fi
svn diff ${CHG:+ -c $CHG} ${REV:+ -r $REV} "$@" > $patchfile
less $patchfile
echo ""
echo ""
echo "Patch is in $patchfile"
