#!/bin/sh
#
# release.sh : build a release tarball
#
# USAGE: release.sh [--security] [--tag TAG POSTFIX] [--postfix POSTFIX]
#                   [--rev REV] PROJECT VERSION [SIGNING-USER]
#
#   The project is either 'httpd-2.0', 'httpd-2.2', 'httpd-2.3'
#
#   The version number is specified as MAJOR.MINOR.PATCH (and will be used in
#   the output tarball name). The script will then look for a CVS tag named
#   "MAJOR.MINOR.PATCH" and export it into a subdirectory (of the current
#   directory). Next, it will run the appropriate commands to prepare and
#   construct the tarball. The subdirectory will be cleaned up upon exit.
#
#   The "signing user" is the name of the key that you'll be signing the
#   release with.
#

RELEASECHECK="`echo $0 | sed 's/release.sh$/releasecheck.sh/'`"
ROLL="`echo $0 | sed 's/release.sh$/roll.sh/'`"

# This forces all exported releases to be on the same timezone
# when SVN props are used inside files.
TZ=UTC

while true
do
  case "$1" in
    --security)
      security_release=1
      shift
      ;;

    --tag)
      tagged_release=1
      tag="$2"
      postfix="$3"
      shift 3
      ;;

    --postfix)
      postfix="$2"
      shift 2 
      ;;

    --rev)
      rev="$2"
      shift 2
      ;;

    --*)
     echo "Unknown option '$1'" >&2
     echo "USAGE: $0 [--security] [--tag TAG POSTFIX] [--postfix POSTFIX] [--rev REV] PROJECT VERSION [SIGNING-USER]" >&2
     echo "  see the comments in this script for more info." >&2
     exit 1
     ;;

    *)
     # apparently there are no options left
     break
     ;;
  esac
done

if test "$#" != 2 && test "$#" != 3; then
  echo "USAGE: $0 [--security] [--tag TAG POSTFIX] [--postfix POSTFIX] [--rev REV] PROJECT VERSION [SIGNING-USER]" >&2
  echo "  see the comments in this script for more info." >&2
  exit 1
fi

# Run tests to ensure that our requirements are met
${RELEASECHECK} || exit 1

project="$1"
version="$2"
user="$3"

case "$1" in
  httpd-2.0)
    ver_path="include/ap_release.h"
    ver_define="AP_SERVER_PATCHLEVEL"

    expected_major="2"
    expected_minor="0"

    branch="branches/2.0.x"

    apr_xxx_in_srclib=1
    apr_tag="0.9.17"
    apu_tag="0.9.15"
    ;;

  httpd-2.2)
    ver_path="include/ap_release.h"
    ver_define="AP_SERVER_PATCHLEVEL"

    expected_major="2"
    expected_minor="2"

    branch="branches/2.2.x"

    apr_xxx_in_srclib=1
    apr_tag="1.3.0"
    apu_tag="1.3.0"
    ;;

  httpd-2.3)
    ver_path="include/ap_release.h"
    ver_define="AP_SERVER_PATCHLEVEL"

    expected_major="2"
    expected_minor="3"

    branch="trunk"

    apr_xxx_in_srclib=1
    apr_tag="1.3.0"
    apu_tag="1.3.0"
    ;;
  *)
    echo "ERROR: '$1' is an unknown project." >&2
    echo "  choose one of: httpd-2.0, httpd-2.2, or httpd-2.3" >&2
    exit 1
esac

major="`echo ${version} | sed 's/\..*$//'`"
minor="`echo ${version} | sed 's/^[0-9]*\.\([0-9]*\)\..*$/\1/'`"
patch="`echo ${version} | sed 's/^.*\.//'`"

if test ${tagged_release}; then
  tagname="${tag}"
else
  tagname="${version}"
fi

dirname="`echo ${project} | sed 's/-[0-9]*\.[0-9]*$//'`"
dirname="${dirname}-${version}"
if test "${postfix}" != ""; then
  postfix="-${postfix}"
  dirname="${dirname}${postfix}"
elif test "${rev}" != ""; then
  postfix="-r${rev}"
  dirname="${dirname}${postfix}"
fi
if test ${security_release}; then
  dirname="${dirname}-security"
fi

if test "$rev" != ""; then
  rev="-r ${rev}"
fi

split="---------------------------------------------------------------------"

echo $split
echo ""

if test ${security_release}; then
  echo "  SECURITY RELEASE"
fi
echo "  Version: ${version}"
echo " Tag name: ${tagname}"
echo "Directory: ${dirname}"
echo ""

if test "${expected_major}" -ne "${major}" || test "${expected_minor}" -ne "${minor}"; then
  echo "ERROR: project doesn't match tag" >&2
  exit 1
fi

if test -d ${dirname}; then
  echo "ERROR: for safety, you must manually remove ${dirname}." >&2
  exit 1
fi


# make sure that the perms are good for the tarball
umask 022

echo $split
echo ""
echo "Starting SVN export of ${project} to ${dirname} ..."
echo ""

if test "${rev}" != ""; then
  svn export ${rev} http://svn.apache.org/repos/asf/httpd/httpd/${branch} ${dirname} > /dev/null || exit 1
else
  svn export http://svn.apache.org/repos/asf/httpd/httpd/tags/${tagname} ${dirname} > /dev/null || exit 1
fi

### Add a check to see if what was checked out matches $vsn

if test ${apr_xxx_in_srclib}; then
  echo "Starting SVN export of apr-${apr_tag} to ${dirname}/srclib ..."
  svn export http://svn.apache.org/repos/asf/apr/apr/tags/${apr_tag} ${dirname}/srclib/apr > /dev/null || exit 1
  echo "Starting SVN export of apr-util-${apu_tag} to ${dirname}/srclib ..."
  svn export http://svn.apache.org/repos/asf/apr/apr-util/tags/${apu_tag} ${dirname}/srclib/apr-util > /dev/null || exit 1
fi

echo $split
echo ""

if test ${tagged_release}; then
#  echo "Fixing up version define (replacing -dev with ${postfix})"
#  mv ${dirname}/${ver_path} ${dirname}/${ver_path}~
#  cat ${dirname}/${ver_path}~ | sed -e "s/\(${ver_define}.*\)-dev/\1${postfix}/" > ${dirname}/${ver_path}
#  rm ${dirname}/${ver_path}~
  echo ""

  echo $split
  echo ""

elif grep "#define.*${ver_define}.*-dev" ${dirname}/${ver_path} > /dev/null; then
  echo "ERROR: ${ver_path} still defines a development version." >&2
  echo "       This script can only produce formal releases." >&2
  exit 1
fi

if test ${security_release}; then
  patch_dir="${dirname}-patches"

  if test -d "${patch_dir}"; then
    echo "Starting CVS update of ${patch_dir}"
    echo ""
    ( cd ${patch_dir} &&
      cvs up -dP 2>/dev/null
    ) || exit 1
    echo ""
  else
    echo "Starting CVS checkout of httpd-security/patches/${version}-dev to ${patch_dir}"
    echo ""
    cvs -d cvs.apache.org:/home/cvs co -d ${patch_dir} httpd-security/patches/${version}-dev > /dev/null || exit 1
    echo ""
  fi
  
  echo "Applying patches..."
  for p in `find ${patch_dir} -type f -name '*.patch'`
  do
    ( cd ${dirname} &&
      cat ../${p} | patch -p0 --no-backup-if-mismatch
    ) || exit 1
  done
  
  echo $split
  echo ""
fi

echo "Copying CHANGES file"
echo ""

cp ${dirname}/CHANGES CHANGES_${major}.${minor}

${ROLL} ${dirname} ${user} || exit 1
