#!/bin/bash
# TODO
# * Do version checking
# * Detect circular builds
# * Detect pkgnames by provides, replaces, etc. instead of dir tree

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

[[ -r ~/.config/libretools/libretools.conf ]] && \
    source ~/.config/libretools/libretools.conf

function usage {
    echo "cd to a dir containing a PKGBUILD and run:"
    echo "$0 [options]"
    printf "This script will check dependencies, build them if possible "
    printf "and stage the packages on it's repo."
    echo
    echo "OPTIONS:"
    echo " -h          : this message."
    echo " -f          : build even when a package has been built."
    echo " -n absdir   : set ABSROOT to this dir"
    echo " -r reponame : set repo name to reponame"
    echo " -R pkgname  : build pkgname if it is a dep"
    echo
}

force_build='n'
force_array=()
_fullpkgargs=""
failed=()
missing=()

while getopts 'hfn:r:R:' arg; do
    case $arg in
	h) usage; exit 0 ;;
	f) force_build='y' ;;
	R) force_array=(${force_array[@]} $OPTARG); _fullpkgargs+="-R $OPTARG ";;
	n) ABSROOT="$OPTARG" ;;
	r) repo="$OPTARG" ;;
    esac
done

[[ ! -r PKGBUILD ]] && {
    error "This isn't a build directory"
    echo
    usage
    exit 1
}

tmp_dir=$(mktemp -d /tmp/$(basename $PWD).XXXXXX)
queue_file=$(mktemp /tmp/queue.XXXXXX)
ban_file=$(mktemp /tmp/ban.XXXXXX)

## START FUNCTIONS ##

# Queue Management
# * Always get the queue list from the server
# * Add/Remove from queue
# * Check if a package is listed

# TODO
# * Check for concurrence

# Get the queue list from the server
get_queue() {
    rsync -e ssh -aq $PARABOLAHOST:mips64el/queue $queue_file >/dev/null 2>&1 || {
        error "Failed to retrieve queue list"
        return 1
    }
}

# Put the queue list on the server
put_queue() {
    rsync -e ssh -aq $queue_file $PARABOLAHOST:mips64el/queue >/dev/null 2>&1 || {
        error "Failed to put queue list"
        return 1
    }
}

# Add packages to the queue
update_queue() {
    get_queue || return $?

    basename $PWD | sed "s/$/:$PACKAGER/" >> $queue_file || return 2

    put_queue || return $?
}

# Remove a package from the queue
remove_queue() {
    get_queue || return $?

    grep -vw "^$(basename $PWD)" $queue_file > $queue_file.2
    cat $queue_file.2 > $queue_file

    put_queue && rm $queue_file{,.2}  && return 0 || return $?
}

# Checks if a package is listed
check_queue() {
    get_queue || return $?

    packager=$(grep -w "$(basename $PWD)" ${queue_file} | cut -d ':' -f2)

    [[ ! -z $packager ]] && [[ "$packager" != "$PACKAGER" ]] && {
        warning "$(basename $PWD) is being packaged by $packager. Please wait."
        return 1
    }

    return 0
}

# END Queue Management #

# Checks if the package is banned from building
is_banned() {
    rsync -e ssh -aq $PARABOLAHOST:mips64el/ban $ban_file >/dev/null 2>&1 || {
        plain "Failed to get ban list"
        return 1
    }
    grep -w $1 $ban_file >/dev/null 2>&1
    return $?
}

guess_repo() {
    basename $(dirname $(pwd))
}

#  usage : in_array( $needle, $haystack )
# return : 0 - found
#          1 - not found
function in_array {
    [[ $2 ]] || return 1
    local needle=$1; shift
    local item
    for item in "$@"; do
	[[ ${item#@} = $needle ]] && return 0
    done
    return 1 # Not Found
}

function quit {
    remove_queue
    exit 1
}

function cleanup {
    rm $ban_file $queue_file
    rm -rf $tmp_dir
}

# TODO keep track of spawned fullpkgs

## END FUNCTIONS ##

source PKGBUILD
repo=${repo:-$(guess_repo)}
msg "Building ${repo:-missing repo}/${pkgbase:-${pkgname[@]}}: $pkgdesc"

# Pre build tests
if [ $force_build == 'n' ]; then

    # Be able to write files
    if [[ ! -w $queue_file ]]; then
	error "can't write queue file"
	exit 1
    elif [[ ! -w $ban_file ]] ; then
	error "can't write ban file"
	exit 1
    fi

    if is_built "${pkgbase:-${pkgname[0]}}>=${pkgver}-${pkgrel}"; then
	msg2 "This package is built."
	exit 0
    fi

    if is_banned ${pkgbase:-$pkgname}; then 
	error "This package is banned from building. Check the ban list"
	exit 1
    fi

    check_queue || exit 1

fi

# This will be executed at exit for any reason.
trap "quit" EXIT INT QUIT TERM KILL HUP

if ! grep mips64el PKGBUILD >/dev/null; then
  msg "Adding mips64el arch"
  sed -i "s/^\(arch=([^)anym]\+\))/\1 'mips64el')/" "PKGBUILD"
fi

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

msg "Checking dependencies"
for _dep in ${deps[@]}; do
    is_banned $_dep && continue

    for _repo in ${REPOS[@]}; do
        # TODO find split packages
        [[ -e "$ABSROOT/${_repo}/$_dep/PKGBUILD" ]] && {
            source "$ABSROOT/${_repo}/$_dep/PKGBUILD"
            msg2 "Checking for $_dep>=$pkgver-$pkgrel"
	    
            if ! in_array $_dep ${force_array[@]}; then
              if is_built "$_dep>=$pkgver-$pkgrel"; then
                  plain "this package is built"
                  break
              fi
            else
              _fullpkgargs+="-f "
              _fullpkgargs="$(echo $_fullpkgargs | sed s/"-R $_dep "//)"
              force_array=( $(echo ${forcearray[@]} | tr " " "\n" | grep -vw "^$_dep") )
            fi
	    
            cp -r "$ABSROOT/$_repo/$_dep" $tmp_dir/ || {
                error "Can't copy $_dep to the work dir."
                exit 1
            }

            # Enter the work dir and run this command in it
            pushd $tmp_dir/$_dep >/dev/null

	    $0 -r $_repo $_fullpkgargs

            [[ $? -ne 0 ]] && {
                failed=(${failed[@]} $_dep)
            }

            popd >/dev/null
        }
    done
done

# TODO probably not elegant enough
# TODO only the last fullpkg should show this message
#      and it should contain all failed pkgs
[[ ${#failed[@]} -gt 0 ]] && {
    error "This packages failed to build: ${failed[@]}"
    exit 1
}

# Let everybody know we're building this
update_queue || {
    warning "Couldn't update the queue, let your partners know about this."
}

cp -r ../$(basename $PWD) $tmp_dir/
pushd $tmp_dir/$(basename $PWD) >/dev/null

msg "Syncing database"
sudo pacman -Syu --noconfirm
makepkg --noconfirm  --nocheck -sLcr ; r=$?
case $r in
    0) msg "The build was succesful."
       mipsrelease *.pkg.tar.*
       librestage $repo
       sudo pacman -Sy
       # cleanup is only on succesfull build so failed can be inspected
       cleanup;;
    1) error "There were errors while trying to build the package." ;;
    2) error "The build failed." ;;
esac

exit $r