#!/bin/bash
#set -x
source /etc/libretools.conf
source $XDG_CONFIG_HOME/libretools/libretools.conf >/dev/null 2>&1|| true

# Get system variables
source /etc/makepkg.conf
source $HOME/makepkg.conf >/dev/null 2>&1|| true

# End inmediately but print an useful message
trap_exit() {
  error "($(basename $0)) $@ (leftovers on ${BUILDDIR})"
  exit 1
}

# Trap signals from makepkg
set -E
trap 'trap_exit "TERM signal caught. Exiting..."' TERM HUP QUIT
trap 'trap_exit "Aborted by user! Exiting..."' INT
trap 'trap_exit "An unknown error has occurred. Exiting..."' ERR

# return : full version spec, including epoch (if necessary), pkgver, pkgrel
#  usage : get_fullver( ${epoch:-0}, $pkgver, $pkgrel )
get_fullver() {
    if [ $1 -eq 0 ]; then
# zero epoch case, don't include it in version
        echo $2-$3
    else
        echo $1:$2-$3
    fi

}

# Add line to build order cache in CSV format
# *must* be run from the PKGBUILD path
# status;depth;pkgbase;[epoch:]pkgver-pkgrel;path;repo
# $1 status
# $2 pkgname
add_order() {
  echo "${1};${DEPTH};${2:-${pkgbase}};${fullver};${PWD};$(guess_repo "$PWD")" >> "${BUILDORDER}"
  ${VERBOSE} && msg2 "%${DEPTH}s${2:-${pkgbase}} [${1}]" || true
}

# Bury a package deeper in the tree
# $1 pkgbase
# $2 nextdepth
bury() {
# Bury only if we are going to build the dep
# Get it's current depth and dir name
    local current_depth=$(egrep "build;[0-9]\+;${1};" "${BUILDORDER}" | cut -d ';' -f 2)
    local current_name="$(printf "%03d" ${current_depth})_${1}"

# If there's a depth or the package is not the root of the build tree (which
# can lead to funny chicken-and-egg problems), update the depth to the current
# package next-depth and rename the dir too
    if [ -z "${current_depth}" ]; then return; fi
    if [ -z "${current_name}" ]; then return; fi
    if [ ${current_depth} -eq 0 ]; then return; fi

    ${VERBOSE} && msg "Burying ${1} from ${current_depth} to ${2}"

    {
        sed -i "s|^\(build;\)\([0-9]\+\)\(;${1};.*\)$|\1${2}\3|" "${BUILDORDER}" && \
        mv "${BUILDDIR}/${current_name}" "${BUILDDIR}/$(printf "%03d" ${2})_${1}"
    } || return 1
}

# Finds a PKGBUILD on toru's path cache
# Look in all caches but pick the first one
# TODO move to a toru flag (-p?)
where_is() {
  grep -m1 "^${1}:" "${TORUPATH}/paths" 2>/dev/null| \
    cut -d: -f2 2>/dev/null
}

# Guess the repo from the pkgbase path
# $1 path, pwd or where_is
guess_repo() {
    basename "$(dirname "${1}")"
}

if [ ! -f PKGBUILD ]; then
  error "Missing PKGBUILD ($PWD)"
  exit 1
fi

if ! source PKGBUILD ; then
  error "Can't source PKGBUILD"
  exit 1
fi

# Save resources
unset pkgdesc arch license groups backup install md5sums sha1sums \
      sha256sums source options >/dev/null 2>&1

unset build package >/dev/null 2>&1

for _pkg in ${pkgname[@]}; do
  unset package_${_pkg} >/dev/null 2>&1 || true
done
## 

# Get useful values
pkgbase="${pkgbase:-${pkgname[0]}}"
fullver=$(get_fullver ${epoch:-0} ${pkgver} ${pkgrel})

# Get or set the work dir
BUILDDIR="${1:-$(mktemp -d /tmp/${pkgbase}-treepkg-XXXx)}"
BUILDORDER="${BUILDDIR}/BUILDORDER"
DEPTH=${2:-0}
NEXTDEPTH=$((${DEPTH} + 1))
# This can be set as env vars (ie: $ V=false B=false treepkg)
# TODO Turn into flags?
VERBOSE=${V:-true}
BUILD=${B:-true}
CLEANUP=${C:-true}
# Skip BUILDORDER creation and build anything on BUILDDIR
BUILDNOW=${N:-false}

if [ ! -z "${1}" -a ${DEPTH} -eq 0 ]; then
    BUILDNOW=true
fi

if ! ${BUILDNOW}; then
# ensure it exists
    touch "${BUILDORDER}"

# If this package is already built quit silently
    if is_built "${pkgbase}" "${fullver}"; then
      add_order "ignore"
      exit 0
    fi

# Ignore if already in build order
    egrep -q ";${pkgbase};" "${BUILDORDER}" && exit 0

# Add pkgbase to build order
    add_order "build"

# Copy the directory to the build dir
# TODO run makepkg --source to avoid moving garbage around?
    cp -r "${PWD}" "${BUILDDIR}/$(printf "%03d" ${DEPTH})_${pkgbase}"

# Cleanup dep versioning
    deps=($(echo "${depends[@]} ${makedepends[@]}" | \
           sed "s/[=<>]\+[^ ]\+//g" | \
           tr ' ' "\n" | \
           sort -u))

# NOTE: getting depends from package() is a PITA
    for _dep in ${deps[@]}; do
# Ignore if already in build order
# TODO move deps deeper in the tree if
# pkgbase - dep1
#         \ dep2 - dep1
# dep1 should be depth + 1
# probably sed -i buildorder and increase dep's dep depth :D
# remember to change dir name from xxx_pkgbase to xxx+1_pkgbase
      egrep -q ";${_dep};" "${BUILDORDER}" && bury "${_dep}" ${NEXTDEPTH}

# Ask toru where's a PKGBUILD
      depdir="$(where_is ${_dep})"

      if [ -z "${depdir}" -o ! -d "${depdir}" ]; then
# We specify the pkgname because we can't source the dep PKGBUILD
# Normally 'any' packages are missing from our work ABS
        add_order "missing" "${_dep}"
        continue
      fi

      pushd "${depdir}" >/dev/null

# Run itself over dependencies
      $0 "${BUILDDIR}" ${NEXTDEPTH}

    done
# End BUILD now
fi

# Only build at the end
if [ ${DEPTH} -eq 0 ]; then
  ${VERBOSE} && msg "Starting build" || true

  if ${BUILD}; then
    ${VERBOSE} && msg "Build tree stored in ${BUILDORDER}" || true

# Build everything sorting the build dir
# The reverse order ensures we start by the deepest packages
    for _pkg in $(ls -r "${BUILDDIR}"); do
# Ignore if there's no PKGBUILD
      if [ ! -f "${BUILDDIR}/${_pkg}/PKGBUILD" ]; then continue; fi

      ${VERBOSE} && msg "Building ${_pkg/_/ }" || true

# Run build command
      pushd "${BUILDDIR}/${_pkg}" >/dev/null
        sudo pacman -Syu --noconfirm

        ${FULLBUILDCMD}
# Run local release hook with $1 = $repo
        ${HOOKLOCALRELEASE} $(egrep ";${_pkg#*_};" "${BUILDORDER}" | cut -d';' -f6)
      popd >/dev/null
    done

  else
# Just print the working dir
    ${VERBOSE} || echo "${BUILDORDER}" || true
  fi

if ${CLEANUP} ; then
      msg2 "Removing ${BUILDDIR}"
      rm -rf "${BUILDDIR}"
fi

fi

exit $?