##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
## Charger nulib et rendre disponible les modules bash, awk et python
##@cooked nocomments
# Ce fichier doit être sourcé en premier. Si ce fichier n'est pas sourcé, alors
# le répertoire nulib doit être disponible dans le répertoire du script qui
# inclue ce fichier.
# Une fois ce fichier sourcé, les autres modules peuvent être importés avec
# require:() ou import:() e.g.
#     source /etc/nulib.sh || exit 1
#     import: other_modules
# ou pour une copie locale de nulib:
#     source "$(dirname "$0")/nulib/load.sh" || exit 1
#     import: other_modules

# vérifier version minimum de bash
if [ "x$BASH" = "x" ]; then
    echo "ERROR: nulib: this script requires bash"
    exit 1
fi

function base_eerror() { echo "ERROR: $*" 1>&2; }
function base_die() { [ $# -gt 0 ] && base_eerror "$*"; exit 1; }
function base_edie() { [ $# -gt 0 ] && base_eerror "$*"; return 1; }
function base_delpath() { local _qdir="${1//\//\\/}"; eval "export ${2:-PATH}; ${2:-PATH}"'="${'"${2:-PATH}"'#$1:}"; '"${2:-PATH}"'="${'"${2:-PATH}"'%:$1}"; '"${2:-PATH}"'="${'"${2:-PATH}"'//:$_qdir:/:}"; [ "$'"${2:-PATH}"'" == "$1" ] && '"${2:-PATH}"'='; }
function base_addpath() { local _qdir="${1//\//\\/}"; eval "export ${2:-PATH}; "'[ "${'"${2:-PATH}"'#$1:}" == "$'"${2:-PATH}"'" -a "${'"${2:-PATH}"'%:$1}" == "$'"${2:-PATH}"'" -a "${'"${2:-PATH}"'//:$_qdir:/:}" == "$'"${2:-PATH}"'" -a "$'"${2:-PATH}"'" != "$1" ] && '"${2:-PATH}"'="${'"${2:-PATH}"':+$'"${2:-PATH}"':}$1"'; }
function base_inspathm() { local _qdir="${1//\//\\/}"; eval "export ${2:-PATH}; "'[ "${'"${2:-PATH}"'#$1:}" == "$'"${2:-PATH}"'" -a "${'"${2:-PATH}"'%:$1}" == "$'"${2:-PATH}"'" -a "${'"${2:-PATH}"'//:$_qdir:/:}" == "$'"${2:-PATH}"'" -a "$'"${2:-PATH}"'" != "$1" ] && '"${2:-PATH}"'="$1${'"${2:-PATH}"':+:$'"${2:-PATH}"'}"'; }
function base_inspath() { base_delpath "$@"; base_inspathm "$@"; }

if [ ${BASH_VERSINFO[0]} -ge 5 -o \( ${BASH_VERSINFO[0]} -eq 4 -a ${BASH_VERSINFO[1]} -ge 1 \) ]; then :
elif [ -n "$NULIB_IGNORE_BASH_VERSION" ]; then :
else base_die "nulib: bash 4.1+ is required"
fi

# Calculer emplacement de nulib
NULIBDIR="@@dest@@/lib/nulib"
if [ "$NULIBDIR" = "@@""dest""@@/lib/nulib" ]; then
    # La valeur "@@"dest"@@" n'est remplacée que dans la copie de ce script
    # faite dans /etc. Sinon, il faut toujours faire le calcul. Cela permet de
    # déplacer la librairie n'importe ou sur le disque, ce qui est
    # particulièrement intéressant quand on fait du déploiement.
    NULIBDIR="${BASH_SOURCE[0]}"
    if [ -f "$NULIBDIR" -a "$(basename -- "$NULIBDIR")" == load.sh ]; then
        # Fichier sourcé depuis nulib/
        NULIB_SOURCED=1
        NULIBDIR="$(dirname -- "$NULIBDIR")"
    elif [ -f "$NULIBDIR" -a "$(basename -- "$NULIBDIR")" == nulib.sh ]; then
        # Fichier sourcé depuis nulib/bash
        NULIB_SOURCED=1
        NULIBDIR="$(dirname -- "$NULIBDIR")/.."
    else
        # Fichier non sourcé. Tout exprimer par rapport au script courant
        NULIB_SOURCED=
        NULIBDIR="$(dirname -- "$0")"
        if [ -d "$NULIBDIR/nulib" ]; then
            NULIBDIR="$NULIBDIR/nulib"
        elif [ -d "$NULIBDIR/lib/nulib" ]; then
            NULIBDIR="$NULIBDIR/lib/nulib"
        fi
    fi
fi
NULIBDIR="$(cd "$NULIBDIR" 2>/dev/null; pwd)"
NULIBDIRS=("$NULIBDIR/bash")

# marqueur pour vérifier que nulib a réellement été chargé. il faut avoir $NULIBINIT == $NULIBDIR
# utilisé par le module base qui doit pouvoir être inclus indépendamment
NULIBINIT="$NULIBDIR"

## Modules bash
NULIB_LOADED_MODULES=(nulib.sh)
NULIB_DEFAULT_MODULES=(base pretty sysinfos)

# Si cette variable est non vide, require: recharge toujours le module, même
# s'il a déjà été chargé. Cette valeur n'est pas transitive: il faut toujours
# recharger explicitement tous les modules désirés
NULIB_FORCE_RELOAD=

function nulib__define_functions() {
    function nulib_check_loaded() {
        local module
        for module in "${NULIB_LOADED_MODULES[@]}"; do
            [ "$module" == "$1" ] && return 0
        done
        return 1
    }
    function module:() {
        NULIB_MODULE="$1"
        NULIB_FUNC_PREFIX="$2"
        if ! nulib_check_loaded "$1"; then
            NULIB_LOADED_MODULES=("${NULIB_LOADED_MODULES[@]}" "$1")
        fi
    }
    function function:() {
        if [ -n "$NULIB_ALLOW_IMPORT" -a -n "$NULIB_FUNC_PREFIX" -a "${1#$NULIB_FUNC_PREFIX}" != "$1" ]; then
            eval "function ${1#$NULIB_FUNC_PREFIX}() { $1 \"\$@\"; }"
        fi
    }
}

function nulib__require:() {
    local nr__module nr__nulibdir nr__found
    [ $# -gt 0 ] || set DEFAULTS

    # sauvegarder valeurs globales
    local nr__orig_module="$NULIB_MODULE" nr__orig_func_prefix="$NULIB_FUNC_PREFIX"
    NULIB_MODULE=
    NULIB_FUNC_PREFIX=

    # garder une copie de la valeur originale et casser la transitivité
    local nr__force_reload="$NULIB_FORCE_RELOAD"
    local NULIB_FORCE_RELOAD

    local nr__should_import="$NULIB_SHOULD_IMPORT" nr__allow_import="$NULIB_ALLOW_IMPORT" nr__recursive_import="$NULIB_RECURSIVE_IMPORT"
    for nr__module in "$@"; do
        local NULIB_SHOULD_IMPORT="$nr__should_import" NULIB_ALLOW_IMPORT="$nr__allow_import" NULIB_RECURSIVE_IMPORT="$nr__recursive_import"
        [ -n "$NULIB_SHOULD_IMPORT" ] && NULIB_ALLOW_IMPORT=1
        nr__found=
        for nr__nulibdir in "${NULIBDIRS[@]}"; do
            if [ -f "$nr__nulibdir/$nr__module" ]; then
                nr__found=1
                if [ -n "$nr__force_reload" ] || ! nulib_check_loaded "$nr__module"; then
                    NULIB_LOADED_MODULES=("${NULIB_LOADED_MODULES[@]}" "$nr__module")
                    source "$nr__nulibdir/$nr__module" || base_die
                fi
                break
            fi
        done
        if [ -z "$nr__found" -a "$nr__module" == DEFAULTS ]; then
            for nr__module in "${NULIB_DEFAULT_MODULES[@]}"; do
                if [ -f "$nr__nulibdir/$nr__module" ]; then
                    nr__found=1
                    if [ -n "$nr__force_reload" ] || ! nulib_check_loaded "$nr__module"; then
                        NULIB_LOADED_MODULES=("${NULIB_LOADED_MODULES[@]}" "$nr__module")
                        source "$nr__nulibdir/$nr__module" || base_die
                    fi
                else
                    break
                fi
            done
        fi
        [ -n "$nr__found" ] || base_die "nulib: unable to find module $nr__module in (${NULIBDIRS[*]})"
    done

    # restaurer valeurs globales
    NULIB_MODULE="$nr__orig_module"
    NULIB_FUNC_PREFIX="$nr__orig_func_prefix"
}

function require:() {
    [ -z "$NULIB_NO_DISABLE_SET_X" ] && [[ $- == *x* ]] && { set +x; local NULIB_REQUIRE_SET_X=1; }; if [ -n "$NULIB_REQUIRE_SET_X" ]; then [ -n "$NULIB_REQUIRE_SET_X_RL1" ] || local NULIB_REQUIRE_SET_X_RL1; local NULIB_REQUIRE_SET_X_RL2=$RANDOM; [ -n "$NULIB_REQUIRE_SET_X_RL1" ] || NULIB_REQUIRE_SET_X_RL1=$NULIB_REQUIRE_SET_X_RL2; fi # désactiver set -x de manière réentrante
    local NULIB_SHOULD_IMPORT
    [ -n "$NULIB_RECURSIVE_IMPORT" -a -n "$NULIB_ALLOW_IMPORT" ] && NULIB_SHOULD_IMPORT=1
    local NULIB_ALLOW_IMPORT NULIB_RECURSIVE_IMPORT NULIB_FUNC_PREFIX
    nulib__define_functions
    nulib__require: "$@"
    [ -n "$NULIB_REQUIRE_SET_X" -a "$NULIB_REQUIRE_SET_X_RL1" == "$NULIB_REQUIRE_SET_X_RL2" ] && set -x
    return 0
}

function import:() {
    [ -z "$NULIB_NO_DISABLE_SET_X" ] && [[ $- == *x* ]] && { set +x; local NULIB_REQUIRE_SET_X=1; }; if [ -n "$NULIB_REQUIRE_SET_X" ]; then [ -n "$NULIB_REQUIRE_SET_X_RL1" ] || local NULIB_REQUIRE_SET_X_RL1; local NULIB_REQUIRE_SET_X_RL2=$RANDOM; [ -n "$NULIB_REQUIRE_SET_X_RL1" ] || NULIB_REQUIRE_SET_X_RL1=$NULIB_REQUIRE_SET_X_RL2; fi # désactiver set -x de manière réentrante
    local NULIB_SHOULD_IMPORT=1 NULIB_ALLOW_IMPORT NULIB_RECURSIVE_IMPORT NULIB_FUNC_PREFIX
    nulib__define_functions
    nulib__require: "$@"
    [ -n "$NULIB_REQUIRE_SET_X" -a "$NULIB_REQUIRE_SET_X_RL1" == "$NULIB_REQUIRE_SET_X_RL2" ] && set -x
    return 0
}

## Autres modules
base_inspath "$NULIBDIR/awk" AWKPATH; export AWKPATH
base_inspath "$NULIBDIR/python" PYTHONPATH; export PYTHONPATH

## Auto import DEFAULTS
nulib__define_functions
if [ -n "$NULIB_SOURCED" -a -z "$NULIB_NO_IMPORT_DEFAULTS" ]; then
    import: DEFAULTS
fi
