#!/usr/local/bin/bash
#
# Copyright (c) 2008, Christopher Cowart and contributors
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions 
# are met:
# * Redistributions of source code must retain the above copyright 
#   notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright 
#   notice, this list of conditions and the following disclaimer in the 
#   documentation and/or other materials provided with the distribution.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# $Id: confsync.in 586 2011-12-23 08:42:07Z blee $
#
# This script obtains the latest "export" from confman and installs
# it onto the system. It is intended to be used in crons as the
# configuration pulling mechanism.

if [ -r /usr/local/share/confman/confmancommon.sh ] ; then
    . /usr/local/share/confman/confmancommon.sh
else
    echo "Can't find confmancommon.sh. Exiting." >&2
    exit 17
fi

function print_help {
    echo "usage: $0 [-f] [-s] [-d]" >&4
    echo "Type '$0 -h' to display this help and exit." >&4
    conf_cleanExit ${1:-0}
}

FORCE=false
QUIET=false
sleep_mode=false

while getopts "fqsdh" OPT 2>&4 ; do
    case $OPT in
        f)  FORCE=true ;;
        s)  sleep_mode=true ;;
        d)  DEBUG=true ;;
        q)  QUIET=true ;;
        h)  print_help 0;;
        *)  print_help 1;;
    esac
done

# If we're in debug mode, we should log stderr messages to the logger
# as well. Otherwise, we send them to the bit bucket.
if $DEBUG ; then
    exec 1>&2
else
    exec 1>/dev/null
fi

system_lock=$(conf_lock_system)

conf_require_recipe

if $sleep_mode; then
    if [ -n "${CONF_SYNC_SLEEP}" ] && [ ${CONF_SYNC_SLEEP} -ge 0 ]; then
        echo "Sleeping ${CONF_SYNC_SLEEP} seconds..."
        sleep ${CONF_SYNC_SLEEP}
    else
        echo "Invalid sleep value: ${CONF_SYNC_SLEEP}" >&2
        exit 1
    fi
fi

# Set up our "Working Copy"
tmpdir=$(conf_tmp_dir)
WORK_PATH="$tmpdir"

tarpath=$(conf_fetch)
if ! [ -s $tarpath ] ; then
    echo "Could not fetch the export." >&2
    exit 1
fi

case ${CONF_EXPORT_STYLE} in
    repository|recipe)
        tar -xzf $tarpath -C $tmpdir
        ;;
    module)
        for layer in $(conf_get_recipe); do
            tarfile="$tarpath/$layer.tgz"
            if ! [ -s $tarfile ]; then
                echo "Could not fetch the export." >&2
                exit 1
            fi
            tar -xzf $tarfile -C $tmpdir
        done
        ;;
    *)
        echo "Unsupported export style." >&2
        exit 1
        ;;
esac

rm -rf $tarpath

tar_revision=`conf_revision`
sys_revision=`conf_sysrev`
last_action=$(conf_lastact)
statefile=$(conf_tmp_file)

if [ -n "${sys_revision}" ] ; then
    if [ "${tar_revision}" -lt "${sys_revision}" ]; then
        echo "Error: ${tarpath} is out of date. Exiting without making changes." >&2
        conf_markdirty
        conf_cleanExit 1
    elif ! ${FORCE} && [ "${tar_revision}" -eq "${sys_revision}" ]; then
        if [ "${last_action}" = "commit" -o "${last_action}" = "sync" ]; then
            ${QUIET} || echo "System is up to date." | conf_logger
            conf_cleanExit 0
        fi
    fi
fi

echo "Sync operation started" | conf_logger
for layer in $(conf_get_reverse_recipe) ; do
    echo "Rolling on $layer..."

    # XXX: Until ticket #151 is resolved, prefer to use the fdb metadata
    # when it is available
    if [ -r "$(conf_meta_dir)/${layer}.fdb" ]; then
        declare -A metadata
        filedb_load "$(conf_meta_dir)/${layer}.fdb" "metadata"
        CONF_GET_PROP_USE_FDB="true"
    fi

    conf_rollout $layer $statefile || conf_cleanExit

    if ${CONF_GET_PROP_USE_FDB}; then
        unset metadata
    fi
done
for file in $SINGULARITIES ; do
    conf_assemble_sing $file || conf_cleanExit
done
conf_markclean
conf_recordAction sync
echo "Sync operation finished successfully" | conf_logger

conf_unlock_system $system_lock

rm -rf $tmpdir

conf_cleanExit 0

