#!/usr/bin/env bash

# PROGRAMMING NOTE: apparently some git commands report
# inaccurate information if the current directory isn't
# root repository directory where the source files live.

orig_dir="$(pwd)"
top_srcdir="$1"
vers_part="$2"
cd "$top_srcdir"

INFILE=configure.ac
MIN_GIT_VERSION="1.8"   # (earlier versions of git return inaccurate results)

#-----------------------------------------------------------
#              vercomp  --  compare versions
#-----------------------------------------------------------
#
#   $1:  first version to be compared   (e.g. "1.2.3")
#   $2:  expected relationship          (e.g. ">")
#   $3:  second version to be compared  (e.g. "1.2")
#
# The algorithm takes into account leading zeros as well
# as missing components (4.08 < 4.08.01, 3.2.0.9 > 3.2),
# but only exact equality is supported for text strings
# which have non-numeric components (1.2rc3 = 1.2rc3).
#
# Returns:  0 = success  if relationship is true
# Returns:  1 = failure  if relationship is false
#
# We use 0 for true and 1 for false so that the caller
# can do such things as:
#
#     if vercomp 1.2.3 '>' 1.2.0; then
#       echo "True!"
#     else
#       echo "FALSE!"
#     fi
#
#-----------------------------------------------------------

vercomp()
{
  local op

  _vercomp $1 $3

  case $? in
      0) op='=';;
      1) op='>';;
      2) op='<';;
  esac

  if [[ $op != $2 ]]; then
    return 1
  else
    return 0
  fi
}

#-----------------------------------------------------------
#              (vercomp helper function)
#-----------------------------------------------------------
_vercomp()
{
  #  rc = 0:    $1 = $2    $1  equals        $2
  #  rc = 1:    $1 > $2    $1  greater than  $2
  #  rc = 2:    $1 < $2    $1  less than     $2

  if [[ $1 == $2 ]]; then
    return 0
  fi

  local IFS=.
  local i ver1=($1) ver2=($2)

  # Fill empty fields in ver1 with zeros

  for ((i=${#ver1[@]}; i<${#ver2[@]}; i++)); do
    ver1[i]=0
  done

  for ((i=0; i<${#ver1[@]}; i++)); do

    if [[ -z ${ver2[i]} ]]; then
      # Fill empty fields in ver2 with zeros
      ver2[i]=0
    fi

    if [[ 10#${ver1[i]} > 10#${ver2[i]} ]]; then
      return 1
    fi

    if [[ 10#${ver1[i]} < 10#${ver2[i]} ]]; then
      return 2
    fi

  done

  return 0
}

#------------------------------------------------------------------------------
#                             M A I N
#------------------------------------------------------------------------------

# Extract the VERS_MAJ, VERS_INT and VERS_MIN values from $INFILE

VERS_MAJ=$(grep -o -a -m 1  '^VERS_MAJ=[0-9][0-9]*'  $INFILE)
VERS_INT=$(grep -o -a -m 1  '^VERS_INT=[0-9][0-9]*'  $INFILE)
VERS_MIN=$(grep -o -a -m 1  '^VERS_MIN=[0-9][0-9]*'  $INFILE)
VERS_DEV=$(grep -o -a -m 1  '^VERS_DEV=[0-9][0-9]*'  $INFILE)

# Result of above is "VERS_xxx=n". The below does the assignment.

eval $VERS_MAJ
eval $VERS_INT
eval $VERS_MIN
eval $VERS_DEV

# PROGRAMMING NOTE: must check for the existence of both the .git
# directory as well as the git command itself since either may exist
# or not exist independent of the other. Only when both are true
# can we then safely query/use the git repository values.

if ! test -d "./.git" ||
   ! type "git" >/dev/null 2>/dev/null;  then

  # Can't query the git repository since the .git directory doesn't
  # exist (i.e. this directory isn't a git repository clone) or else
  # the git command doesn't exist (i.e. git itself isn't installed)

  VERS_BLD="0"
  git_hash=""
  modified_str=""

else

  # The current directory appears to be a git repository clone AND the
  # git command exists (i.e. git *IS* installed), so we can safely ask
  # git for some repository values that we can then use in our VERSION.

  # Determine if any local modifications exist. PLEASE NOTE that doing
  # "update-index --refresh" beforehand is seemingly critical to ensure
  # accurate "diff-index" results with some versions of git.

  git update-index --refresh -q > /dev/null 2>&1
  git diff-index --quiet HEAD

  if test "$?" == "0"; then
    modified_str=""
  else
    # Check for possibly inaccurate results
    gitvers=$(git --version | egrep -o "([0-9]{1,}\.)+[0-9]{1,}" | head -n 1)
    if vercomp $gitvers '>' $MIN_GIT_VERSION; then
      modified_str="-modified"
    else
      modified_str="-modified(?)"   # (indicate questionable results)
    fi
  fi

  # Extract the short git hash of the repository (usually the last commit)

  git_hash=-g$(git rev-parse --short HEAD)

  # Count the number of commits and use that as our "build" number

  # PROGRAMMING NOTE: we purposely do NOT use the simpler, newer, easier,
  # slightly faster, and harder to get wrong "rev-list --count" technique,
  # since older gits that come with some still in use older distros likely
  # don't understand the "--count" option.  Thus, we use the slightly
  # slower, older, more complex and much easier to get wrong technique
  # of piping the output of "log --pretty..." into "wc -l".  Please also
  # note that, unlike many broken implementations that are out there, we
  # correctly use "tformat" and not "format" to ensure an accurate count.

  VERS_BLD=$(($(git log --pretty=tformat:'' | wc -l)))

  if test "$VERS_BLD" == "0"; then

    # Try "format" instead of "tformat"...
    VERS_BLD=$(($(git log --pretty=format:'' | wc -l)))

    if test "$VERS_BLD" != "0"; then

      # increment by 1 (because "format" was used, not "tformat")
      VERS_BLD=$((++VERS_BLD))

    else
      # Last chance: use new "rev-list --count" method
      VERS_BLD=$(($(git rev-list --count HEAD)))
    fi
  fi
fi


# Make sure all required variables have a value

if test "x$VERS_MAJ" = "x"; then
           VERS_MAJ=0
fi
if test "x$VERS_INT" = "x"; then
           VERS_INT=0
fi
if test "x$VERS_MIN" = "x"; then
           VERS_MIN=0
fi
if test "x$VERS_BLD" = "x"; then
           VERS_BLD=0
fi
if test "x$VERS_DEV" = "x"; then
           VERS_DEV=0
fi


# Determine whether this is an official formal release version,
# or a between formal releases intermediate development version.

if test "$VERS_DEV" == "0"; then
         dev_string=""          # (official formal release version)
else
         dev_string="-DEV"      # (between release development version)
fi


# Construct a quoted VERSION string value

QUOTE='"'
VERSION="${QUOTE}${VERS_MAJ}.${VERS_INT}.${VERS_MIN}.${VERS_BLD}-SDL${dev_string}${git_hash}${modified_str}${QUOTE}"


# Finally, return (via echo) the desired version component back to the caller

if   test "$vers_part" == "VERS_MAJ"; then
                     echo $VERS_MAJ

elif test "$vers_part" == "VERS_INT"; then
                     echo $VERS_INT

elif test "$vers_part" == "VERS_MIN"; then
                     echo $VERS_MIN

elif test "$vers_part" == "VERS_BLD"; then
                     echo $VERS_BLD

elif test "$vers_part" == "VERS_DEV"; then
                     echo $VERS_DEV

elif test "$vers_part" == "VERSION"; then
                     echo $VERSION
else
                     echo $VERSION
fi


#  DONE!  Exit back to caller...

cd "$orig_dir"
exit 0
