#!/bin/bash
# *******************************************************************
# **  @file eisman_info_to_db.sh - copy info file into db format
# **
# **  Creation:     2013-01-12 dv
# **  Last update:  $Id: eisman_info_to_db.sh 43814 2016-10-23 14:13:16Z dv $
# **
# **  Copyright (c) 2013-2017 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


# *******************************************************************
# **  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
# **  @param  $1  path to info file
# **  @param  $2  path to output file
# **  @param  $3  url to place into the package file
# **  @return n/a
# *******************************************************************

info_to_db()
{
    local inputfile="$1"
    local outputfile="$2"
    local package="$3"
    local version="$4"
    local url="$5"
    local base_url

    # convert package url to base url
    base_url="$(get_base_url ${url})"

    # check file encoding
    local encoding="$(file -b --mime-encoding ${inputfile})"
    if [ "${encoding}" != "us-ascii" ] && [ "${encoding}" != "unknown-8bit" ]
    then
        # convert file to ascii. Use -c to ignore non-encodable characters
        if ! iconv -c -f "${encoding}" -t "us-ascii" "${inputfile}" > /tmp/info_file$$
        then
            rm -f /tmp/info_file$$
            exit 1
        else
            inputfile="/tmp/info_file$$"
        fi
    fi

    # copy info file into a temporary file and strip all comment lines.
    # note that all tag values are read from the stripped file except the
    # <description>-tag. The latter one is read directly from inputfile
    if ! grep -v -E '^[ ]*#' "${inputfile}" > /tmp/stripped_file$$
    then
        echo "error: unable to read file \"${inputfile}\"!" >&2

        # remove temporary files
        rm -f /tmp/info_file$$
        rm -f /tmp/stripped_file$$
        exit 1
    fi

    # grep out all relevant data fields
    local short=$(sed -ne 's#[ \t]*</*short>[ \t]*##gp'                /tmp/stripped_file$$ | head -n 1)
    local date=$(sed -ne 's#[ \t]*</*date>[ \t]*##gp'                  /tmp/stripped_file$$ | head -n 1 | sed 's|/|-|g' )
    local author=$(sed -ne 's#[ \t]*</*author>[ \t]*##gp'              /tmp/stripped_file$$ | head -n 1)
    local status=$(sed -ne 's#[ \t]*</*status>[ \t]*##gp'              /tmp/stripped_file$$ | head -n 1)
    local space=$(sed -ne 's#[ \t]*</*space>[ \t]*##gp'                /tmp/stripped_file$$ | head -n 1)
    local sha1sum=$(sed -ne 's#[ \t]*</*sha1sum>[ \t]*##gp'            /tmp/stripped_file$$ | head -n 1)
    local sha256sum=$(sed -ne 's#[ \t]*</*sha256sum>[ \t]*##gp'        /tmp/stripped_file$$ | head -n 1)
    local section=$(sed -ne 's#[ \t]*</*section>[ \t]*##gp'            /tmp/stripped_file$$ | head -n 1)
    local require1=$(sed -ne 's#[ \t]*</*require-lib>[ \t]*##gp'       /tmp/stripped_file$$)
    local require2=$(sed -ne 's#[ \t]*</*require-package>[ \t]*##gp'   /tmp/stripped_file$$)
    local links=$(sed -ne 's#[ \t]*</*linked-package>[ \t]*##gp'       /tmp/stripped_file$$)
    local replacements=$(sed -ne 's#[ \t]*</*replaces>[ \t]*##gp'      /tmp/stripped_file$$)
    local exclusions=$(sed -ne 's#[ \t]*</*exclude-package>[ \t]*##gp' /tmp/stripped_file$$)

    # if not given on command line, fetch version from tag "version"
    if [ -z "${version}" ]
    then
        version=$(sed -ne 's#[ \t]*</*version>[ \t]*##gp' /tmp/stripped_file$$ | head -n 1)
    fi

    # if package not given on command line, get it from info tag
    if [ -z "${package}" ]
    then
        package=$(sed -ne 's#[ \t]*</*name>[ \t]*##gp' /tmp/stripped_file$$ | head -n 1)
    fi

    # if package still empty, try old "package" tag
    if [ -z "${package}" ]
    then
        package=$(sed -ne 's#[ \t]*</*package>[ \t]*##gp' /tmp/stripped_file$$ | head -n 1)
    fi

    # if package still empty or no version is available, exit (do not create any output)
    # package and version are the minimum requirement for a package to be added to a
    # database
    if [ -z "${package}" ] || [ -z "${version}" ]
    then
        echo "error: invalid file format \"${inputfile}\"!" >&2

        # remove temporary files
        rm -f /tmp/info_file$$
        rm -f /tmp/stripped_file$$
        exit 1
    fi

    # if space is unknown, suggest it is the smallest size possible
    if [ -z "${space}" ]
    then
        space='1'
    fi

    # when no section is given, place it into "unknown"
    if [ -z "${section}" ]
    then
        section="unknown"
    fi

    # when no status is given, the package is taken as "unstable"
    if [ -z "${status}" ]
    then
        status="unstable"
    fi

    # when no short text is available, create one
    if [ -z "${short}" ]
    then
        short="${package} package"
    fi

    # get multi line text from <description> to </description>
    local text=$(sed ':a;N;$!ba;s#\\#\\\\#g;s#\n#\\n-#g' "${inputfile}" |
        sed -ne 's#^.*<description>\(.*\)</description>.*#\1#p'         |
        sed 's#\\n\\n#\\n \\n#g;s#\\n#\n#g')

    # if description is empty, create a standard text
    if [ -z "${text}" ]
    then
        text="-No further description available"
    fi

    local stat="u"
    if [ "$status" = "stable" ]
    then
        stat='s'
    fi

    {
        local line
        local dev_given

        echo "[${section}][${package}][${version}][${stat}][${base_url}]name       ${package}"
        echo "[${section}][${package}][${version}][${stat}][${base_url}]version    ${version}"
        echo "[${section}][${package}][${version}][${stat}][${base_url}]short      ${short}"
        echo "[${section}][${package}][${version}][${stat}][${base_url}]date       ${date}"
        echo "[${section}][${package}][${version}][${stat}][${base_url}]author     ${author}"
        echo "[${section}][${package}][${version}][${stat}][${base_url}]section    ${section}"
        echo "[${section}][${package}][${version}][${stat}][${base_url}]space      ${space}"
        echo "[${section}][${package}][${version}][${stat}][${base_url}]sha1sum    ${sha1sum}"
        echo "[${section}][${package}][${version}][${stat}][${base_url}]sha256sum  ${sha256sum}"
        echo "[${section}][${package}][${version}][${stat}][${base_url}]url        ${url}"
        echo "[${section}][${package}][${version}][${stat}][${base_url}]status     ${status}"

        IFS_BAK=$IFS
        IFS="
"

        # process replacements
        for line in ${replacements}
        do
            echo "[${section}][${package}][${version}][${stat}][${base_url}]replaces   ${line}"
        done

        # process exclusions
        for line in ${exclusions}
        do
            echo "[${section}][${package}][${version}][${stat}][${base_url}]exclude    ${line}"
        done

        # process requirements type 1
        for line in ${require1}
        do
            echo "[${section}][${package}][${version}][${stat}][${base_url}]require    ${line}"
        done

        # process requirements type 2
        for line in ${require2}
        do
            echo "[${section}][${package}][${version}][${stat}][${base_url}]require    ${line}"
        done

        # process linked entries
        dev_given='no'
        local len1=$((${#package} + 4))
        local len2=$((${#package} + 11))
        for line in ${links}
        do
            echo "[${section}][${package}][${version}][${stat}][${base_url}]link       ${line}"
            if [ "${line:0:${len1}}" = "${package}-dev" ] ||
               [ "${line:0:${len2}}" = "${package}-dev-static" ]
            then
                dev_given='yes'
            fi
        done

        # add implicit link to dev package neede for compatibility
        if [ "${dev_given}" = "no" ]
        then
            local pos1=$((${#package} - 4))
            local pos2=$((${#package} - 11))
            local isdev="no"
            local devpackage="${package}-dev"

            # check if package already is a dev package
            if [ "${pos1}" -gt 0 ] && [ "${pos2}" -gt 0 ]
            then
                if [ "${package:${pos1}}" = "-dev" ] || [ "${package:${pos2}}" = "-dev-static" ]
                then
                    isdev="yes"
                fi

            elif [ "${pos1}" -gt 0 ]
            then
                if [ "${package:${pos1}}" = "-dev" ]
                then
                    isdev="yes"
                fi
            fi

            # if not a dev package, create link entries
            if [ "${isdev}" = "no" ]
            then
                # handling for all (non-dev) packages
                echo "[${section}][${package}][${version}][${stat}][${base_url}]link       ${devpackage} ${version}"

                # handling for lib packages only
                if [ "${package:0:3}" = "lib" ]
                then
                    # handle only the general case
                    echo "[${section}][${package}][${version}][${stat}][${base_url}]link       ${devpackage}-static ${version}"
                fi
            fi
        fi

        # process text entries
        for line in ${text}
        do
            echo "[${section}][${package}][${version}][${stat}][${base_url}]text       ${line:1}"
        done


        IFS=${IFS_BAK}

        echo "[${section}][${package}][${version}][${stat}][${base_url}]${EISMAN_SEPARATOR}"
    } > "${outputfile}"

    # check if we are running on a temporary file and remove it
    rm -f /tmp/info_file$$
    rm -f /tmp/stripped_file$$

    if [ "$?" != "0" ]
    then
        echo "error: unable to write file \"${outputfile}\"!" >&2
        exit 1
    fi
}


# *******************************************************************
# **  main script
# **  @param  n/a
# **  @return n/a
# *******************************************************************
main()
{
    local url=''
    local name=''
    local version=''

    while [ "${1:0:2}" = "--" ]
    do
        case $1 in
        --url)
            shift
            url="$1"
            if [ "$url" = "" -o "${url:0:2}" = "--" ]
            then
                echo "error: missing argument for \"--url\"!" >&2
                exit 1
            fi
            ;;
        --url=*)
            url="${1:6}"
            ;;
        --name)
            shift
            name="$1"
            if [ "$name" = "" -o "${name:0:2}" = "--" ]
            then
                echo "error: missing argument for \"--name\"!" >&2
                exit 1
            fi
            ;;
        --name=*)
            name="${1:7}"
            ;;
        --version)
            shift
            version="$1"
            if [ "$version" = "" -o "${version:0:2}" = "--" ]
            then
                echo "error: missing argument for \"--version\"!" >&2
                exit 1
            fi
            ;;
        --version=*)
            version="${1:10}"
            ;;
        *)
            echo "error: unknown option \"$1\"!" >&2
            exit 1
        esac

        shift
    done

    if [ "$#" != "2" ]
    then
        echo "error: invalid number of arguments!" >&2
        exit 1
    fi

    local infile="${1}"
    local outfile="${2}"

    # check if file exists
    if [ ! -f "${infile}" ]
    then
        echo "error: file \"${infile}\" not found!" >&2
        exit 1
    fi

    # build file
    info_to_db "${infile}" "${outfile}" "${name}" "${version}" "${url}"

    exit 0
}

main "${@}"
