#!/bin/bash

# Copyright 2016 Matthew Thode
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

if [[ "${DIB_DEBUG_TRACE:-0}" -gt 0 ]]; then
    set -x
fi
set -eu
set -o pipefail

ACTION='install'

SCRIPTNAME="$(basename $0)"
function show_options {
    echo "Usage: ${SCRIPTNAME} [package ...]"
    echo
    echo 'Options:'
    echo '    -u          -- update all packages'
    echo '    -e          -- erase/remove packages'
    exit 0
}

function fix_shm {
    # make /dev/shm dir if it doesn't exist
    # mount tmpfs and chown it
    # existing programs could be using /dev/shm
    #  This means it cannot be moved or backed
    #  up as a copy easily.  The only remaining
    #  option is to move the link if it exists
    #  as a link.  Existing programs will still
    #  hold the file handle of the original
    #  location open and new programs can use
    #  the fixed /dev/shm.
    if [[ "${RUN_ONCE_SHM}" == '1' ]]; then
        if [[ ! -d /dev/shm ]]; then
            if [[ ! -e /dev/shm ]]; then
                if [[ -L /dev/shm ]]; then
                    mv /dev/shm /dev/shm.orig
                fi
                mkdir /dev/shm
            fi
        fi
        mount -t tmpfs none /dev/shm
        chmod 1777 /dev/shm
        RUN_ONCE_SHM='0'
    fi
}

function unfix_shm {
    # unmount tmpfs
    # care about anything still using it
    if [[ "${RUN_ONCE_SHM}" == '0' ]]; then
        umount /dev/shm
        if fuser /dev/shm; then
            rmdir /dev/shm
        fi
        if [[ -e /dev/shm.orig ]]; then
            mv /dev/shm.orig /dev/shm
        fi
    fi
}

function install_gentoo_packages {
    RUN_ONCE_SHM='1'
    if grep -q /dev/shm /proc/mounts; then
        emerge $@
    elif [[ -k /dev/shm ]]; then
        emerge $@
    else
        fix_shm
        emerge $@
        unfix_shm
    fi
}

TEMP="$(getopt -o huem: -n ${SCRIPTNAME} -- ${@})"
if [[ "${?}" != 0 ]]; then
    echo 'Terminating...' >&2
    exit 1
fi
eval set -- "${TEMP}"

while true; do
    case "${1}" in
        -u )
            if [[ ! -f /usr/portage/profiles ]]; then
                emerge-webrsync -q
            fi
            install_gentoo_packages -uDNv --with-bdeps=y --backtrack=99 --jobs=2 @world
            install_gentoo_packages --verbose=n --depclean
            install_gentoo_packages -v --usepkg=n @preserved-rebuild
            etc-update --automode -5
            eselect news read new
            exit 0;
            ;;
        -e )
            ACTION='remove'
            shift
            ;;
        -m )
            MAP_ELEMENT="${2}"
            shift 2
            ;;
        -h )
            show_options
            ;;
        -- )
            shift
            break
            ;;
        * )
            echo "Error: unsupported option ${1}."
            exit 1
            ;;
    esac
done

PKGS="${@}"
if [[ -n "${MAP_ELEMENT:-}" ]]; then
    PKGS="$(pkg-map --element ${MAP_ELEMENT} ${@})"
    if [[ "${?}" != 0 ]]; then
        echo "bin/pkg-map error. ${PKGS}"
        exit 1
    fi
fi

if [[ -z "${PKGS}" ]]; then
    echo "Not running install-packages ${ACTION} with empty packages list"
else
    if [[ "${ACTION}" == 'install' ]]; then
        if [[ ! -f /usr/portage/profiles ]]; then
            emerge-webrsync -q
        fi
        install_gentoo_packages -q --jobs=2 --changed-use "${PKGS}"
    elif [[ "${ACTION}" == 'remove' ]]; then
        if [[ ! -f /usr/portage/profiles ]]; then
            emerge-webrsync -q
        fi
        install_gentoo_packages -C "${PKGS}"
    else
        echo 'something when really wrong, install action is not install or remove'
    fi
fi
