#! /bin/sh
#
# Prepare a release of libpqxx.  This is tailored to my machine and my current
# postgres installation.  It's not supposed to work on anything else.
#
# Usage: preprelease [sourcedir]
#
# where sourcedir is the main directory of the libpqxx source tree; defaults
# to "."
# 
# The script builds libpqxx and runs a regression test from the tarball
# generated by 'make dist'.  This ensures that no important files are left out
# of the distribution archive, and that there are no regression failures in the
# released version.
#
# If successful, the script leaves a distribution tarball in $TMPDIR (which
# defaults to /tmp).
#
# Set CONFIG_ARGS to any argument list you wish to pass to configure for
# compilation.  Defaults to "--enable-shared".  Don't set the compiler here;
# use COMPILERS instead (see below).
#
# Set CONFIGDIST_ARGS to any argument list you wish to pass to configure when
# preparing to make a distribution archive.  Defaults to
# "--enable-maintainer-mode" so that the HTML documentation is built and
# included in the archive.
#
# The distribution is tested for several compilers by default; override the list
# by setting COMPILERS to a space-separated list of compilers.
#
# Set CONCURRENCY_LEVEL to the number of parallel jobs you want "make" to run.
# This can be useful on SMP or SMT systems, or in conjunction with distcc.

SOURCEDIR="$1"

TMPDIR="${TMPDIR:-/tmp}"
export TMPDIR

LOGFILE="$TMPDIR/libpqxx-preprelease.log"
ERRLOG="$TMPDIR/libpqxx-preprelease.err"

DEFAULTCOMPILERS="g++-3.0 g++-3.3 g++-3.4 g++-4.0 g++-4.1"


if test -z "$CONCURRENCY_LEVEL" ; then
	CONCURRENCY_LEVEL=1
fi

if test -z "$COMPILERS" ; then
	COMPILERS="$DEFAULTCOMPILERS"
fi

if test -z "$CONFIG_ARGS" ; then
	CONFIG_ARGS="--enable-shared"
fi

if test -z "$CONFIGDIST_ARGS" ; then
	CONFIGDIST_ARGS="--enable-maintainer-mode"
fi


print () {
	echo "$1" >>$LOGFILE
	echo "$1" >>$ERRLOG
}

log () {
	print
	print "`date`: $1"
	print
}

command () {
	print "$ $1"
	$2 $1 >>$LOGFILE 2>>$ERRLOG
}


# In current directory, configure, build, and run regression test using the
# compiler given as an argument.  If no argument is given, the default compiler
# is used.
run_test () {
	if ! test -z "$1" ; then
		COMPILEROPT="CXX=$1"
	fi

	if test -z "$1" || which "$1" >/dev/null ; then
		log "********* Testing with $1 *********"

		# Skip documentation build: we tested that the first time around
		touch doc/reference-stamp doc/tutorial-stamp &

		log "Configuring"
		command "./configure $CONFIG_ARGS $COMPILEROPT" nice

		log "Building"
		command "make -j $CONCURRENCY_LEVEL" nice

		log "Running regression test"
		command "make -j $CONCURRENCY_LEVEL check" nice
		grep '^FAIL:' $LOGFILE 2>>$ERRLOG || true
		grep '^All [0-9]* tests passed' $LOGFILE
	else
		log "********* Skipping $1      *********"
	fi
}


# Ensure that the given file has been produced before rolling a tarball
require_product () {
	PRODUCT="$1"
	TYPE="$2"
	if ! test -e "$PRODUCT" ; then
		if test -z "$TYPE" ; then
			TYPE="file"
		fi
		print "Required $TYPE not generated: $PRODUCT"
		exit 1
	fi
}

LC_ALL=C

rm -f -- $LOGFILE $ERRLOG

PQXXVERSION=`grep '\<PQXXVERSION\>' VERSION | sed -e 's/^[[:space:]A-Z_]*//' | sed -e 's/[[:space:]]*#.*$//'`

# See if debian/changelog needs updating
log "Seeing if debian/changelog is up to date..."
if ! head -n 1 debian/changelog | grep "($PQXXVERSION-" >/dev/null
then
	echo "Please update debian/changelog to mention version $PQXXVERSION"
	exit 1
fi

# See if NEWS describes the new release
log "Seeing if NEWS is up to date..."
if ! head -n 1 NEWS | grep "^$PQXXVERSION[[:space:]]*$"
then
	echo "Please update NEWS to describe $PQXXVERSION release"
	exit 1
fi

# Check that compiler-internal-pre.hxx and compiler-internal-post.hxx inclusions
# match up
findhdr() {
  HDR="$1"
  shift
  grep "^[[:space:]]*#[[:space:]]*include[[:space:]]*[<\"]$HDR[>\"]" $*
}

OLDPATH="$PATH"
PATH="$OLDPATH:./tools"
PREFILES="`maketemporary`"
PATH="$OLDPATH"

log "Looking for mismatched pre/post compiler headers..."
findhdr pqxx/compiler-internal-pre.hxx -l include/pqxx/* >"$PREFILES"
if ! findhdr pqxx/compiler-internal-post.hxx -l include/pqxx/* | \
	diff "$PREFILES" - ; \
	then
	echo "Mismatched compiler-internal-pre/post headers"
	rm -f -- "$PREFILES"
	exit 1
fi
rm -f -- "$PREFILES"

log "Preparing libpqxx release $PQXXVERSION."
log "Log file is $LOGFILE, errors go to $ERRLOG"

tail -f --pid=$$ $ERRLOG &

if test -z "$PGHOST"; then 
	log "Looking for local PostgreSQL socket..."
	SOCKET=".s.PGSQL.5432"
	for d in "$TMPDIR" /var/run /tmp /var/run/postgresql ; do
		if test -S "$d/$SOCKET" ; then
			log "Found socket in $d."
			PGHOST="$d"
			export PGHOST
		fi
	done
	if test -z "$PGHOST" ; then
		log "WARNING: No local PostgreSQL found.  Tests may not run."
	fi
fi

if test -z "$PGHOST" ; then
	log "Using default PostgreSQL location."
else
	log "Accessing PostgreSQL in $PGHOST"
fi

set -e

if test -z "$SOURCEDIR"; then SOURCEDIR="."; fi
command "cd $SOURCEDIR"
SOURCEDIR=`pwd`

log "Building from \"$SOURCEDIR\" (`pwd`)"

DISTNAME=libpqxx-$PQXXVERSION
TARBALL=$DISTNAME.tar.gz

log "Cleaning up old documentation"
# Re-generating the reference docs every time just takes too much time...  Just
# remember to clean them out every once in a while.
#command "rm -f -- doc/html/Reference/*"
command "rm -f -- doc/html/Tutorial/*"
command "rm -f -- doc/reference-stamp doc/tutorial-stamp"

log "Generating autoconf/automake files"
command "env NOCONFIGURE=1 ./autogen.sh" nice

log "Configuring for make dist"
command "./configure $CONFIGDIST_ARGS" nice

log "Creating $TARBALL"
command "make dist" nice

command "rm -f -- $TMPDIR/$TARBALL"
command "mv -- $TARBALL $TMPDIR"

command "cd $TMPDIR"
command "rm -rf -- $DISTNAME"

log "Extracting $TARBALL in $TMPDIR"
command "tar xzf $TARBALL"
command "rm -- $TARBALL"
command "cd $DISTNAME"

for compiler in $COMPILERS ; do
	run_test "$compiler"
done


log "Generating symbol table"
mkdir -p "$SOURCEDIR/lib"
nm --demangle src/.libs/libpqxx.a | cut -d' ' -f 3-  | grep -v '^_' | grep -v '^$' | grep -i '^pqxx' | sort -u -o "$SOURCEDIR/lib/SYMBOLS.$PQXXVERSION"

log "Creating release version of $TARBALL"
command "make dist" nice

require_product doc/html/Reference/index.html
require_product doc/html/Tutorial/index.html

command "mv -- $TARBALL .."
command "cd .."
# Can't use "command" function here--breaks redirection:
nice md5sum -b $TARBALL >"$TARBALL.md5sum"
command "rm -rf -- $DISTNAME"

set +e
nice vacuumdb >/dev/null 2>&1 &

log "Finished.  Release tarball is $TMPDIR/$TARBALL"

# Give output time to catch up with command prompt
sleep 2

