#!/bin/bash -e

# The script ensures that all commands succeed unless an error occurred. If it
# does though, the shell terminates the script and our exit handler runs.
trap 'tput bel || :; echo Failed! >&2' EXIT

# Ask the user a yes/no question. This function does not require the user to
# press ENTER after making a selection.
yes_no() {
  local c
  while :; do
    c="$(set +e
         trap 'stty echo -iuclc icanon 2>/dev/null' EXIT INT TERM QUIT
         stty -echo iuclc -icanon 2>/dev/null
         dd count=1 bs=1 2>/dev/null | od -An -tx1)"
    case "$c" in
      " 0a") if [ -n "$1" ]; then
               [ $1 -eq 0 ] && echo "Y" || echo "N"
               return $1
             fi
             ;;
      " 79") echo "Y"
             return 0
             ;;
      " 6e") echo "N"
             return 1
             ;;
      "")    echo "Aborted" >&2
             exit 1
             ;;
      *)     # The user pressed an unrecognized key. As we are not echoing
             # any incorrect user input, alert the user by ringing the bell.
             (tput bel) 2>/dev/null || :
             ;;
    esac
  done
}

# Build Debian package and create all the files that are needed by the
# distribution maintainer.
debian_package() {
  set -e
  (
    # Try to build the package. If things fail, let the exit handler remove all
    # temporary files.
    trap 'rm -rf "${prj}-${ver}" "${prj}_${ver}"*' EXIT

    # Clean up any old temporary files
    rm -rf "${prj}-${ver}" "${prj}_${ver}"*

    # Extract the distribution source archive
    tar zfx "${prj}-${ver}.tar.gz"

    # We want to ship the "debian" directory with the source archive that
    # users download directly from the project web site. This allows them to
    # easily build their own Debian package by following the instructions in
    # INSTALL.Debian.
    # But when preparing our package for direct integration with Debian-based
    # distributions, we have to instead remove the "debian" directory, as the
    # distribution prefers that third-party projects are not built "natively".
    mv "${prj}-${ver}/debian" "${prj}_${ver}_debian"
    tar zfc "${prj}_${ver}.orig.tar.gz" "${prj}-${ver}"
    mv "${prj}_${ver}_debian" "${prj}-${ver}/debian"

    # Reset compatibility level
    echo 7 >"${prj}-${ver}/debian/compat"
    sed -i -e 's/debhelper *([^0-9]*[^)]*)/debhelper (>= 7.0.0)/'             \
        "${prj}-${ver}/debian/control"
    sed -i -e 's/dh_clean *-k/dh_prep/' "${prj}-${ver}/debian/rules"

    # Check that the version number in the debian/changelog file matches
    if [ "$(sed -e 's/^'"${prj}"' *(\([^-]*\)-.*).*/\1/;t1;d;:1;q'            \
             "${prj}-${ver}/debian/changelog")" != "${ver}" ]; then
      echo "Debian changelog file does not match current version number!" >&2
      exit 1
    fi

    # Build Debian packages.
    (cd "${prj}-${ver}"
     fakeroot dpkg-buildpackage -sa -us -uc || :)
    trap '' EXIT

    # Run lintian
    lintian --verbose -I ${prj}_${ver}*_*.changes
  ) || exit 1

  # Revert any changes that might be pending in distributions/debian/*
  local revert="$(svn st |
                  grep distributions/debian |
                  grep '^[^?]' |
                  awk '{ print $2 }' |
                  tac)"
  if [ -n "${revert}" ]; then
    svn revert ${revert}
    rm -f ${revert}
  fi

  # Create distributions/debian if it does not exist yet.
  mkdir -p distributions/debian
  for i in distributions distributions/debian; do
    if [ -z "$(svn st "${i}" 2>/dev/null | grep -v '^[?]')" ]; then
      svn add --depth=empty "${i}"
    fi
  done

  # If this version of files already exists in the distribution directory,
  # we are not yet ready to cut a new release. Just clean up and exit.
  for i in "${prj}_${ver}"[-.]*.*; do
    [ -r "distributions/debian/${i}" ] && {
      rm $(ls "${prj}_${ver}"[-.]* | egrep -v '_*.changes|_*.deb')
      return 0
    }
  done

  # Move new Debian files into release area.
  mv $(ls "${prj}_${ver}"[-.]* | egrep -v '_*.changes|_*.deb')                \
     distributions/debian/
  svn add distributions/debian/"${prj}_${ver}"[-.]*.*

  # Let the caller know that we added new packages.
  return 1
}

# Quick sanity check that we are running from the correct directory
test -r configure.ac

# Make sure there are no stale files
svn update

# Determine Subversion revision number, project name, and public version
# number
{
  rev=$(($(svn info | sed -e 's/^Revision: \(.*\)/\1/;t1;d;:1;q')+1))
  prj="$(sed -e 's/^AC_INIT(\([^,]*\),.*/\1/;t1;d;:1;q' configure.ac)"
  ver="$(sed -e 's/^AC_INIT([^,]*, *\([^,]*\),.*/\1/;t1;d;:1;q' configure.ac)"
} 2>/dev/null

# Update "configure.ac" with the next Subversion revision number. This
# information will trickle down into various source files where it becomes
# part of the user-visible version information.
sed -i -e 's/^\(VCS_REVISION=\).*/\1'"${rev}"'/' configure.ac
touch shellinabox/vt100.jspp shellinabox/shell_in_a_box.jspp

# If the manual page has been changed, make sure that the time stamp will be
# changed, too.
if [ -n "$(svn st shellinabox/shellinaboxd.man.in 2>/dev/null |
           grep '^M')" ]; then
  sed -i -e 's/^\([.]TH .*\)"[^"]*"/\1"'"$(date +'%b %d, %Y')"'"/
             s/2008-2[01][0-9][0-9]/2008-'"$(date +'%Y')"'/g'                 \
      shellinabox/shellinaboxd.man.in
fi

# Always update the year in the user visible copyright statement(s)
for i in shellinabox/shell_in_a_box.jspp                                      \
         shellinabox/vt100.jspp                                               \
         COPYING                                                              \
         debian/copyright; do
  sed -i -e 's/\(2[01][0-9][0-9]-\)2[01][0-9][0-9]/\1'"$(date +'%Y')"'/g' "$i"
done

# If a source file has changed, make sure to update the year in the copyright
# statement for that particular file.
svn st | egrep '^[MA]' | awk '{ print $2 }' |
  egrep '^(shellinabox|libhttp|demo)/' |
  egrep '[.](html|h|c|css|jspp)$' |
  while read -r f; do
   sed -i -e 's/\(2[01][0-9][0-9]-\)2[01][0-9][0-9]/\1'"$(date +'%Y')"'/g' "$f"
  done

# For now, Ubuntu/Hardy is still quite popular. We want to make it easy for
# our users to build Debian packages from source. So, make sure we lock the
# compatibility level at 6. Once we no longer care about maintaining strict
# backwards compatibility, we can lift this restriction.
echo 6 >debian/compat
sed -i -e 's/debhelper *([^0-9]*[^)]*)/debhelper (>= 6.0.0)/' debian/control
sed -i -e 's/dh_prep/dh_clean *-k/' debian/rules

# Build all the sources, create the distribution tar archive, and run some
# basic sanity checks.
make all distcheck

# Build Debian package and create all the files that are needed by the
# distribution maintainer.
msg=
debian_package || {
  msg="${msg}
NOTICE: New version released. Please do not forget to notify distributions"
  if [ -r ~/.shellinabox-notifier ]; then
    while read e; do
      {
        echo "This is an automatically generated e-mail notification that"
        echo "a new release of ShellInABox has just been made available"
        echo "on the project's website at http://shellinabox.com"
        echo
        echo "You had previously requested to be notified when this happens."
      } | mail -s "New ShellInABox release" "$e"
    done
  else
    msg="${msg}
NOTICE: Could not find ~/.shellinabox-notifier. Not sending e-mail..."
  fi
}

svn diff $(svn st |
           egrep -v ' configure$| aclocal.m4$|distributions|^[?]' |
           sed -e 's/^[^ ]* *//') | less
echo -n 'Commit these changes (Y/n): '
yes_no 0 || exit 1
svn commit
echo "${msg}"

trap '' EXIT
exit 0
