#!/bin/bash
# cmddiff	Command Difference
# 	stores a command output in RCS file,
#	shows a diff with previous version,
#	if field # given calculates changes' speed
#	if maximal value given calculates when it will be reached
# Copyright (C) 1999 Rafał Maszkowski <rzm@icm.edu.pl>
# Licence: GNU GPL rev 3+
# 19990205 written; rcs, line.field syntax
# 19990504 check if there is any command given
#	   -h option
# 19990506 check if t1-t0 or speed ==0
# 19990512 cat first version
# 2000-05-26 more flexible fields selection [?]
# 2011-08-12 more precise -p description; limit numbers accuracy on output
# 2012-12-06 licence: GPL 2 -> 3+; script encoding: latin2 -> utf8; help corrections; [ ] std test -> [[ ]] bash test

# TODO
# -r options other than 0, -1, x.y will be time span to make comparison in, in seconds
# options cache for given command
# remove spaces and such and make lower case before md5ing ( tr A-Z a-z|tr -dc 'a-z0-9' ?)
# maximal value error checking
# curve fitting to field value
# multiple "-f"s
# -n option for not adding next entry into RCS
# div. by 0
# rounding the results to 3 sign. digits
# initialize option

path=`pwd`
rev="0"
unset LANG

while [[ "$1" =~ -[feprh] ]]; do
	case "$1" in
		"-f") shift; field="$1"; shift;;
		"-e") shift; end="$1";   shift;;
		"-p") shift; path="";;
		"-r") shift; rev="$1";   shift;;
		"-h") shift; echo cmddiff - command output tracer; cat <<EOT

example:
cmddiff -f 2 -e 137000 -p -r 1.6 'wc -l addr.resolved'
-f 2          compare the 2nd field in 1st (default) line; general form: [line.]field
-e 137000     calculate when the field is going to reach this value
-p            do not append path of the current directory to the characteristic command string
-r 1.6        compare with revision 1.6, default: 0 == 1.1, -1 means the previous one
'wc ...'      the command
EOT
			exit;;
	esac
done
#echo $field $end; exit

if [ "$1" = "" ]; then
	echo missing command argument, use -h option to see help
	exit 1
fi

tmp=~/.cmddiff
if [ ! -d "$tmp" ]; then mkdir "$tmp"; fi

file=`echo "$path$@" | md5sum | awk '{print $1}'`
tmpf="$tmp/$file"
tmprcs="$tmp/$file,v"

if [ ! -e "$tmprcs" ]; then
	name="$@"
fi

case $rev in
	0) rev=1.1;;
	-1) if [ -e "$tmprcs" ]; then
		rev=`rlog -b "$tmprcs" | awk '/^revision / { print $2; exit }'`
	else
		rev=1.1
	fi
	;;
esac
# else given, e.g. 1.6

sh -c "$@" 2>&1 > "$tmpf"

cd "$tmp"
if [ -e "$tmprcs" ]; then
	rlog -t "$tmprcs" | tail -2 | head -1
	rcsdiff -q -r$rev -u "$tmprcs"
else
	echo first version:
	cat "$tmpf"
fi

echo "$name" | ci -d -q -f "$tmpf"
rcs -U -q "$tmprcs"

if [ ! -z "$field" ]; then
	co -r$rev -q -M -f -u "$tmprcs"
	t0=`date -r "$tmpf" +%s`
	v0=`cat "$tmpf" | awk --assign=field="$field" 'BEGIN { n=split ( field, lnfd, "." ); if (n==1) { lnfd[2]=lnfd[1]; lnfd[1]=1 } } { i++; if (i==lnfd[1]) { print $lnfd[2]; exit} }'`
	co -q -M -f -u "$tmprcs"
	t1=`date -r "$tmpf" +%s`
	v1=`cat "$tmpf" | awk --assign=field="$field" 'BEGIN { n=split ( field, lnfd, "." ); if (n==1) { lnfd[2]=lnfd[1]; lnfd[1]=1 } } { i++; if (i==lnfd[1]) { print $lnfd[2]; exit} }'`
	tdiff=`echo "$t1-$t0" | bc -l`
	if [ "$tdiff" != 0 ]; then
		speed=`echo "($v1-$v0)/($tdiff)" | bc -l`
		if [ ! -z "$end" -a "$speed" != 0 ]; then
			toend=`echo "($end-$v1)/$speed + 0.5" | bc -l | sed 's/\..*//'`
			atend=`date -d "now + $toend seconds"`
			toendstr=`echo , ends: $atend`
		fi
		printf "change: %.3g per second%s\n" "$speed" "$toendstr"
	fi
fi
