#!/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/branch.h ]
then

  versionfile='source/base/branch.h'
  version_macro='BRANCH_VERSION'
  version_int_macro='BRANCH_VERSION_NUMBER'
  version_hex_macro='BRANCH_VERSION_NUMBER_HEX'
  prerelease_macro='BRANCH_PRERELEASE'
  maintainer_macro='BRANCH_MAINTAINER'

  copyright_owner=`sed -n 's/^.*#define [ ]*'"$maintainer_macro"' [ ]*"\([^"]*\)".*$/\1/p' "$versionfile"`

else

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

  version_macro='OFFICIAL_VERSION_STRING'
  version_int_macro='OFFICIAL_VERSION_NUMBER'
  version_hex_macro='OFFICIAL_VERSION_NUMBER_HEX'
  prerelease_macro='POV_RAY_PRERELEASE'

  copyright_owner='Persistence of Vision Raytracer Pty. Ltd.'

fi

ver_povray_h=`sed -n 's/#define [ ]*'"$version_macro"' [ ]*"\([0-9]*\.[0-9]*\.[.0-9]*\)"/\1/p' "$versionfile"`
ver_povray_h_int=`sed -n 's/#define [ ]*'"$version_macro_int"' [ ]*\([0-9]*\)/\1/p' "$versionfile"`
ver_povray_h_hex=`sed -n 's/#define [ ]*'"$version_macro_hex"' [ ]*\(0x[0]*[0-9]*\)/\1/p' "$versionfile"`
prerelease_povray_h=`sed -n 's/^.*#define [ ]*'"$prerelease_macro"' [ ]*"\([^"]*\)".*$/\1/p' "$versionfile"`
ver_VERSION=`cat unix/VERSION`

echo "$versionfile identifies this as version:"
echo "  $ver_povray_h-$prerelease_povray_h"
if [ x"$ver_povray_h_int" != x"" ]
then
  echo "  $ver_povray_h_int"
fi
if [ x"$ver_povray_h_hex" != x"" ]
then
  echo "  0x$ver_povray_h_hex"
fi

if [ x"$ver_povray_h_int" != x"" ]
then
  if [ x"$ver_povray_h_int" != x"`echo $ver_povray_h | 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_povray_h-$prerelease_povray_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"$prerelease_povray_h" = x"" ]
  then
    echo "this does not seem intended to be a prerelease"
  else
    y2k=`date -u -d"2000-01-01" +"%s"`
    timestamp=`date -u +"%s"`
    revision=`expr \( "$timestamp" - "$y2k" \) / 60`
    echo "changes to the POV-Ray code detected, updating prerelease id to $revision."
    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 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
    sed -i \
      -e 's/\(#define [ ]*'"$prerelease_macro"' [ ]*".*[^0-9]\)[0-9][0-9]*"/\1'"$revision"'"/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'"$revision"'/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
else
  echo "changes are limited to accompanying files, no need to update $prerelease_macro."
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]\( '"$copyright_owner"'\)'

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

sed_i_fix $stage

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

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

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

exit 0
