#!/bin/sh
#
# Create svnversion.h file or get package version
#
# Home page of code is: https://www.smartmontools.org
#
# Copyright (C) 2024 Christian Franke
#
# SPDX-License-Identifier: GPL-2.0-or-later
#
# $Id: getversion.sh 5597 2024-01-24 10:30:14Z chrfranke $
#

set -e
myname=$0

usage()
{
  cat <<EOF
Usage: $myname [-i] [-pq] [-r] [METHOD...] [> svnversion.h]

  -i          Print new contents of svnversion.h
  -p          Print package version from configure.ac
  -q          Prepend 'pre-' to package version if pre-release (implies -p)
  -r          Print svn revision (like 'svnversion')

  METHOD...   One or more of 'svn', 'ids' or 'git' [default: svn ids git]
EOF
  exit 1
}

error()
{
  echo "$myname: $*" >&2
  exit 1
}

i_opt=false; p_opt=false; q_opt=false; r_opt=false
while true; do case $1 in
  -i) i_opt=true ;;
  -p) p_opt=true ;;
  -q) p_opt=true; q_opt=true ;;
  -r) r_opt=true ;;
  -*) usage ;;
  *) break ;;
esac; shift; done
$i_opt || $p_opt || $r_opt || usage

if [ $# -ne 0 ]; then
  methods=$*
  for m in $methods; do case $m in
    svn|ids|git) ;;
    *) usage ;;
  esac; done
else
  methods="svn ids git"
fi

srcdir=${myname%/*}
test "$srcdir" != "$myname" || error 'unknown $srcdir'

files="
  ChangeLog NEWS Makefile.am configure.ac smart*.in
  *.cpp *.h os_win32/*.cpp os_win32/*.h
"
(cd "$srcdir" && ls -d $files >/dev/null) || error "sources not found in $srcdir"

revision_from_svn()
{
  local r t
  r=$(cd "$srcdir" && svnversion 2>/dev/null) || return 1
  case $r in [1-9][0-9]*) ;; *) return 1 ;; esac
  t=$(cd "$srcdir" && TZ='' LC_ALL=C svn info 2>/dev/null) || return 1
  t=$(echo "$t" | sed -n 's,^.* Date: *\(2[-0-9]*\) \([0-9][:0-9]*\) .*$,\1 \2,p')
  test -n "$t" || return 1
  svnrev=$r; revdate=${t% *}; revtime=${t#* }
  origin="svn info"
}

revision_from_ids()
{
  local x
  x=$(cd "$srcdir" && \
      sed -n 's,^.*\$[I][d]: [^ ]* \([0-9][0-9]*\) \([0-9][-0-9]*\) \([0-9][:0-9]*\)Z [^$]*\$.*$,\1 \2 \3,p' $files \
      | sort -n -r | sed -n 1p)
  test -n "$x" || return 1
  svnrev=${x%% *}; x=${x#* }; revdate=${x% *}; revtime=${x#* }
  origin="Id strings"
}

revision_from_git()
{
  local h r t x
  x=$(cd "$srcdir" && TZ='' LC_ALL=C git log -1 --date=iso 2>/dev/null) || return 1
  h=$(echo "$x" | sed -n 's,^commit \([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]\).*$,\1,p')
  t=$(echo "$x" | sed -n 's,^Date: *\(2[-0-9]*\) \([0-9][:0-9]*\) .*$,\1 \2,p')
  r=$(echo "$x" | sed -n 's,^.*git-svn-id: [.:/a-z]*/smartmontools/code/trunk@\([1-9][0-9]*\) 4ea69e.*$,\1,p')
  test "${h:+y}${r:+y}${t:+y}" = "yyy" || return 1
  test -z "$(cd "$srcdir" && git status -s -uno 2>&1)" || r="${r}M"
  svnrev=$r; revdate=${t% *}; revtime=${t#* }; githash=$h
  origin="git log"
}

if $i_opt || $r_opt; then
  svnrev=; revdate=; revtime=; githash=
  origin="missing information"
  for m in $methods; do
    revision_from_$m || continue
    break
  done

  if $i_opt; then
    cat <<EOF
/* svnversion.h.  Generated by ${myname##*/} from $origin.  */
EOF
    test -z "$svnrev" || cat << EOF
#define SMARTMONTOOLS_SVN_REV  "$svnrev"
#define SMARTMONTOOLS_SVN_DATE "$revdate"
#define SMARTMONTOOLS_SVN_TIME "$revtime"
EOF
    test -z "$githash" || cat <<EOF
#define SMARTMONTOOLS_GIT_HASH "$githash"
EOF
  fi

  if $r_opt; then
    test -n "$svnrev" || error "svn revision not found using $methods"
    echo "$svnrev"
  fi
fi

if $p_opt; then
  p=$(sed -n 's|^AC_INIT[^,]*, *\[\([0-9.]*\)\] *,.*$|\1|p' "$srcdir/configure.ac") || exit 1
  test -n "$p" || error "package version not found in $srcdir/configure.ac"
  if $q_opt; then
    x=$(sed -n 's|^smartmontools_release_date=\(.*\)$|\1|p' "$srcdir/configure.ac") || exit 1
    case $x in
      20*) ;;
      \ \#*) p="pre-$p" ;;
      *) error "unable to detect pre-release state in $srcdir/configure.ac"
    esac
  fi
  echo "$p"
fi
