#!/bin/bash
# *******************************************************************
# **  @file eisman_update.sh - update local package database
# **
# **  Creation:     2013-01-12 dv
# **  Last update:  $Id: eisman_update.sh 42823 2016-08-13 19:22:10Z dv $
# **
# **  Copyright (c) 2013-2016 the eisfair team, team(at)eisfair(dot)org
# **
# **  This program is free software; you can redistribute it and/or modify
# **  it under the terms of the GNU General Public License as published by
# **  the Free Software Foundation; either version 2 of the License, or
# **  (at your option) any later version.
# *******************************************************************

. /var/install/include/eislib
. /var/install/include/eismanlib


# *******************************************************************
# **  show help on arguments and possible options
# **  @param  n/a
# **  @return n/a
# *******************************************************************

show_help()
{
cat <<EOF

Update local package database

usage: eisman update [OPTIONS]

options:
   --help      show this help screen
   --quiet     show messages in [mecho --file] format
               default [mecho --tty]

EOF

}


# *******************************************************************
# **  show current progress in percent
# **  @param  $1 progress in percent
# **  @return n/a
# *******************************************************************

show_progress()
{
    echo -en "\033[7D"
    printf "[%3d%%] completed!" "${1}"
    echo -en "\033[10D"
}


# *******************************************************************
# **  read index file line by line, check if package meets current system
# **  and fetch the info header file if it is't already in the local cache.
# **  The files are converted into record format!
# **  Further an entry for every package is added to the package database
# **  (without any respect to the fact if it is a new entry or not). Before
# **  doing that, the contents of the package database is cleared.
# **  @param  n/a
# **  @return n/a
# *******************************************************************

update_record_files()
{
    local version
    local invalid_base='no'
    local linecount='0'
    local progress='0'
    local linetotal
    local idx2='0'

    # show what we are doing
    mecho ${output} --info '(Re)building package database ...'

    # init progress display
    if [ "${output}" = "--tty" ]
    then
        echo -n "       "
        show_progress 0
    fi

    # get total number of lines in index
    linetotal=$(wc -l < /tmp/index.txt)

    # overwrite existing database
    > "${EISMAN_PATH}/packages.db.tmp"

    # read index line by line
    while read -r
    do
        local line=$REPLY

        linecount=$((${linecount} + 1))

        if [ "${line:0:1}" != "#" ]
        then
            local idx=0
            local package=""
            local version=""
            local status=""
            local url=""
            local system=""
            local file=""
            local success=0

            for word in $line
            do
                case $idx in
                0)  package="$word"
                    ;;
                1)  version="$word"
                    ;;
                2)  status="$word"
                    ;;
                3)  url="$word"
                    file="${word:0:$((${#word} - 5))}"
                    ;;
                4)  system="$word"
                    ;;
                esac

                idx=$(($idx + 1))
            done

            # handle entries missing system tag
            if [ -z "$system" ]
            then
                system='eisfair-1'
            fi

            if [ "$idx" -ge 3 ]
            then
                # if base version is invalid, only accept base packages
                if [ "${invalid_base}" = "no" ] ||
                   [ "${package}" = "base" ]
                then
                    # if package name is "base", do not accept "update-"
                    # archives, since they belong to base update installer
                    if [ "${package}" != "base" ] ||
                       [ -z "$(basename $file | grep -E "^update-")" ]
                    then
                        if [ $(expr match "$system" "[a-zA-Z0-9\;-]*${EISMAN_SYSTEM}") -gt 0 ]
                        then
                            local recfile="${EISMAN_PATH}/info/${package}/${version}/$(basename $file).rec"

                            if [ ! -d "${EISMAN_PATH}/info/${package}/${version}" -o \
                                 ! -f "${recfile}" ]
                            then
                                if [ "${output}" = "--file" ]
                                then
                                    nonewline='-n'
                                fi
                                echo ${nonewline} "=> Fetching $package (${version}) ..."

                                success=0

                                # first download files into temporary locations
                                rm -f /tmp/tmpinfofile$$

                                /usr/local/bin/wget.sh -q -O /tmp/tmpinfofile$$ "$url"
                                if [ "$?" = "0" ]
                                then
                                    success=1
                                fi

                                # if successful, copy files to correct destination
                                if [ "$success" = "1" ]
                                then
                                    mkdir -p "${EISMAN_PATH}/info/${package}/${version}"

                                    "${EISMAN_BIN_PATH}/eisman_info_to_db.sh" \
                                        --url     "${file}" \
                                        --name    "${package}" \
                                        /tmp/tmpinfofile$$ \
                                        "${EISMAN_PATH}/info/${package}/${version}/$(basename $file).rec"
                                fi

                                rm -f /tmp/tmpinfofile$$

                                # show result ${output} --tty or --file
                                if [ "$success" = "1" ]
                                then
                                    mecho ${output} --ok
                                else
                                    mecho ${output} --fail
                                fi

                                # show progress of last file fetched
                                if [ "${output}" = "--tty" ]
                                then
                                    progress=$((${linecount} * 100 / ${linetotal}))
                                    show_progress "${progress}"
                                    idx2=0
                                fi
                            else
                                # update file date of recfile
                                touch "${recfile}"

                                # every 25th loop update progress
                                if [ "${output}" = "--tty" ] &&
                                   [ ${idx2} -eq 25 ]
                                then
                                    progress=$((${linecount} * 100 / ${linetotal}))
                                    show_progress "${progress}"
                                    idx2=0
                                fi
                                idx2=$((${idx2} + 1))
                            fi

                            # add file to package database. Make sure that url
                            # is correct even for existing record files
                            if [ -f "${recfile}" ]
                            then
                               local base_url

                               base_url="$(echo ${file} | cut -d '?' -f 1)"
                               base_url="$(dirname "${base_url}" | sed 's|/[0-9]*$||')"

                               sed -e "s|url        .*|url        ${file}|g" \
                                   -e "s|\[[^][]*\]|\[${base_url}]|5"    \
                                    < "${recfile}" >> "${EISMAN_PATH}/packages.db.tmp"
                            fi
                        fi
                    fi
                fi
            fi
        elif [ "${line:0:17}" = "# required_base: " ]
        then
            # get eisfair base version
            version=$(cat /etc/version)

            # compare required base version with current version
            if [ "$(${EISMAN_BIN_PATH}/eisman_check_version.sh \
                 -diff "${version}" "${line:17}")" = "old" ]
            then
                # if old, set invalid_base flag
                invalid_base='yes'
            fi
        fi
    done < /tmp/index.txt

    # when done, rename database
    rm -f "${EISMAN_PATH}/packages.db"
    mv "${EISMAN_PATH}/packages.db.tmp" "${EISMAN_PATH}/packages.db"

    # we are done !
    # ${output} --tty
    if [ "${output}" = "--tty" ]
    then
        show_progress 100
        echo
    fi
    mecho ${output} --info 'Done!'
}


# *******************************************************************
# **  clean up all info files older than 90 days. Since the mtime of
# **  all info files existing in the index is set to the current time
# **  upon update, only thme mtime of old info files becomes more and
# **  more out of date.
# **  @param  n/a
# **  @return n/a
# *******************************************************************

clean_up_info_cache()
{
    local files=$(find ${EISMAN_PATH}/info -mtime +90 -name "*.rec")
    local OLDIFS=${IFS}

    IFS="
"
    for file in ${files}
    do
        rm    -f "${file}"
        rmdir -p "$(dirname ${file})" 2> /dev/tmp
    done

    IFS="${OLDIFS}"
}


# *******************************************************************
# **  main script
# **  @param  n/a
# **  @return n/a
# *******************************************************************

main()
{
    # output shows messages in [--tty or--file] format
    # --file ist set with --quiet
    output='--tty'

    while [ "${1:0:2}" = "--" ]
    do
        case $1 in
        --help)
            show_help
            exit 0
            ;;
        --quiet)
            output='--file'
            shift
            ;;
        *)
            echo "error: unknown option \"$1\"!" >&2
            echo
            show_help
            exit 1
        esac
    done

    if [ "$#" -gt 0 ]
    then
        echo 'error: invalid number of arguments!' >&2
        echo
        show_help
        exit 1
    fi

    # get index according to configured package sources
    /var/install/bin/get-index --clear

    # create info file path
    mkdir -p "${EISMAN_PATH}/info"

    # read index line by line and fetch new info files
    update_record_files

    # remove info files older than 90 days
    clean_up_info_cache
}

main "${@}"
