#!/bin/bash

# requires:
# https://aur.archlinux.org/packages/clean-chroot-manager
# https://aur.archlinux.org/packages/aurutils

basedir="$(pwd)"
src_dir="${basedir}/src"
repo_name=aur
pkg_dir="${basedir}/$repo_name"
aurweb='https://aur.archlinux.org'

if [ `whoami` == 'root' ]; then
   echo "Must not be run as root."
   exit 1;
fi

[ -e ppa.cfg ] && source ppa.cfg

clone_update_aur() {
    declare -r startdir=$PWD

    while IFS= read -r; do
        if [[ -d $REPLY ]]
        then

            if [[ ! -d $REPLY/.git-nosub ]]
            then
                rm -rf tmp
                git clone "$aurweb/$REPLY".git tmp
                mv tmp/.git "$REPLY"/.git-nosub
                rm -rf tmp
            fi

            cd "$REPLY"
            mv .git-nosub .git

            git fetch -v # returns 0 even if nothing was fetched
            git reset --hard HEAD
            git merge

            cd "$startdir"
        else
            git clone "$aurweb/$REPLY".git
        fi
        # .git folders make it a git submodule, we don't want that, need to gitignore .git-nosub
        mv "$REPLY"/.git "$REPLY"/.git-nosub
        # we don't ever want to track these
        rm -f "$REPLY"/.SRCINFO
    done
}

add() {
    cd "$src_dir"
    aurchain "$@" | clone_update_aur
}

update() {
    cd "$src_dir"
    if [ "$#" -gt 0 ]; then
        aurchain "$@" | clone_update_aur
    else
        aurchain * | clone_update_aur
    fi
}

sign_packages() {
    cd "$pkg_dir"
    for pkg in "$@"; do
        gpg -v "${pkg}.sig" 2>/dev/null || (rm -f "${pkg}.sig"; gpg --detach-sign --use-agent "$pkg")
    done
}

build() {
    cd "$src_dir"
    if [ "$#" -gt 0 ]; then
        failed=''
        # create .SRCINFO, so aurqueue can use it next
        for dir in "$@"
        do
            cd $dir
            makepkg --printsrcinfo > .SRCINFO
            cd "$src_dir"
        done
        for dir in $(aurqueue "$@")
        do
            cd $dir
            # delete any existing packages
            grep '^pkgname = ' .SRCINFO | sed 's/^pkgname = //' | xargs -I {} sh -c 'rm -f {}*pkg.tar*'
            sudo arch-chroot-helper make
            if [ $? -ne 0 ]; then
                # failed, append to failed string
                failed="$failed $dir"
            else
                #list_of_packages="$(grep '^pkgname = ' .SRCINFO | sed 's/^pkgname = //' | sort -u | tr '\n' ' ')"
                list_of_package_files="$(grep '^pkgname = ' .SRCINFO | sed 's/^pkgname = //' | xargs -I {} sh -c 'ls {}*pkg.tar*' 2>/dev/null | sort -u | tr '\n' ' ')"
                mv $list_of_package_files "$pkg_dir"
                cd "$pkg_dir"
                sign_packages $list_of_package_files
                # repose appears to work the same with both $list_of_packages and $list_of_package_files
                repose -f -z $repo_name $list_of_package_files
                sign_packages $repo_name.db $repo_name.files
            fi
            cd "$src_dir"
        done

        if [ "$failed" == "" ]
        then
            # success!, nuke the chroot
            echo sudo arch-chroot-helper nuke
        else
            # some failures
            echo "failed packages:$failed"
        fi

    else
        build *
    fi
}

rebuild_db() {
    cd "$pkg_dir"
    repose -v -f -z $repo_name
    sign_packages $repo_name.db $repo_name.files
}

echo_deps() {
    cd "$src_dir"
    aurchain "$@"
}

build_deps() {
    cd "$src_dir"
    if [ "$#" -gt 0 ]; then
        build $(aurchain "$@")
    else
        # regular build? if we are building all no use looking up deps...
        build
    fi
}

build_changed() {
    commit="$1"
    [ "$commit" == "" ] && commit=HEAD
    build $(git diff-tree --no-commit-id --name-status -r "$commit" | grep -v ^D | grep PKGBUILD$ | sed -e 's@/PKGBUILD$@@' -e 's@.*/@@' | tr '\n' ' ')
}

build_changed_deps() {
    commit="$1"
    [ "$commit" == "" ] && commit=HEAD
    build_deps $(git diff-tree --no-commit-id --name-status -r "$commit" | grep -v ^D | grep PKGBUILD$ | sed -e 's@/PKGBUILD$@@' -e 's@.*/@@' | tr '\n' ' ')
}

echo_changed() {
    commit="$1"
    [ "$commit" == "" ] && commit=HEAD
    git diff-tree --no-commit-id --name-status -r "$commit" | grep -v ^D | grep PKGBUILD$ | sed -e 's@/PKGBUILD$@@' -e 's@.*/@@' | tr '\n' ' '
}

list_official_packages() {
    cd "$src_dir"
    ls | xargs -n1 -I {} pacman -Ss '^{}$' | egrep -v "^($repo_name| )"
}

list_installed_paclist() {
    paclist $repo_name | cut -d' ' -f1
}

list_installed() {
    comm -12 <(pacman -Qq | sort) <(pacman -Slq $repo_name | sort)
}

reinstall() {
    list_installed | xargs sudo pacman -S --noconfirm
}

update_installed() {
    update $(list_installed | xargs aurchain)
}

clean() {
    # git clean -e 'aur/*' -dxn | grep -v .git
    git clean -e '*.git*' -e 'aur/*' -dxf
}

undo() {
    patch -p1 -R < undo.diff
}

grep_deps() {
    grep "$1" src/*/PKGBUILD
}

git_add_changes() {
    git add -f $(git status | grep -E '^.+(modified|deleted):' | sed 's/.* //' | tr '\n' ' ')
}

if [ "$#" -gt 0 ]; then
    [ -d "$src_dir" ] || mkdir -p "$src_dir"
    [ -d "$pkg_dir" ] || mkdir -p "$pkg_dir"
    $*
else
    echo "Must specify a command, eg: add, build, list, clean"
    exit 1
fi
