#!/bin/sh

# Copyright (C) 2010  International Business Machines and others.
# All Rights Reserved.
# This file is distributed under the Eclipse Public License.
# It is part of the BuildTools project in COIN-OR (www.coin-or.org)
#
# $Id: commit_new_release 3599 2016-07-20 15:32:26Z stefan $
#
# Author: Andreas Waechter     IBM      2007-06-21
# Modified by: Lou Hafer       SFU	2008-04-17
#              Lou Hafer       SFU	2010-06-29	major rewrite

#set -x -v

set -e

# Know thy self. If there are no '/' chars in the command name, we're running
# in the current directory. Otherwise, strip the command name, leaving the
# prefix.  Coin-functions is expected to live in the same directory.  As of
# the original version (100602), this script doesn't need coin-functions,
# but this still has some value as a consistency check.

if expr "$0" : '.*/.*' >/dev/null 2>&1 ; then
  cmdDir=`echo $0 | sed -e 's,\(.*\)/[^/]*,\1,'`
else
  cmdDir='.'
fi
cmdDir=`cd $cmdDir ; pwd`
if test -r $cmdDir/coin-functions ; then
  . $cmdDir/coin-functions
else
  echo "Cannot find utility functions file coin-functions; exiting."
fi

# We need at least one parameter. The default is a dry run (dryRun = 1).

printHelp=0
dryRun=1
dirToCommit=

if test "$#" -eq 0; then
  printHelp=1
else

# Process the parameters. A parameter without an opening `-' is assumed to be
# the spec for the directory to be committed. (Strip any trailing '/'. Some
# people add it, but the script doesn't expect it.)

  while test $# -gt 0 && test $printHelp = 0 ; do
    case "$1" in
      -h* | --h*)
	   printHelp=1
	   ;;
      -c* | --c*)
	   dryRun=0
	   ;;
       -*) echo "$0: unrecognised command line switch '"$1"'."
	   printHelp=1
	   ;;
	*) dirToCommit=`echo $1 | sed -e 's,/$,,'`
	   ;;
    esac
    shift
  done
fi

# What are we committing?

if test -z "$dirToCommit" ; then
  printHelp=1
fi

if test $printHelp = 1 ; then
  cat <<EOF
usage: commit_new_release [-c] <directory_to_commit>

  By default, commit_new_release is a dry run, printing the commands that
  will be executed. When you're confident that everything looks right, use
  the -c (--commit) flag to commit the release.
EOF
  exit 1
fi

# Remember what was done during generation of the new release.

if test -r $dirToCommit/.new_release_data; then
  . $dirToCommit/.new_release_data
else
  echo ''
  echo "Error: the file .new_release_data is not present in $dirToCommit."
  echo 'Are you running commit_new_release in the same directory where you'
  echo 'ran prepare_new_release?'
  echo ''
  exit 1
fi

# Confirm that we're in the proper directory.

currDir=`pwd`
if test "$currDir/$dirToCommit" != "$topBuildDir" ; then
  echo "According to $dirToCommit/.new_release_data, the release candidate was assembled"
  echo "in $topBuildDir."
  echo "You have asked to commit $currDir/$dirToCommit."
  echo "There is some confusion. Repository is unchanged."
  exit 1
fi

if test $dryRun = 1 ; then
  echo "Dry run; testing commit of $dirToCommit."
else
  echo "Committing $dirToCommit."
fi

# Change to the checkout directory.

cd $coDir

# If there are externals set on this directory, confirm that
# .Externals.original is present so that we can restore them later.

releaseExternals=`svn propget svn:externals . || true`
if test -n "$releaseExternals" ; then
  if test -r .Externals.original ; then
    :
  else
    echo "This project has externals, but no .Externals.original file"
    echo "is present to restore them. Repository is unchanged."
    exit 1
  fi
fi

# Make some short-form URLs by stripping the COIN URL base.

stableURLshort=`echo $stableURL | sed -e "s,$coinURL/\(.*\),\1,"`
releaseURLshort=`echo $releaseURL | sed -e "s,$coinURL/\(.*\),\1,"`

# Do we have to svn add Dependencies? If this query comes up with a leading
# `?', the answer is yes. If Dependencies is entirely absent or unchanged,
# we'll get a null string. If it's modified, we'll have a leading `M'.

dependStatus=`svn status Dependencies`
if expr "$dependStatus" : '?.*Dependencies.*' >/dev/null 2>&1 ; then
  cmd='svn add Dependencies'
  echo $cmd
  if test $dryRun = 0 ; then
    eval $cmd
  fi
fi

# Now, do we really need to to a temporary commit? BuildTools is the poster
# child, there are no changes at time of writing (100629). Do an svn status
# on the checkout directory and see if anything comes up as modified.

if svn status $coDir | egrep '^M' 2>&1 >/dev/null ; then
  doCommit=yes
else
  doCommit=no
fi

if test $doCommit = yes ; then

# Commit the release to stable so we can do a repository-side copy to create
# the release.

  echo ''
  echo "===> Temporarily committing release candidate to $stableURLshort ..."
  echo ''

  rev_num_before=`svn info . | grep -E '^Revision:' | sed -e 's|Revision: ||'`
  echo "Revision number before commit: $rev_num_before"

  cmd="svn ci -m \"temporarily committing release candidate\""
  echo $cmd
  if test $dryRun = 0 ; then
    eval $cmd
  fi

# Update to confirm the commit. Avoid pulling in externals --- if we're doing
# multiple commits of new releases, they may not exist. As it stands, the
# main purpose of this call is to allow us to easily obtain the current
# revision.
# It might be useful to strengthen this and check that the value
# is what we're expecting --- one greater than the revision before
# commit. `--ignore-externals' could be made provisional on the existence
# of all externals by passing a boolean through .new_release_data. This
# would strengthen the update, in that the update would confirm existence
# of the externals.

  cmd='svn update --ignore-externals'
  echo $cmd
  if test $dryRun = 0 ; then
    eval $cmd
  fi

  rev_num=`svn info . | grep -E '^Revision:' | sed -e 's|Revision: ||'`
  echo "Current revision number is: $rev_num"

fi

# End preparatory commit.

# Create the release with a repository-side copy.

echo ''
echo "===> Creating new release $releaseURLshort from $stableURLshort (rev $rev_num) ..."
echo ''

cmd="svn copy -m \"creating $releaseURLshort from $stableURLshort (rev $rev_num)\" $stableURL $releaseURL"
echo $cmd
if test $dryRun = 0 ; then
  eval $cmd
fi

# Restore the original stable branch.

if test $doCommit = yes ; then

# And restore the stable branch to its original condition. Start by reverting
# to the original externals.

  if test -r .Externals.original ; then
    echo ''
    echo '===> Restoring original externals ...'
    echo ''
    cmd="svn propset -F .Externals.original svn:externals ."
    echo $cmd
    if test $dryRun = 0 ; then
      eval $cmd
      rm .Externals.original
    fi
  fi

# For every .bak file that we created, revert it. 

  if test -n "$bak_files" ; then
    echo ''
    echo '===> Restoring modified files ...'
    echo ''
    for i in $bak_files; do
      cmd="cp $i.bak $i ; rm $i.bak"
      if test $dryRun = 1 ; then
	echo "$cmd"
      else
	eval $cmd
      fi
    done
  fi

# Rebuild configure and Makefile.in files.

  echo ''
  echo '===> Executing run_autotools to restore configuration files ...'
  echo ''
  curdir=`pwd`
  cd $topBuildDir
  cmd="./BuildTools/run_autotools"
  echo $cmd
  if test $dryRun = 0 ; then
    eval $cmd
  fi
  cd "$curdir"

# Commit the restored stable branch.

  echo ''
  echo "===> Committing restored $stableURLshort ..."
  echo ''

  cmd="svn ci -m \"restoring $stableURLshort\""
  echo $cmd
  if test $dryRun = 0 ; then
    eval $cmd
  fi

fi

# End restorative commit.

cd $topBuildDir
cmd="rm .new_release_data"
if test $dryRun = 0 ; then
  eval $cmd
fi

cd $startDir
echo ''
echo "Done, new release $releaseURLshort created."
echo ''
echo "You can now delete the directory $topBuildDir including subdirectories"

