#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
source "$(dirname "$0")/lib/ulib/ulib" || exit 1
urequire DEFAULTS udir

function display_help() {
    uecho "$scriptname: gérer les variables de répertoire

USAGE
    $scriptname [options] [dir [name=value...]]

Par défaut, mettre à jour les variables du répertoire avec les définitions
données. Attention! Les définitions sont insérées ${COULEUR_JAUNE}*telles quelles*${COULEUR_NORMALE} dans le
fichier. Par exemple, pour définir une variable qui contient des espaces,
on pourra faire:
    $scriptname /path/to/dir 'var=\"value with spaces\"'
pour définir un tableau:
    $scriptname /path/to/dir 'array=(first second)'

OPTIONS
    -i
        Afficher la description du répertoire. C'est l'action par défaut si ce
        script est lancé *sans argument*
    -d
        Afficher toutes les variables définies pour le répertoire 'dir'.
    -x 'cmds;...'
        Exécuter les commandes dans le contexte des variables définies pour le
        répertoire.
    -e
        Editer les variables du répertoire
    --local-vars
        Avec -d, ajouter des directives 'local' aux définitions de variables
    -A
        Avec -d et -x, considérer les variables de tous les répertoires parents
        jusqu'à la racine. Pour ne considérer que les variables du répertoire
        spécifié (par défaut), utiliser --local-only
    --help-vars
        Afficher une descriptions des variables spécifiques aux outils de nutools"
}
function display_help_vars() {
    local OENC="$UTF8"
    uecho "\
udir_desc   Description du projet contenu dans ce répertoire, affichée avec
            'udir -i'
udir_note   Note importante concernant le contenu de ce répertoire.
            Cette note doit être affichée automatiquement quand on entre dans
            le répertoire.
udir_types  Liste de types pour ce répertoire. Les valeurs valides sont:
              uinst        -- un répertoire installable avec uinst.
              uinst:legacy -- un répertoire installable avec uinst en utilisant
                              l'ancien fichier de configuration .uinst.conf
              uinst:python -- un répertoire de projet python à installer avec
                              'python setup.py'
uinc        Mode de dépliage des fichiers avant le déploiement. Les valeurs
            valides sont:
              false   -- ne jamais faire dépliage/repliage automatique
              release -- ne faire le dépliage que lors de 'release -u'
              true    -- faire systématiquement le dépliage/repliage pour
                         chaque opération
uinc_options
            Options à passer automatiquement à uinc quand il traite ce
            répertoire
uinc_args   Liste des fichiers à traiter par uinc en mode automatique
config_scripts
            Liste de scripts de configuration à lancer avant déploiement,
            avec les droits de l'utilisateur qui lance uinst.
            Chacun de ces script est exécuté avec en unique argument un fichier
            de configuration, qui représente la somme de tous les paramètres
            qui ont été spécifiés.
            Les script peuvent augmenter ce fichier de configuration avec
            d'autres valeurs s'ils le désirent. Ces nouvelles valeurs pourront
            être utilisées par les scripts suivants, ou les scripts root.
            Pour annuler le déploiement, les scripts de configuration peuvent
            créer un fichier nommé 'abort' dans le répertoire qui contient le
            fichier de configuration. Par défaut, la variable ABORT contient le
            chemin vers ce fichier, sauf si cette variable a été surchargée par
            des paramètres du fichier de configuration.
configure_variables
            Liste de variables configurables. Pour chacune des variables de
            ce tableau, un tableau nommé configure_\${name}_for contient la
            liste des fichiers qui doivent être mis à jour. Dans ce fichiers,
            toutes les occurences de @@name@@ sont remplacées par la valeur
            de la variable \$name.
install_profiles
            Faut-il installer les profils pour l'utilisateur courant dans
            ~/etc
profiledir  Répertoire source pour les fichiers à copier dans ~/etc/profile.d
bashrcdir   Répertoire source pour les fichiers à copier dans ~/etc/bashrc.d
defaultdir  Répertoire source pour les fichiers à copier dans ~/etc/default.d
workdir_excludes
workdir_includes
            Fichiers à exclure (resp. inclure) pour construire le répertoire de
            travail avec uinst. C'est à partir du répertoire de travail que sont
            déployés les fichiers.
            La copie se faisant avec rsync, workdir_excludes spécifie les
            fichiers à exclure. workdir_includes permet de forcer l'inclusion de
            fichiers qui seraient exclus autrement.
copy_files  Faut-il copier les fichiers sources dans le répertoire de
            destination? Les fichiers sources et le répertoire de
            destination sont calculés à partir des valeurs des variables
            \$srcdir, \$files, \$destdir
srcdir      Si \$copy_files==true, répertoire source pour la copie des fichiers.
files       Liste de fichiers à copier, exprimés par rapport à srcdir.
            Si ce tableau est vide, tout le répertoire courant est déployé
            et écrase la destination. Sinon, le répertoire de destination
            n'est pas écrasé et seuls les fichiers mentionnés sont copiés.
destdir     Répertoire de base pour la copie des fichiers. Le répertoire de
            destination proprement dit est \$destdir/\$dirname où \$dirname est
            le nom de base de ce répertoire si \$files est un tableau
            vide. Sinon, la destination est \$destdir.  \$dest contient le
            répertoire de destination effectif.
owner       Propriétaire et groupe des fichiers après le déploiement. Le
            propriétaire et le groupe sont appliqués de façon récursive à tous
            les fichiers déployés.
modes       Liste de modes pour les fichiers après le déploiement. Le
            premier élément de ce tableau contient les modes à appliquer de
            façon récursive à tous les fichiers déployés. Les éléments suivants
            doivent être de la forme path:mode, où path est un chemin relatif à
            \$dest. Par contre, dans ce cas la modification du mode ne se fait
            pas de manière récursive, et il faut spécifier chaque fichier
            concerné séparément.
root_scripts
            Liste de scripts de configuration à lancer après le déploiement,
            avec les droits de root. Si des fichiers sont copiés pendant le
            déploiement, les scripts sont lancés dans le répertoire de
            destination."
}

action=auto
parse_opts "${PRETTYOPTS[@]}" \
    --help '$exit_with display_help' \
    --help-vars '$exit_with display_help_vars' \
    -u,--update action=update \
    -i,--show-desc action=desc \
    --show-note action=desc:note \
    -d,--dump action=dump \
    -x,--eval action=eval \
    -e,--edit action=edit \
    --local-vars local_vars \
    -A,--all-parents all_parents \
    --local-only local_only \
    @ args -- "$@" && set -- "${args[@]}" || die "$args"

function check_dir() { [ -d "$1" ] || die "$1: Répertoire non trouvé"; }

[ -z "$all_parents" -a -z "$local_only" ] && local_only=1
[ -z "$*" -a "$action" == "auto" ] && action=desc
[ "$action" == "auto" ] && action=update
udir="${1:-.}"; shift

if [ "$action" == "update" ]; then
    check_dir "$udir"
    if [ -z "$*" ]; then
        # pas de variable à mettre à jour, afficher simplement la note si elle existe
        udir_check "$udir" && 
        udir_eval "$udir" '[ -n "$udir_note" ] && eecho "$(ppath "$udir"): $udir_note"'
    else
        # mettre à jour les variables
        udir_create_maybe "$udir"
        udir_update "$udir" "$@"
        check_verbosity -c && udir_dump "$udir" 1>&2
    fi

elif [ "$action" == "desc" ]; then
    check_dir "$udir"
    udir_desc=
    udir_note=
    udir_ppath="$(ppath "$udir")"
    if [ "$udir_ppath" == "." ]; then
        udir_ppath="$(abspath "$udir_ppath")"
        udir_ppath="$(basename "$udir_ppath")"
    fi
    udir_eval "$udir" '
if [ -n "$udir_desc" -o -n "$udir_note" ]; then
    eecho "$udir_ppath: $udir_desc"
    [ -n "$udir_note" ] && estepe "$udir_note"
fi
'

elif [ "$action" == "desc:note" ]; then
    check_dir "$udir"
    udir_note=
    udir_eval "$udir" '
maxi="${COLUMNS:-80}"
line0="== $(basename "$PWD") "
line1=
while [ ${#line0} -lt $maxi ]; do line0="$line0="; done
while [ ${#line1} -lt $maxi ]; do line1="$line1="; done
if [ -n "$udir_note" ]; then
    eecho "$COULEUR_ROUGE$line0$COULEUR_NORMALE
$udir_note
$COULEUR_ROUGE$line1$COULEUR_NORMALE"
fi
'

elif [ "$action" == "dump" ]; then
    [ -n "$local_vars" ] && opts=(-l) || opts=()
    check_dir "$udir"
    if [ -n "$all_parents" ]; then
        udir_dump_all "${opts[@]}" "$udir"
    elif [ -n "$local_only" ]; then
        udir_dump "${opts[@]}" "$udir"
    fi

elif [ "$action" == "eval" ]; then
    check_dir "$udir"
    if [ -n "$all_parents" ]; then
        udir_eval_all "$udir" "$@"
    elif [ -n "$local_only" ]; then
        udir_eval "$udir" "$@"
    fi

elif [ "$action" == "edit" ]; then
    check_dir "$udir"
    udir_edit "$udir"
fi