#!/bin/bash
# automaint -- batch automatic maintainance tool of the autodist suite
# Copyright (C) 2013-2026 by Silvan Calarco <silvan.calarco@mambasoft.it>
#
# Released under the terms of the GNU GPL release 3 license
#
. /usr/share/autodist/VERSION
me=(${0##*/} $VERSION)

# First in vector is base arch
. /etc/autodist/config

function usage() {
   echo "\
${me[0]} ${me[1]}
"$"Copyright (C) 2013-2026 Silvan Calarco <silvan.calarco@mambasoft.it>""
"$"Released under the terms of the GNU GPL v3 license"
   echo "
"$"Batch automatic maintainance tool of the autodist suite.""

"$"Usage"":
   $me -s repository -d repository [-p repository] [-h] [-t] [-v]

   -d repository      "$"Main destination repository
   -p repository      "$"Port repository
   -s repository      "$"Automatic/Staging builds source repository

   -h                 "$"Show this help and exit
   -t                 "$"Test mode (no change will be made)
   -v                 "$"Verbose output
"

}

# for webbuild message
function cgi_encodevar() {
  local string="${1}"
  local strlen=${#string}
  local encoded=""

  for (( pos=0 ; pos<strlen ; pos++ )); do
     c=${string:$pos:1}
     case "$c" in
        [-_.~a-zA-Z0-9] ) o="${c}" ;;
        * )               printf -v o '%%%02x' "'$c"
     esac
     encoded+="${o}"
  done
  echo "${encoded}"    # You can either set a return variable (FASTER) 
#  REPLY="${encoded}"   #+or echo the result (EASIER)... or both... :p
}

# get_pkg_buildinfo - retrieve package metadata via the distroquery REST API.
#   On success sets the global variables pkg_name, pkg_version, pkg_release,
#   pkg_arch, pkg_buildtime, pkg_builds[], pkg_archs[].
#
# $1: repository name
# $2: architecture, or "any" to auto-detect
# $3: package name (optional)
function get_pkg_buildinfo() {

   local pkg i a

   [ $1 ] && rep=$1 || exit 1
   [ $2 ] && buildarch=$2 || exit 1
   [ $3 ] && pkg=$3

   pkg_archs=();
   pkg_header=();
   pkg_builds=();
   pkg_obsoletes=();
   pkg_list=();

   unset pkg_name pkg_arch pkg_version pkg_release \
         pkg_group pkg_license pkg_size pkg_buildtime pkg_altrep pkg_repository

   local _distroquery_output _distroquery_ret
   if [ "$pkg" ]; then
      if [ "$buildarch" = "any" ]; then
         _distroquery_output=$(autodist-distroquery package-all-archs "$rep" "$pkg" 2>&1)
      else
         _distroquery_output=$(autodist-distroquery package "$rep" "$pkg" "$buildarch" 2>&1)
      fi
   else
      _distroquery_output=$(autodist-distroquery repository "$rep" 2>&1)
   fi
   _distroquery_ret=$?
   if [ $_distroquery_ret -ne 0 ]; then
      echo "ERROR: autodist-distroquery failed (exit code $_distroquery_ret): $(echo "$_distroquery_output" | grep "^ERROR:" | head -1)" >&2
      return $_distroquery_ret
   fi
   eval $(echo "$_distroquery_output" | grep -v "^ERROR:")
}

[ $# -gt 0 ] || { usage ; exit 1; }

for ((i=1; i<=$#; i++)); do
   case ${!i} in
      -s) shift
          SOURCE_REPOSITORY="${!i}"
          ;;
      -d) shift
          DEST_REPOSITORY="${!i}"
          ;;
      -p) shift
          PORT_REPOSITORY="${!i}"
          ;;
      -t) TESTMODE=1
          ;;
      -v) VERBOSE=1
          ;;
      -h|--help)
          usage
          exit 0
          ;;
   esac
done

[ "$SOURCE_REPOSITORY" -a "$DEST_REPOSITORY" ] || { usage; exit 1; }

[ "$SOURCE_REPOSITORY" = "$DEST_REPOSITORY" ] && {
   echo "ERROR: source and destination repository cannot be the same; aborting."
   exit 1
}

[ "$TESTMODE" ] && echo "** TEST MODE enabled: no changes will be made **"

_distroquery_out=$(autodist-distroquery repository $SOURCE_REPOSITORY 2>&1) || {
   echo "ERROR: autodist-distroquery repository failed: $(echo "$_distroquery_out" | grep "^ERROR:" | head -1)" >&2
   exit 1
}
eval "$_distroquery_out"
for a in `seq 1 ${#AUTODIST_ARCHS[*]}`; do
   _distroquery_out=$(autodist-distroquery repository-problems $SOURCE_REPOSITORY ${AUTODIST_ARCHS[$a-1]} 2>&1) || {
      echo "ERROR: autodist-distroquery repository-problems failed: $(echo "$_distroquery_out" | grep "^ERROR:" | head -1)" >&2
      exit 1
   }
   eval "$_distroquery_out"
   pkglist[$a-1]="${pkg_list[*]}"
   warningslist[$a-1]="${warnings_list[*]}"
   needportlist[$a-1]="${needport_list[*]}"
done

tmpfile=`mktemp -q -t $me.XXXXXXXX` || {
      echo "ERROR: cannot create temporary files." >&2
      exit 1
   }

for a in `seq 1 ${#AUTODIST_ARCHS[*]}`; do
   echo -n "${pkglist[$a-1]} " >> $tmpfile
done
allpkgs="`cat $tmpfile | xargs -n 1 | sort -u | xargs`"
rm -f $tmpfile

for p in ${allpkgs}; do
   pkgcontinue=
   needsport=

   for w in ${warningslist[*]}; do
      [ "$p" = "$w" ] && { pkgcontinue=1; break; }
   done
   [ "$pkgcontinue" ] && continue

   for a in `seq 1 ${#AUTODIST_ARCHS[*]}`; do
      # Get pkg info from port repository
      get_pkg_buildinfo $PORT_REPOSITORY ${AUTODIST_ARCHS[$a-1]} $p
      # If not found get info from main repository
      if [ ! "$pkg_name" ]; then
         get_pkg_buildinfo $DEST_REPOSITORY ${AUTODIST_ARCHS[$a-1]} $p
      fi

      if [ "$pkg_name" ]; then
         old_pkg_version=$pkg_version
         old_pkg_release=$pkg_release
         old_pkg_repository=$pkg_repository
         break
      fi
   done

   [ "$pkg_name" ] || {
      [ "$VERBOSE" ] && echo "$p: not present in $DEST_REPOSITORY; skipping."
      continue
   }

   [ "$VERBOSE" ] && echo "$p: old release in $DEST_REPOSITORY is $old_pkg_version-$old_pkg_release"

   for o in ${needportlist[*]}; do
      [ "$p" = "$o" ] && { needsport=1; break; }
   done
   #[ "$needsport" ] && continue
   [ "$needsport" -a ! "$PORT_REPOSITORY" ] && continue

   for a in `seq 1 ${#AUTODIST_ARCHS[*]}`; do
      get_pkg_buildinfo $SOURCE_REPOSITORY ${AUTODIST_ARCHS[$a-1]} $p
      [ "$pkg_name" ] && break
   done

   [ "$pkg_name" ] || {
      [ "$VERBOSE" ] && echo "$p: not present in $SOURCE_REPOSITORY; skipping."
      continue
   }

   [ "$VERBOSE" ] && echo "$p: new release in $SOURCE_REPOSITORY is $pkg_version-$pkg_release"

   if [ "$pkg_version" = "$old_pkg_version" ]; then
      if [ "$pkg_release" = "$old_pkg_release" ]; then
         echo "$p: same release as upstream; skipping."
            continue
      fi
      update_type="release"
   else
      OIFS=$IFS
      IFS='.'
      read -ra SVER <<< "$old_pkg_version"
      read -ra VER <<< "$pkg_version"
      IFS=$OIFS
      dotdiff=`expr ${#VER[*]} - ${#SVER[*]}`
      for i in `seq 1 ${#SVER[*]}`; do
         [ "${SVER[i-1]}" != "${VER[i-1]}" ] && break
      done
      if [ "$i" = "${#SVER[*]}" -a $dotdiff -eq 0 ]; then
         # e.g. SVER=0.11.3 -> VER=0.11.4
         if [[ 64#${VER[i-1]} -gt 64#89 && 64#${SVER[i-1]} -lt 64#80 ]]; then
            [ "$VERBOSE" ] && echo "$p: dubious beta upgrade from ${SVER[i-1]} to ${VER[i-1]}; skipping."
            continue
         fi
         update_type="minor"
      #elif [ $dotdiff -lt 0 ]; then
      #   [ "$VERBOSE" ] && echo "$p: newer version has less dots than older ${#VER[*]} < ${#SVER[*]}; skipping."
      #   continue
      #elif [ "$i" != "${#SVER[*]}" ]; then
      #   # e.g. SVER=0.11 -> VER=1.0
      #   [ "$VERBOSE" ] && echo "$p: not a minor version update at position $i/${#SVER[*]}: ${SVER[i-1]} != ${VER[i-1]}; skipping."
      #   continue
      elif [ "${SVER[i-1]}" = "${VER[i-1]}" -a $dotdiff -ge 1 ]; then
         # e.g. SVER=0.11.2 -> VER=0.11.2.3
         update_type="minor"
      elif [[ 64#${VER[i-1]} -gt 64#89 && 64#${SVER[i-1]} -lt 64#80 ]]; then
         [ "$VERBOSE" ] && echo "$p: dubious beta upgrade from ${SVER[i-1]} to ${VER[i-1]}; skipping."
         continue
      elif [[ 64#${VER[i-1]} -gt 64#${SVER[i-1]} && $i -gt 1 ]]; then
         # e.g. SVER=1.0.2 -> VER=1.0.3.dev1234
         update_type="minor"
      #else
      #  [ "$VERBOSE" ] && echo "$p: major version update ${SVER[i-1]} vs ${VER[i-1]}; skipping"
      #  continue
      fi
   fi
   #if [ ! "${needsport}" ]; then
      if [ "$old_pkg_repository" == "$PORT_REPOSITORY" -o "$old_pkg_repository" == "$DEST_REPOSITORY" ]; then
         echo "$p: importing from $SOURCE_REPOSITORY to $PORT_REPOSITORY ($pkg_version-$pkg_release -> $old_pkg_version-$old_pkg_release)"
         if [ ! "$TESTMODE" ]; then
            autodist-repository import $SOURCE_REPOSITORY $p -d $PORT_REPOSITORY -y >/dev/null
            if [ $? -eq 0 ]; then
               [ "$WEBBUILD_USER" -a "$DISTROQUERY_API_URL" ] && \
                  autodist-distroquery social-log post "$WEBBUILD_USER" \
"imported <b>$p</b> from <b>$SOURCE_REPOSITORY</b> to <b>$PORT_REPOSITORY</b> for porting" \
"" "" "false" "$WEBBUILD_EMAIL" 2>/dev/null
            fi
         fi
      fi
done

exit 0
