#!/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 move __build to chroot

source /etc/makepkg.conf
source /etc/libretools.conf

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


## List packages on log that are on status
## usage: list_pkgs <status> <message>
#
## status: nonfree, built, failed, unstaged
list_pkgs() {
    msg="$2"
    local pkgs=($(grep "$1:" $build_dir/log)) && {
        msg "$2"
        echo ${pkgs[@]} | tr " " "\n" | cut -d: -f2
    }
}

# 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

}

## Check all build_dir, fails if one PKGBUILD is nonfree
check_nonfree() {
    find "$build_dir" -name PKGBUILD \
        -exec pkgbuild-check-nonfree {} +
    if [ "$?" -eq 15 ]; then
        error "Some PKGBUILD have nonfree problems"
        exit 15
    fi

}

# Removes a package from the buildorder
# $1 package name
# $2 buildorder file
remove_buildorder() {
  grep -Evw "${1}" ${2} > ${2}2
  mv -f ${2}2 ${2}

  return $?
}

succesfull_build() {

    if [ "$RUN" != "$FULLBUILDCMD" ]; then
        return 0 # Custom command or download sources
    fi

    if source .INFO && [ -n "$repo" ]; then

        if [ ! -z "$HOOKLOCALRELEASE" ]; then
            find -name "*.pkg.tar.?z" -print0 | xargs -0 "$HOOKLOCALRELEASE" "$repo"
        fi

        librestage $repo || echo "unstaged:$(basename $PWD)" >>$build_dir/log

        msg "Updating pacman db and packages"
        sudo pacman -Sy || true

    fi

    echo "built:$(basename $PWD)" >>$build_dir/log
}

build_description() {
    list_pkgs "nonfree" "Those packages contain nonfree deps:"
    list_pkgs "built" "Those packages were built and staged:"
    list_pkgs "failed" "Those packages failed to build:"
    list_pkgs "unstaged" "Those packages couldn't be staged (missing reponame):"
}

__build() {
    pushd ${build_dir} >/dev/null

    build_packages=($(sort -gr $buildorder | cut -d: -f2)) # greater levels must be built first

    while [ ${#build_packages[@]} -ge 1 ]; do

        pushd "$build_dir/${build_packages[0]}" >/dev/null

        if [ -n "${HOOKPKGBUILDMOD}" ]; then
            ${HOOKPKGBUILDMOD} || true
        fi

        eval "$RUN"; r=$?

        case $r in

            0) succesfull_build ;;

            *) error "There were errors while trying to build the package."
                echo "failed:$(basename $PWD)" >>$build_dir/log
                ;;
        esac

        remove_buildorder "${build_packages[0]}" $buildorder || true

# which is next package?
        build_packages=($(sort -gr $buildorder | cut -d: -f2))
        popd > /dev/null
    done

    popd >/dev/null
}

# End inmediately but print a useful message
trap_exit() {
  error "$@"
  warning "Leftover files left on $build_dir"
  mv .BUILDORDER BUILDORDER
  exit 1
}

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

CLEANUP="false"
CHECKNONFREE="true"
RUN="$FULLBUILDCMD"
MESSAGE="Building packages"

usage() {

    echo ""
    echo "$(basename $0) [options] <build_dir>"
    echo ""
    echo "Builds packages from build_dir, create a build_dir using:"
    echo "'fullpkg-find <build_dir>'"
    echo ""
    echo "If no <build_dir> is specified, it uses the current directory."
    echo ""
    echo "OPTIONS:"
    echo " -h : this message."
    echo " -c : clean <build_dir> on succesfull build"
    echo " -N : don't check for freedom issues." #Also made by fullpkg-find
    echo " -r \"command\" : use this instead of \"$FULLBUILDCMD\"."
    echo " -g : get sources for building packages on build_dir."
    echo ""
    exit 1

}

while getopts 'hNr:g' arg; do
    case $arg in
        h) usage ;;
        c) CLEAN ;;
        N) CHECKNONFREE="false" ;;
        r) RUN="$OPTARG"
            MESSAGE="Executing custom action";;
        g) RUN='makepkg -g > /dev/null'
            MESSAGE="Downloading packages";;
    esac
done

shift $(( OPTIND - 1 ))
build_dir="${1:-`pwd`}"
buildorder="${build_dir}/BUILDORDER"

if [ ! -e "$buildorder" ]; then
    error "This is not a build_dir. Make one using fullpkg."
    usage
else
# backup BUILDORDER
    cp "$buildorder" "$build_dir/.BUILDORDER"
fi

if "$CHECKNONFREE"; then
    check_nonfree
fi

if [ -z "$FULLBUILDCMD" ]; then
    error "Set your FULLBUILDCMD on libretools.conf"
fi

msg "$MESSAGE"
__build

if [ "$RUN" != "$FULLBUILDCMD" ]; then
    # Used for downloading or custom command
    mv "$build_dir/.BUILDORDER" "$buildorder"
    exit 0
elif "$CLEANUP"; then
    find "$build_dir" -mindepth 1 -delete
fi

build_description

plain "Test packages on and if they work fine librerelease."

exit 0