#!/bin/bash
# set -x # uncomment for debug
# Builds packages from ABS recursively. It tries to find dependencies that
# aren't built or need update and then makepkg them in order.

# TODO: fullpkg-find should find packages wich depend on the
#       package to be build, so we can avoid "missing $name.so errors"

# Get repo name. Asumes ${ABSROOT}/repo/package/PKGBUILD
guess_repo() {
    basename $(dirname $(pwd))
}

# 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
}

# 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

}

# Checks ABSROOT and look for target pkg deps. Adds them if not built or outdated.
find_deps() {
# Check this level
    source PKGBUILD

    local repo="${repo:-$(guess_repo)}"
    local pkgbase="${pkgbase:-${pkgname[0]}}"
    local fullver="$(get_fullver ${epoch:-0} ${pkgver} ${pkgrel})"

    if ! pkgbuild-check-nonfree > /dev/null 2> /dev/null; then
        if [ "$?" -eq 15 ]; then
            error "pkgbase" has nonfree issues
            return 15
        fi
    fi

    if is_built "${pkgbase}" "${fullver}"; then
        exit 0 # pkg is built and updated
    fi

# greater levels are built first
    echo "${LEVEL}:${pkgbase}" >>"$build_dir/BUILDORDER"
# PKGBUILD is already there
    if [ -d "${build_dir}/${pkgbase}" ]; then
        exit 0
# Copy dir to build_dir
    else
        cp -r ../${pkgbase}/ ${build_dir}/

# to identify repo later
        echo "repo=$repo" > "${build_dir}/${pkgbase}/.INFO"
    fi

# current package plus a space for every level
    msg2 "%${LEVEL}s${pkgbase}-${fullver}"

## Check next levels
    declare -i next_level=$LEVEL+1

# All deps in separate line, only once, without version.
    deps=($(echo "${depends[@]} ${makedepends[@]}" | \
           sed "s/[=<>]\+[^ ]\+//g" | \
           tr ' ' "\n" | \
           sort -u))

    for _dep in ${deps[@]}; do

        local found=false
# TODO change for where_is or toru-path
        local pkgdir=$(toru -p ${_dep})

        if [ -n "$pkgdir" -a -d "${pkgdir}" ]; then
          found=true

          pushd "${pkgdir}" > /dev/null
# runs itself on dep's PKGBUILD dir
          $0 -l ${next_level} ${build_dir}

# probable circular deps
          [ $? -eq 20 ] && return 20
          popd > /dev/null
        fi

        if ! (( found )); then
          echo "dep_not_found:$_dep" >>$build_dir/log
        fi

    done

## End variable block

    unset next_level dir
}

source /etc/libretools.conf

if [ -e $XDG_CONFIG_HOME/libretools/libretools.conf ]; then
    source $XDG_CONFIG_HOME/libretools/libretools.conf
fi

LEVEL=0
MAXLEVEL=20
CLEANFIRST='false'
UPDATEDB='true'

usage() {

    echo ""
    echo "cd to a dir containing a PKGBUILD and run:"
    echo "$(basename $0) [options] <build_dir>"
    echo ""
    echo "This script will create a build_dir for recursive building"
    echo "it tries to find dependencies that aren't built or need update."
    echo ""
    echo "If no <build_dir> is specified, the script works on a tempdir"
    echo ""
    echo "OPTIONS:"
    echo " -h : this message."
#    echo " -A <absroot> : use this ABSROOT." # Is it needed anymore?
    echo " -c : clean <build_dir> before working."
    echo " -m <max_level> : check deps until this level"
    echo " -n : don't update pacman db."
    echo ""
    exit 1

}

while getopts 'hA:l:cmn' arg; do
    case "$arg" in
        h) usage ;;
#        A) ABSROOT="$OPTARG" ;;
        l) LEVEL="$OPTARG" ;; # hidden option to know dep level.
        c) CLEANFIRST='true' ;;
        m) MAXLEVEL="$OPTARG" ;;
        n) UPDATEDB='false' ;;
    esac
done

if [ ! -r PKGBUILD ]; then
    error "This directory doesnt contain a PKGBUILD"
    usage
fi

shift $(( OPTIND - 1 ))
build_dir="${1}"

if [ "$LEVEL" -eq 0 ]; then

    build_dir="${1:-$(mktemp -d /tmp/fullpkg.XXXXXX)}"

    if [ ! -d "$build_dir" ]; then
        mkdir -p "$build_dir"
    elif "$CLEANFIRST"; then
        # Erase files already in dir
        msg "Cleaning up files in dir"
        find "$build_dir" -mindepth 1 -delete
    fi

    if "$UPDATEDB"; then
        msg "Updating pacman db"
        sudo pacman -Sy --noconfirm || true
    fi

# make files for log and buildorder
    touch "${build_dir}"/{log,BUILDORDER}
    buildorder="${build_dir}/BUILDORDER"

    msg "Checking dependencies"
fi

# Probable circular deps
[ "$LEVEL" -gt "$MAXLEVEL" ] && exit 20

# Find the dependencies on the ABS itself
find_deps || {

# Probable circular deps
    if [ "$?" -eq 20 ]; then

# Show error only on level 0
       if [ "$LEVEL" -eq 0 ]; then
           error "Check for circular deps on $build_dir/BUILDORDER";
       fi

    fi
# Pass message 20
    exit 20
}

exit 0