#!/bin/sh

tab=`echo -e '\t'`
nl='
'

########################################################################################################################
#
# Workarounds for quirks of particular runtime environments.

# A single sed expression to fix line endings, passed to sed via the '-e' option as the last expression to process.
# By default, this is a no-op expression.
sed_newline_fix=''

# A function to fix quirky behaviour of 'sed -i', called with a list of all files previously processed by 'sed -i'.
# By default, this is a no-op function.
sed_i_fix() { : ; }

case "$(uname -s)" in

   Darwin)
     echo 'Running on Mac OS X'
     # no known quirks to work around
     ;;

   Linux)
     echo 'Running on Linux'
     # no known quirks to work around
     ;;

   CYGWIN*|MINGW32*|MSYS*)
     echo 'Running on MS Windows'
     # 'sed' output has LF line endings, but we want CR+LF for consistency.
     sed_newline_fix='s/$/\r/g'
     # 'sed -i' sets the edited file to read-only.
     sed_i_fix() { chmod u+w "$@" ; }
     ;;

   *)
     echo 'Running on unidentified OS' 
     # no known quirks to work around
     ;;

esac

# List of all the directories that contain files which may have an impact on the POV-Ray binary, and are under control
# of the POV-Ray team, as a regular expression for grep -E to match file names.
# Note that this does not include auxiliary source code such as unit tests (as they have no impact on the POV-Ray
# binary), nor libraries (as they are not under control of the POV-Ray team).
src_dir_pattern="^source/|^vfe/|^platform/|^mac/|^unix/|^windows/"

# List of all the file extensions used for C/C++ source code, as a regular expression for grep -E to match file names.
src_ext_pattern='\.c$|\.cpp$|\.h$|\.hpp$'

########################################################################################################################
#
# Verify that all the version identifiers in the source tree match.

if [ -f source/base/version.h ]
then
  versionfile=source/base/version.h
else
  versionfile=source/backend/povray.h
fi

ver_povray_h_3=`sed -n 's/^[ ]*#define [ ]*OFFICIAL_VERSION_STRING [ ]*"\([0-9]*\.[0-9]*\.[0-9]*\)"/\1/p' "$versionfile"`
ver_povray_h=`sed -n 's/^[ ]*#define [ ]*OFFICIAL_VERSION_STRING [ ]*"\([0-9.]*\)"/\1/p' "$versionfile"`
ver_povray_h_int=`sed -n 's/^[ ]*#define [ ]*OFFICIAL_VERSION_NUMBER [ ]*\([0-9]*\)/\1/p' "$versionfile"`
ver_povray_h_hex=`sed -n 's/^[ ]*#define [ ]*OFFICIAL_VERSION_NUMBER_HEX [ ]*\(0x[0]*[0-9]*\)/\1/p' "$versionfile"`
ver_version_h_major=`sed -n 's/^[ ]*#define [ ]*POV_RAY_MAJOR_VERSION_INT [ ]*\([0-9]*\)/\1/p' "$versionfile"`
ver_version_h_minor=`sed -n 's/^[ ]*#define [ ]*POV_RAY_MINOR_VERSION_INT [ ]*\([0-9]*\)/\1/p' "$versionfile"`
ver_version_h_revision=`sed -n 's/^[ ]*#define [ ]*POV_RAY_REVISION_INT [ ]*\([0-9]*\)/\1/p' "$versionfile"`
ver_version_h_patchlevel=`sed -n 's/^[ ]*#define [ ]*POV_RAY_PATCHLEVEL_INT [ ]*\([0-9]*\)/\1/p' "$versionfile"`
ver_version_h_prerelease=`sed -n 's/^[ ]*#define [ ]*POV_RAY_PRERELEASE [ ]*"\([^"]*\)".*$/\1/p' "$versionfile"`
if [ -f unix/VERSION ]
then
  ver_VERSION=`cat unix/VERSION`
else
  ver_VERSION=""
fi

if [ x"$ver_povray_h" != x"" ]
then
  ver_version_h_3="$ver_povray_h_3"
  ver_version_h="$ver_povray_h"
else
  ver_version_h_3="$ver_version_h_major.$ver_version_h_minor.$ver_version_h_revision"
  if [ x"$ver_version_h_patchlevel" != x"" ] && [ $ver_version_h_patchlevel -gt 0 ]
  then
    ver_version_h="$ver_version_h_3.$ver_version_h_patchlevel"
  else
    ver_version_h="$ver_version_h_3"
  fi
fi

if [ x"$ver_version_h_prerelease" != x"" ]
then
  ver_version_h="$ver_version_h-$ver_version_h_prerelease"
fi

echo "$versionfile identifies this as version:"
echo "  $ver_version_h"
if [ x"$ver_povray_h_int" != x"" ]
then
  echo "  $ver_povray_h_int"
fi
if [ x"$ver_povray_h_hex" != x"" ]
then
  echo "  $ver_povray_h_hex"
fi

if [ x"$ver_povray_h_int" != x"" ]
then
  if [ x"$ver_povray_h_int" != x"`echo $ver_version_h_3 | sed 's/\.//g'`" ]
  then
    echo "MISMATCH."
    exit 1
  fi
fi

if [ x"$ver_povray_h_hex" != x"" ]
then
  if [ x"`echo $ver_povray_h_hex | sed 's/0x0*//g'`" != x"$ver_povray_h_int" ]
  then
    echo "MISMATCH."
    exit 1
  fi
fi

if [ x"$ver_VERSION" != x"" ]
then
  echo "unix/VERSION identifies this as version:"
  echo "  $ver_VERSION"
  if [ x"$ver_VERSION" != x"$ver_version_h" ]
  then
    echo "MISMATCH."
    exit 1
  fi
fi

########################################################################################################################
#
# Update prerelease id (trailing numeric portion) if there is any change to the actual program code.
# We're setting the prerelease id to the number of minutes since 2000-01-01 00:00.

if git diff --cached --name-only | grep -E "$src_dir_pattern|^libraries/" >/dev/null
then
  if [ x"$ver_version_h_prerelease" = x"" ]
  then
    echo "this does not seem intended to be a prerelease"
  else
    prerelease_id=`echo "$ver_version_h_prerelease" | sed 's/^.*[^0-9]\([0-9]*\)$/\1/g'`
    echo "prerelease id is $prerelease_id"
    if [ x"$prerelease_id" = x"" ]
    then
      echo "no trailing number to auto-increment"
    elif [ "$prerelease_id" -le "999999" ]
    then
      echo "trailing number does not seem to be intended for auto-increment"
    else
      y2k=`date -u -d"2000-01-01" +"%s"`
      timestamp=`date -u +"%s"`
      prerelease_id=`expr \( "$timestamp" - "$y2k" \) / 60`
      echo "changes to the POV-Ray code detected, updating prerelease id to $prerelease_id."
      if git diff --name-only "$versionfile" | grep "$versionfile" >/dev/null
      then
        echo "ERROR: Unstaged changes to $versionfile detected, can't safely update prerelease id."
        exit 1
      fi
      if [ -f unix/VERSION ]
      then
        if git diff --name-only "unix/VERSION" | grep "unix/VERSION" >/dev/null
        then
          echo "ERROR: Unstaged changes to unix/VERSION detected, can't safely update prerelease id."
          exit 1
        fi
      fi
      sed -i \
        -e 's/\(#define [ ]*POV_RAY_PRERELEASE [ ]*".*[^0-9]\)[0-9][0-9]*"/\1'"$prerelease_id"'"/g' \
        -e "$sed_newline_fix" \
        "$versionfile" >/dev/null 2>/dev/null
      sed_i_fix "$versionfile"
      # stage update
      git add "$versionfile" >/dev/null 2>/dev/null
      if [ -f unix/VERSION ]
      then
        sed -i \
          -e 's/\([^0-9]\)[0-9][0-9]*$/\1'"$prerelease_id"'/g' \
          -e "$sed_newline_fix" \
          unix/VERSION >/dev/null 2>/dev/null
        sed_i_fix unix/VERSION
        # stage update
        git add unix/VERSION >/dev/null 2>/dev/null
      fi
    fi
  fi
else
  echo "changes are limited to accompanying files, no need to update POV_RAY_PRERELEASE."
fi

########################################################################################################################
#
# Sanitize & sanity-check changed C/C++ source files:
# - Update copyright year
# - Convert leading tabs to spaces (limited)
# - Trim trailing spaces
# - check for presence of copyright statement
# - check for proper doxygen @file tag
# - check for tab characters

year=`date -u +"%Y"`
copytext='\(Copyright [1-2][90][0-9][0-9]-\)20[0-9][0-9]\( Persistence of Vision Raytracer Pty. Ltd.\)'

unstaged=`git diff --name-only`

errors=""
stage=""
for fname in `git diff --cached --name-only | grep -E "$src_dir_pattern|^tests/source/" | grep -E "$src_ext_pattern"`
do

  if [ -f "$fname" ]
  then

    echo "Sanitizing $fname"

    if echo "$unstaged" | grep "$fname" >/dev/null 2>/dev/null
    then
      errors="$errors$nl$fname: unstaged changes detected, can't safely sanitize file."
    else

      # Update...
      # - copyright year
      # - leading tabs (replace with spaces)
      # - trailing spaces (remove)

      year=`date -u +"%Y"`
      sed -i \
        -e 's/'"$copytext"'/\1'"$year"'\2/g' \
        -e 's/^\t\t\t\t\t/                    /g' \
        -e 's/^\t\t\t\t/                /g' \
        -e 's/^\t\t\t/            /g' \
        -e 's/^\t\t/        /g' \
        -e 's/^\t/    /g' \
        -e 's/ *$//g' \
        -e "$sed_newline_fix" \
        "$fname" >/dev/null 2>/dev/null

      # mark updates for staging
      stage="$stage$nl$fname"

    fi

    # Check for copyright statement

    if ! grep "$copytext" "$fname" >/dev/null
    then
      errors="$errors$nl$fname: missing copyright statement"
    fi

    # Check for proper doxygen @file tag

    shortfname=`echo "$fname" | sed 's/^source\///g'`
    if ! grep '@file  *'"$shortfname"'$' "$fname" >/dev/null
    then
      errors="$errors$nl$fname: missing doxygen '@file $shortfname' tag"
    elif grep "@file " "$fname" | sed 's|  *'"$shortfname"' *||g' | grep "@file " >/dev/null
    then
      errors="$errors$nl$fname: wrong doxygen '@file ...' tag"
    fi

    # Check for any remaining tab characters

    if grep "$tab" "$fname" >/dev/null
    then
      errors="$errors$nl$fname: tab characters found"
    fi

  else

    echo "$fname seems to have been moved or deleted."

  fi

done

if [ x"$stage" != x"" ]
then
  sed_i_fix $stage
fi

if [ x"$errors" != x"" ]
then
  echo "$errors"
  exit 1
fi

# Stage updates
git add $stage >/dev/null 2>/dev/null

########################################################################################################################
#
# Done.

exit 0
