# -*-shell-script-*-

# Database support routines

###
#
# This code is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# Copyright 2002-2005 Mike Hearn (mike@plan99.net)
#
###


# ensures we have an unversioned root name. If $1 is a simple name, then
# we translate it by checking first in the local package dbs,
# then if not there we can go on to check on the autopackage network (to be done)
# echos the result to stdout

# $1 = name to resolve
function _resolveName() {
    trace called with $1

    local a="$autopackage_db_location/$1"
    while true; do
	if [ ! -e "$a" ]; then
	    # we don't appear to have a reference to it in the user db
	    trace "no reference or dead symlink trail in db $autopackage_db_location"
	    break;
	elif [ -d "$a" -a -L "$a" ]; then
	    if readlink "$a" >/dev/null; then # we can optimize this so we don't run readlink twice
		a=$( readlink "$a" );
		trace read symlink as $a # should be absolute
		# loop around, tracking the symlinks as we go
	    else
		# we've encountered something, but we don't know what it is :(
		warn "unknown database entry ($a) in $autopackage_db_location"
		return 1;
	    fi
	else
	    echo "$a" | sed "s|$autopackage_db_location||; s|^/||";
	    return 0;
	fi
    done

    return 2;
}

##
# _createDBEntry
#
# Create package database entry and create necessary package data files.
# Package environment file is loaded before this call so all variables are set.
function _createDBEntry() {

    outputStatus "$intl_UPDATING_DB"
    mkdirs --session --nolog "${autopackage_db_location}/${ROOTNAME}"

    trace linking from \"$autopackage_db_location/${SHORTNAME}-${SOFTWAREVERSION}\" to \"$autopackage_db_location/$ROOTNAME\"
    ln -s -f "$autopackage_db_location/$ROOTNAME" "$autopackage_db_location/${SHORTNAME}-${SOFTWAREVERSION}"
    logCommand --session "removeFile `escapeFilename \"$autopackage_db_location/${SHORTNAME}-${SOFTWAREVERSION}\"`"

    trace linking from \"$autopackage_db_location/${SHORTNAME}\" to  \"$autopackage_db_location/${SHORTNAME}-${SOFTWAREVERSION}\"
    ln -s -f "$autopackage_db_location/${SHORTNAME}-${SOFTWAREVERSION}" "$autopackage_db_location/${SHORTNAME}"
    logCommand --session "removeFile `escapeFilename \"$autopackage_db_location/${SHORTNAME}\"`"

    # create eula file if interim marker is present
    if [ -e "$_meta_dir/apkg-eula-$SHORTNAME" ]; then
        if [[ `id -u` == "0" ]]; then
            trace creating eula file "$AUTOPACKAGE_CONFIG_DIR/eulas/$SHORTNAME-$SOFTWAREVERSION-$PACKAGEVERSION"
            copyFile --silent --nobackup "$_meta_dir/apkg-eula-$SHORTNAME" "$AUTOPACKAGE_CONFIG_DIR/eulas/$SHORTNAME-$SOFTWAREVERSION-$PACKAGEVERSION"
        else
            trace creating eula file "$AUTOPACKAGE_CONFIG_HOME/eulas/$SHORTNAME-$SOFTWAREVERSION-$PACKAGEVERSION"
            copyFile --silent --nobackup "$_meta_dir/apkg-eula-$SHORTNAME" "$AUTOPACKAGE_CONFIG_HOME/eulas/$SHORTNAME-$SOFTWAREVERSION-$PACKAGEVERSION"
        fi
        copyFiles --silent --nobackup "$_meta_dir/eula" "$autopackage_db_location/$ROOTNAME"
    fi

    # create log file
    trace creating log file $autopackage_db_location/$ROOTNAME/log
    [ ! -f "$apkg_logfile" ] && touch "$apkg_logfile"

    # A - from file listing - gather file sizes, write dirname to uninstalldirs, write filelist to log
    installsize=0
    if [ -f "$apkg_filelist" ]; then
        while read; do
            filesize=`getFile --no-newline --no-whitespace --size "$REPLY"`
            [ "$filesize" ] && let "installsize = $installsize + $filesize"
            echo removeFile "`escapeFilename \"$REPLY\"`"
            local uninstalldirs_dir=`dirname "$REPLY"`
            echo "$uninstalldirs_dir" >> "$apkg_uninstalldirs"
        done < "$apkg_filelist" >> "$autopackage_db_location/$ROOTNAME/log"
    fi

    # B - create file list
    trace creating file listing $autopackage_db_location/$ROOTNAME/files
    [ ! -f "$apkg_filelist" ] && touch "$apkg_filelist"
    cat "$apkg_filelist" >> "$autopackage_db_location/$ROOTNAME/files"
    logCommand --session "removeFile `escapeFilename \"$autopackage_db_location/$ROOTNAME/files\"`"

    # C - from baseline file gather file sizes for precise total install size, write filenames to filelist
    if [[ -f "$_meta_dir/baseline" ]]; then
        while read; do
            local config_filename=`echo "$REPLY"| awk '{print $2}'`
            filesize=`getFile --no-newline --no-whitespace --size "$config_filename"`
            [ "$filesize" ] && let "installsize = $installsize + $filesize"
            echo "$config_filename" >> "$autopackage_db_location/$ROOTNAME/files"
        done < "$_meta_dir/baseline"
    fi

    # D - next uninstall folders after collecting, sorting, and making unique
    # collection is from logDir and dirname calls from apkg_filelist
    if [ -f "$apkg_uninstalldirs" ]; then
        local tmp_uninstalldirs=`<"$apkg_uninstalldirs"`
        echo "$tmp_uninstalldirs" | sort -r | uniq > "$apkg_uninstalldirs"
        while read; do
            echo removeDir "`escapeFilename \"$REPLY\"`"
        done < "$apkg_uninstalldirs" >> "$autopackage_db_location/$ROOTNAME/log"
    fi

    # E - finally append the package installation log
    tac "$apkg_logfile" >> "$autopackage_db_location/$ROOTNAME/log"
    logCommand --session "removeFile `escapeFilename \"$autopackage_db_location/$ROOTNAME/log\"`"

    # create uninstall file
    trace creating uninstall file $autopackage_db_location/$ROOTNAME/uninstall
    [ ! -f "$_meta_dir/apkg-uninstall" ] && touch "$_meta_dir/apkg-uninstall"
    cat "$_meta_dir/apkg-uninstall" > "$autopackage_db_location/$ROOTNAME/uninstall"
    logCommand --session "removeFile `escapeFilename \"$autopackage_db_location/$ROOTNAME/uninstall\"`"

    # create verification file
    trace create verification file $autopackage_db_location/$ROOTNAME/verification
    [ ! -f "$_meta_dir/verification" ] && touch "$_meta_dir/verification"
    cat "$_meta_dir/verification" >> "$autopackage_db_location/$ROOTNAME/verification"
    logCommand --session "removeFile `escapeFilename \"$autopackage_db_location/$ROOTNAME/verification\"`"

    # go through language list and copy over package environment files and append environment variables
    for language in $PACKAGELANGUAGES; do

        trace copying package environment from "$autopackage_db_location/$ROOTNAME/environment.${language}"
        cp "$_meta_dir/environment.${language}" "$autopackage_db_location/$ROOTNAME"
        echo "export INSTALLSIZE=\"$installsize\"" >> "$autopackage_db_location/$ROOTNAME/environment.${language}"
        logCommand --session "removeFile `escapeFilename \"$autopackage_db_location/$ROOTNAME/environment.${language}\"`"

    done

    # create baseline file $autopackage_db_location/$ROOTNAME/baseline
    trace create verification file $autopackage_db_location/$ROOTNAME/baseline
    [ ! -f "$_meta_dir/baseline" ] && touch "$_meta_dir/baseline"
    cat "$_meta_dir/baseline" >> "$autopackage_db_location/$ROOTNAME/baseline"
    logCommand --session "removeFile `escapeFilename \"$autopackage_db_location/$ROOTNAME/baseline\"`"

}


# Figures out which database to use (global or user) and sets the autopackage_db_location variable
function _initializePackageDB() {
  trace called
  if ! haveWriteAccess "$autopackage_global_db_location"; then
    if [[ "$autopackage_user_db_location" != "" ]]; then
      export autopackage_db_location=`eval echo $autopackage_user_db_location`
      trace user prefix:autopackage_db_location=$autopackage_db_location
    else
      # default if none is set in config file
      export autopackage_db_location="$HOME/.packages"
      trace no prefix:autopackage_db_location=$autopackage_db_location
    fi
  else
    export autopackage_db_location="$autopackage_global_db_location"
    trace global prefix:autopackage_db_location=$autopackage_db_location
  fi
}

# Is the given root name in the database?
function isNameKnown() {
    if [ -e "$autopackage_global_db_location/$1/environment.en" ] || [ -e "$autopackage_user_db_location/$1/environment.en" ]; then
	return 0;
    fi
    return 1;
}

##
# _listPackagesDB [OPTION]
# --user: provides only packages that the user can modify
#
# List package filenames from available package databases.
function _listPackagesDB() {

    trace called

    local user_mode=false
    if [[ "$1" == "--user" ]] && [[ `id -u` != "0" ]]; then
        trace set user mode
        user_mode=true
        shift
    fi

    if [[ `id -u` != "0" ]]; then
        if [ -d "$autopackage_user_db_location" ]; then
            _listPackagesDBDir "$autopackage_user_db_location"
        else
            trace User package directory does not exist: $autopackage_user_db_location
        fi
    fi

    if ! $user_mode && [ -d "$autopackage_global_db_location" ]; then
        _listPackagesDBDir "$autopackage_global_db_location"
    else
        trace Global package directory does not exist: $autopackage_global_db_location
    fi
    return 0

}


##
# _listPackagesDBDir <DIRECTORY>
# RETURNS: 0 if successful.<br />1 if DIRECTORY does not exist.
#
# List the info directories for each installed package in the given database directory.
#
# Example:
#   _listPackagesDBDir /var/packages
#
#   /var/packages/@inkscape.org/inkscape:0.42
#
function _listPackagesDBDir() {

    trace called with $1

    if [ ! -d "$1" ]; then
        warn Package database directory does not exist: $1
        echo
        return 1
    fi
    cd "$1"
    for f in `ls -1 | grep -v '^@'`; do
        _resolveLink "$f"
    done | sort | uniq
    cd - >/dev/null
    return 0
}
