675 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
			
		
		
	
	
			675 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
 | 
						|
## Gestion de fichiers modèles
 | 
						|
##@cooked nocomments
 | 
						|
##@require base
 | 
						|
uprovide template
 | 
						|
urequire base
 | 
						|
 | 
						|
function __template_prel_abspath() {
 | 
						|
    # afficher le chemin absolu du fichier $1. Si $1 est un chemin relatif, le
 | 
						|
    # répertoire de référence pour le calcul du chemin absolu dépend du
 | 
						|
    # répertoire courant: si l'on est dans un des sous-répertoires du répertoire
 | 
						|
    # de destination $2, calculer le chemin absolu par rapport au répertoire
 | 
						|
    # courant. Sinon, l'exprimer par rapport à $2.
 | 
						|
    if withinpath "$2" "$(pwd)"; then
 | 
						|
        abspath "$1"
 | 
						|
    else
 | 
						|
        abspath "$1" "$2"
 | 
						|
    fi
 | 
						|
}
 | 
						|
function __template_check_srcdir() {
 | 
						|
    [ -n "$1" ] || {
 | 
						|
        eerror "Vous devez spécifier le répertoire source"
 | 
						|
        return 1
 | 
						|
    }
 | 
						|
    [ -d "$1" ] || {
 | 
						|
        eerror "$1: répertoire source introuvable"
 | 
						|
        return 1
 | 
						|
    }
 | 
						|
    return 0
 | 
						|
}
 | 
						|
function __template_check_destdir() {
 | 
						|
    [ -n "$1" ] || {
 | 
						|
        eerror "Vous devez spécifier le répertoire de destination"
 | 
						|
        return 1
 | 
						|
    }
 | 
						|
    [ -d "$1" ] || {
 | 
						|
        eerror "$1: répertoire destination introuvable"
 | 
						|
        return 1
 | 
						|
    }
 | 
						|
    return 0
 | 
						|
}
 | 
						|
function __template_plsort() {
 | 
						|
    # Trier par taille du chemin
 | 
						|
    awk '{print length($0) ":" $0}' |
 | 
						|
    sort -n "$@" |
 | 
						|
    awk '{sub(/[0-9]+:/, ""); print}'
 | 
						|
}
 | 
						|
function __template_search_destdir() {
 | 
						|
    # Chercher à partir du répertoire courant si un des répertoires parents
 | 
						|
    # s'appelle $1. Retourner vrai si le répertoire a été trouvé.
 | 
						|
    local dir="$(pwd)" dirname
 | 
						|
 | 
						|
    while true; do
 | 
						|
        setx dirname=basename -- "$dir"
 | 
						|
        if [ "$dir" == / ]; then
 | 
						|
            # s'arrêter à la racine
 | 
						|
            return 1
 | 
						|
        elif [ "$dir" == "$HOME" ]; then
 | 
						|
            # s'arrêter au répertoire HOME
 | 
						|
            return 1
 | 
						|
        elif [ "$dirname" == "$1" ]; then
 | 
						|
            echo "$dir"
 | 
						|
            return 0
 | 
						|
        elif [ "$dirname" == ".$1" ]; then
 | 
						|
            echo "$dir"
 | 
						|
            return 0
 | 
						|
        fi
 | 
						|
        setx dir=dirname -- "$dir"
 | 
						|
    done
 | 
						|
}
 | 
						|
function __template_set_destdir() {
 | 
						|
    local __destdir="${1:-destdir}" __autocreate="${2:-autocreate}" __name="${3:-template}"
 | 
						|
    setv "$__autocreate"
 | 
						|
    if [ -z "${!__destdir}" ]; then
 | 
						|
        if [ -d "$__name" ]; then
 | 
						|
            setv "$__destdir" "$__name"
 | 
						|
        elif [ -d ".$__name" ]; then
 | 
						|
            setv "$__destdir" ".$__name"
 | 
						|
        elif setx "$__destdir" __template_search_destdir "$__name"; then
 | 
						|
            estepn "Sélection automatique de $(ppath "${!__destdir}")"
 | 
						|
        elif [ -e "$__name" ]; then
 | 
						|
            eerror "Vous devez spécifier le répertoire de destination avec -d"
 | 
						|
            return 1
 | 
						|
        else
 | 
						|
            setv "$__destdir" "$__name"
 | 
						|
            setv "$__autocreate" 1
 | 
						|
        fi
 | 
						|
    fi
 | 
						|
    setx "$__destdir" abspath "${!__destdir}"
 | 
						|
    return 0
 | 
						|
}
 | 
						|
function __template_set_var() {
 | 
						|
    # Mettre à jour la variable $1 avec la valeur $2 en tenant compte de
 | 
						|
    # certaines dépendances. Par exemple, si on modifie host, il faut mettre à
 | 
						|
    # jour hostname.
 | 
						|
    # La variable __TEMPLATE_DEFAULTF_var contient le nom d'une fonction qui
 | 
						|
    # retourne la valeur par défaut de la variable. Cette fonction est appelée
 | 
						|
    # avec le nom de la variable comme premier argument.
 | 
						|
    # La variable __TEMPLATE_UPDATEF_var contient le nom d'une fonction qui met
 | 
						|
    # à jour les variables dépendantes. Cette fonction est appelée avec le nom
 | 
						|
    # de la variable comme premier argument et sa nouvelle valeur en deuxième
 | 
						|
    # argument.
 | 
						|
    # Retourner vrai si la valeur a été changée
 | 
						|
    local __orig_value="${!1}"
 | 
						|
    local __defaultf="__TEMPLATE_DEFAULTF_$1" __updatef="__TEMPLATE_UPDATEF_$1"
 | 
						|
 | 
						|
    array_contains TEMPLATE_DYNAMIC_VARS "$1" || array_addu TEMPLATE_STATIC_VARS "$1"
 | 
						|
    [ "$3" == writable ] && array_del TEMPLATE_NOWRITE_VARS
 | 
						|
 | 
						|
    [ -z "$2" -a -n "${!__defaultf}" ] && set -- "$1" "$("${!__defaultf}" "$1")"
 | 
						|
    setv "$1" "$2"
 | 
						|
    [ -n "${!__updatef}" ] && "${!__updatef}" "$1" "$2"
 | 
						|
    [ "$2" != "$__orig_value" ]
 | 
						|
}
 | 
						|
 | 
						|
# liste des variables qu'il faut remplacer dans les fichiers sources
 | 
						|
TEMPLATE_STATIC_VARS=()
 | 
						|
function __template_setup_tmpfile() {
 | 
						|
    if [ ${#TEMPLATE_STATIC_VARS[*]} -gt 0 ]; then
 | 
						|
        # S'il y a des variables à remplacer, préparer un fichier temporaire
 | 
						|
        ac_set_tmpfile tmpfile
 | 
						|
    fi
 | 
						|
}
 | 
						|
function __template_clean_tmpfile() {
 | 
						|
    if [ ${#TEMPLATE_STATIC_VARS[*]} -gt 0 ]; then
 | 
						|
        ac_clean "$tmpfile"
 | 
						|
    fi
 | 
						|
}
 | 
						|
function __template_fillvars() {
 | 
						|
    # Pour chacune des variables VAR de TEMPLATE_STATIC_VARS, remplacer dans le
 | 
						|
    # fichier $1 les occurences de @@VAR@@ par la valeur $VAR
 | 
						|
    # Afficher le chemin vers le fichier temporaire qui contient le fichier
 | 
						|
    # modifié. Si $2 est spécifié, prendre ce chemin comme fichier temporaire.
 | 
						|
    # Sinon, créer un nouveau fichier temporaire. Si le fichier ne contient
 | 
						|
    # aucune occurence de variable, afficher le chemin original $1.
 | 
						|
    [ ${#TEMPLATE_STATIC_VARS[*]} -eq 0 ] && { echo "$1"; return; }
 | 
						|
 | 
						|
    # chercher si le fichier contient au moins un des tags de
 | 
						|
    # TEMPLATE_STATIC_VARS
 | 
						|
    local __var __tag __found
 | 
						|
    for __var in "${TEMPLATE_STATIC_VARS[@]}"; do
 | 
						|
        __tag="@@${__var}@@"
 | 
						|
        if quietgrep "$__tag" "$1"; then
 | 
						|
            __found=1
 | 
						|
            break
 | 
						|
        fi
 | 
						|
    done
 | 
						|
    [ -n "$__found" ] || { echo "$1"; return; }
 | 
						|
 | 
						|
    # construire le script sed pour le remplacement des variables
 | 
						|
    local __script __first=1 __repl
 | 
						|
    for __var in "${TEMPLATE_STATIC_VARS[@]}"; do
 | 
						|
        [ -n "$__first" ] || __script="$__script"$'\n'
 | 
						|
        __first=
 | 
						|
        __script="${__script}s/@@${__var}@@/$(qseds "${!__var}")/g"
 | 
						|
    done
 | 
						|
 | 
						|
    sed "$__script" <"$1" >"$2"
 | 
						|
    echo "$2"
 | 
						|
}
 | 
						|
 | 
						|
function template_list() {
 | 
						|
# Soit $N le séparateur --, lister les fichiers des répertoires sources
 | 
						|
# $2..$(N-1) qui seraient fusionnés avec template_merge() ou supprimés avec
 | 
						|
# template_unmerge() du répertoire destination $1. Si des chemins sont spécifiés
 | 
						|
# avec les arguments $(N+1)..@, ne traiter que les fichiers qui correspondent à
 | 
						|
# ces spécifications. Exemple:
 | 
						|
#     template_list destdir srcdirs... -- specs...
 | 
						|
    local destdir="${1:-.}"; shift
 | 
						|
    __template_check_destdir "$destdir" || return 1
 | 
						|
    setx destdir=abspath "$destdir"
 | 
						|
 | 
						|
    local -a srcdirs; local srcdir
 | 
						|
    while [ $# -gt 0 ]; do
 | 
						|
        srcdir="$1"; shift
 | 
						|
        [ "$srcdir" == -- ] && break
 | 
						|
        __template_check_srcdir "$srcdir" || return 1
 | 
						|
        setx srcdir=abspath "$srcdir"
 | 
						|
        array_add srcdirs "$srcdir"
 | 
						|
    done
 | 
						|
 | 
						|
    local rel2pwd
 | 
						|
    withinpath "$destdir" "$(pwd)" && rel2pwd=1
 | 
						|
 | 
						|
    if [ $# -eq 0 ]; then
 | 
						|
        [ -n "$rel2pwd" ] && set -- . || set -- "$destdir"
 | 
						|
    fi
 | 
						|
 | 
						|
    local tmpfile; __template_setup_tmpfile
 | 
						|
 | 
						|
    local spec srcspec src content dest list
 | 
						|
    local -a srcfiles
 | 
						|
    for spec in "$@"; do
 | 
						|
        setx srcspec=__template_prel_abspath "$spec" "$destdir"
 | 
						|
        withinpath "$destdir" "$srcspec" || continue
 | 
						|
        srcspec="${srcspec#$destdir}"
 | 
						|
 | 
						|
        for srcdir in "${srcdirs[@]}"; do
 | 
						|
            [ -e "$srcdir$srcspec" ] || continue
 | 
						|
            array_from_lines srcfiles "$(find "$srcdir$srcspec" -type f)"
 | 
						|
            for src in "${srcfiles[@]}"; do
 | 
						|
                setx content=__template_fillvars "$src" "$tmpfile"
 | 
						|
                dest="$destdir/${src#$srcdir/}"
 | 
						|
 | 
						|
                list=
 | 
						|
                if [ -L "$dest" ]; then
 | 
						|
                    :
 | 
						|
                elif [ -f "$dest" ]; then
 | 
						|
                    testsame "$content" "$dest" && list=1
 | 
						|
                else
 | 
						|
                    list=1
 | 
						|
                fi
 | 
						|
                [ -n "$list" ] || continue
 | 
						|
 | 
						|
                if [ -n "$rel2pwd" ]; then
 | 
						|
                    relpath "$dest"
 | 
						|
                else
 | 
						|
                    echo "${src#$srcdir/}"
 | 
						|
                fi
 | 
						|
            done
 | 
						|
        done
 | 
						|
    done | csort -u
 | 
						|
 | 
						|
    __template_clean_tmpfile
 | 
						|
}
 | 
						|
 | 
						|
function template_merge() {
 | 
						|
# Soit $N le séparateur --, copier dans le répertoire destination $1 les
 | 
						|
# fichiers des répertoires sources $2..$(N-1) correspondant aux spécifications
 | 
						|
# $(N+1)..@, si ces fichiers n'ont pas été modifiés dans le répertoire de
 | 
						|
# destination.
 | 
						|
# Les fichiers sources ayant l'extension .template sont ignorés par défaut, sauf
 | 
						|
# s'ils sonts demandés explicitement. Exemple:
 | 
						|
#     template_merge destdir srcdirs... -- specs...
 | 
						|
    local destdir="${1:-.}"; shift
 | 
						|
    __template_check_destdir "$destdir" || return 1
 | 
						|
    setx destdir=abspath "$destdir"
 | 
						|
 | 
						|
    local -a srcdirs; local srcdir
 | 
						|
    while [ $# -gt 0 ]; do
 | 
						|
        srcdir="$1"; shift
 | 
						|
        [ "$srcdir" == -- ] && break
 | 
						|
        __template_check_srcdir "$srcdir" || return 1
 | 
						|
        setx srcdir=abspath "$srcdir"
 | 
						|
        array_add srcdirs "$srcdir"
 | 
						|
    done
 | 
						|
 | 
						|
    [ $# -gt 0 ] || set -- "$destdir"
 | 
						|
 | 
						|
    local tmpfile; __template_setup_tmpfile
 | 
						|
 | 
						|
    local spec template srcspec src content dest
 | 
						|
    local srcfiles
 | 
						|
    for spec in "$@"; do
 | 
						|
        setb template=[ "${spec%.template}" != "$spec" ]
 | 
						|
        setx srcspec=__template_prel_abspath "$spec"
 | 
						|
        if ! withinpath "$destdir" "$srcspec"; then
 | 
						|
            ewarn "$spec: fichier ignoré"
 | 
						|
            continue
 | 
						|
        fi
 | 
						|
        srcspec="${srcspec#$destdir}"
 | 
						|
 | 
						|
        for srcdir in "${srcdirs[@]}"; do
 | 
						|
            if [ -z "$template" -a ! -e "$srcdir$srcspec" -a -e "$srcdir$srcspec.template" ]; then
 | 
						|
                srcspec="$srcspec.template"
 | 
						|
                template=1
 | 
						|
            fi
 | 
						|
            [ -e "$srcdir$srcspec" ] || continue
 | 
						|
            ebegin "$(basename -- "$srcdir") --> $(ppath "$destdir$srcspec")"
 | 
						|
            s=0
 | 
						|
            if [ -n "$template" ]; then
 | 
						|
                array_from_lines srcfiles "$(find "$srcdir$srcspec" -type f)"
 | 
						|
            else
 | 
						|
                array_from_lines srcfiles "$(find "$srcdir$srcspec" -type f | grep -v '\.template$')"
 | 
						|
            fi
 | 
						|
            for src in "${srcfiles[@]}"; do
 | 
						|
                setx content=__template_fillvars "$src" "$tmpfile"
 | 
						|
                dest="$destdir/${src#$srcdir/}"
 | 
						|
                [ -n "$template" ] && dest="${dest%.template}"
 | 
						|
 | 
						|
                if [ -L "$dest" ]; then
 | 
						|
                    edotw 0 "LOCALLY MODIFIED: $(ppath "$dest")"
 | 
						|
                elif [ -f "$dest" ]; then
 | 
						|
                    if testsame "$content" "$dest"; then
 | 
						|
                        show_debug && edot 0 "ALREADY COPIED: $(ppath "$dest")"
 | 
						|
                    else
 | 
						|
                        edotw 0 "LOCALLY MODIFIED: $(ppath "$dest")"
 | 
						|
                    fi
 | 
						|
                else
 | 
						|
                    mkdirof "$dest"
 | 
						|
                    cp "$content" "$dest"; r=$?
 | 
						|
                    edot $r "COPY: $(ppath "$dest")"
 | 
						|
                    [ $r -eq 0 ] || s=$r
 | 
						|
                fi
 | 
						|
            done
 | 
						|
            eend $s
 | 
						|
        done
 | 
						|
    done
 | 
						|
 | 
						|
    __template_clean_tmpfile
 | 
						|
}
 | 
						|
 | 
						|
function template_unmerge() {
 | 
						|
# Soit $N le séparateur --, supprimer du répertoire destination $1 les fichiers
 | 
						|
# provenant des répertoires sources $2..$(N-1) et qui n'ont pas été modifiés. Si
 | 
						|
# des chemins sont spécifiés avec les arguments $(N+1)..@, ne traiter que les
 | 
						|
# fichiers qui correspondent à ces spécifications. Exemple:
 | 
						|
#     template_unmerge destdir srcdirs... -- specs...
 | 
						|
    local destdir="${1:-.}"; shift
 | 
						|
    __template_check_destdir "$destdir" || return 1
 | 
						|
    setx destdir=abspath "$destdir"
 | 
						|
 | 
						|
    local -a srcdirs; local srcdir
 | 
						|
    while [ $# -gt 0 ]; do
 | 
						|
        srcdir="$1"; shift
 | 
						|
        [ "$srcdir" == -- ] && break
 | 
						|
        __template_check_srcdir "$srcdir" || return 1
 | 
						|
        setx srcdir=abspath "$srcdir"
 | 
						|
        array_add srcdirs "$srcdir"
 | 
						|
    done
 | 
						|
 | 
						|
    [ $# -gt 0 ] || set -- "$destdir"
 | 
						|
 | 
						|
    local tmpfile; __template_setup_tmpfile
 | 
						|
 | 
						|
    local spec srcspec src content dest
 | 
						|
    local srcfiles
 | 
						|
    for spec in "$@"; do
 | 
						|
        setx srcspec=__template_prel_abspath "$spec"
 | 
						|
        if ! withinpath "$destdir" "$srcspec"; then
 | 
						|
            ewarn "$spec: fichier ignoré"
 | 
						|
            continue
 | 
						|
        fi
 | 
						|
        srcspec="${srcspec#$destdir}"
 | 
						|
 | 
						|
        for srcdir in "${srcdirs[@]}"; do
 | 
						|
            [ -e "$srcdir$srcspec" ] || continue
 | 
						|
            s=0
 | 
						|
            ebegin "$(ppath "$destdir$srcspec")"
 | 
						|
            array_from_lines files "$(find "$srcdir$srcspec" -type f)"
 | 
						|
            for src in "${files[@]}"; do
 | 
						|
                setx content=__template_fillvars "$src" "$tmpfile"
 | 
						|
                dest="$destdir/${src#$srcdir/}"
 | 
						|
 | 
						|
                if [ -L "$dest" ]; then
 | 
						|
                    edotw 0 "LOCALLY MODIFIED: $(ppath "$dest")"
 | 
						|
                elif [ -f "$dest" ]; then
 | 
						|
                    if testsame "$content" "$dest"; then
 | 
						|
                        rm -f "$dest"; r=$?
 | 
						|
                        edot $r "REMOVE: $(ppath "$dest")"
 | 
						|
                        [ $r -eq 0 ] || s=$r
 | 
						|
                    else
 | 
						|
                        edotw 0 "LOCALLY MODIFIED: $(ppath "$dest")"
 | 
						|
                    fi
 | 
						|
                else
 | 
						|
                    show_debug && edot 0 "ALREADY REMOVED: $(ppath "$dest")"
 | 
						|
                fi
 | 
						|
            done
 | 
						|
            eend $s
 | 
						|
        done
 | 
						|
    done
 | 
						|
 | 
						|
    __template_clean_tmpfile
 | 
						|
}
 | 
						|
 | 
						|
function template_cleandest() {
 | 
						|
# Supprimer dans le répertoire de destination $1 tous les répertoires vides.
 | 
						|
# Cette fonction est habituellement utilisée après template_unmerge()
 | 
						|
# Ignorer les chemins qui contiennent .git/ et .svn/
 | 
						|
    local -a dirs
 | 
						|
    [ -d "$1" ] || return 1
 | 
						|
    array_from_lines dirs "$(cd "$1"; find . -type d | grep -v .git/ | grep -v .svn/ | __template_plsort -r)"
 | 
						|
    array_del dirs .
 | 
						|
    (cd "$1"; rmdir "${dirs[@]}" 2>/dev/null)
 | 
						|
}
 | 
						|
 | 
						|
function template_diff() {
 | 
						|
# Afficher les différences entre les fichiers du répertoire de destination $1 et
 | 
						|
# les fichiers des répertoires sources $2..@
 | 
						|
    local destdir="${1:-.}"; shift
 | 
						|
    __template_check_destdir "$destdir" || return 1
 | 
						|
    setx destdir=abspath "$destdir"
 | 
						|
 | 
						|
    local -a srcdirs; local srcdir
 | 
						|
    while [ $# -gt 0 ]; do
 | 
						|
        srcdir="$1"; shift
 | 
						|
        [ "$srcdir" == -- ] && break
 | 
						|
        __template_check_srcdir "$srcdir" || return 1
 | 
						|
        setx srcdir=abspath "$srcdir"
 | 
						|
        array_add srcdirs "$srcdir"
 | 
						|
    done
 | 
						|
 | 
						|
    local tmpfile; __template_setup_tmpfile
 | 
						|
 | 
						|
    local src content dest
 | 
						|
    local -a srcfiles
 | 
						|
    for srcdir in "${srcdirs[@]}"; do
 | 
						|
        array_from_lines srcfiles "$(find "$srcdir" -type f)"
 | 
						|
        for src in "${srcfiles[@]}"; do
 | 
						|
            setx content=__template_fillvars "$src" "$tmpfile"
 | 
						|
            dest="$destdir/${src#$srcdir/}"
 | 
						|
            if [ -f "$dest" ] && testdiff "$content" "$dest"; then
 | 
						|
                diff -uwB "$content" "$dest"
 | 
						|
            fi
 | 
						|
        done
 | 
						|
    done | page_maybe -S
 | 
						|
 | 
						|
    __template_clean_tmpfile
 | 
						|
}
 | 
						|
 | 
						|
function template_srcdir() {
 | 
						|
# Obtenir le chemin vers le répertoire source de templates $1, situé dans
 | 
						|
# ULIBDIR/templates
 | 
						|
    urequire ulib
 | 
						|
    if [ -n "$ULIBDIR" ]; then
 | 
						|
        echo "$ULIBDIR/templates/$1"
 | 
						|
    else
 | 
						|
        abspath "templates/$1"
 | 
						|
    fi
 | 
						|
}
 | 
						|
 | 
						|
function template_build_vars() {
 | 
						|
# Initialiser les tableaux $1 et $2 avec la description des variables $3..@
 | 
						|
# les descriptions sont de la forme var[:depvars,...]=desc
 | 
						|
# $1 reçoit les noms (depvars... var) parce que les variables dépendantes
 | 
						|
# doivent toujours être placées AVANT la variable maitre
 | 
						|
# $2 reçoit les noms (depvars...)
 | 
						|
# pour chaque description, une variable __TEMPLATE_DESC_var est créée avec
 | 
						|
# la valeur desc
 | 
						|
    local __t_destvs="$1"; shift
 | 
						|
    local __t_destnw="$1"; shift
 | 
						|
    local -a __t_depvars
 | 
						|
    local __t_vardesc __t_var __t_depvar __t_desc
 | 
						|
    for __t_vardesc in "$@"; do
 | 
						|
        splitvar "$__t_vardesc" __t_depvar __t_desc
 | 
						|
        splitpair "$__t_depvar" __t_var __t_depvar
 | 
						|
        array_split __t_depvars "$__t_depvar" ,
 | 
						|
        for __t_depvar in "${__t_depvars[@]}"; do
 | 
						|
            array_addu "$__t_destvs" "$__t_depvar"
 | 
						|
            [ -n "$__t_destnw" ] && array_addu "$__t_destnw" "$__t_depvar"
 | 
						|
        done
 | 
						|
        array_del "$__t_destvs" "$__t_var"
 | 
						|
        array_add "$__t_destvs" "$__t_var"
 | 
						|
        eval "__TEMPLATE_DESC_$__t_var=\"\$__t_desc\""
 | 
						|
    done
 | 
						|
}
 | 
						|
 | 
						|
function templatectl_config() {
 | 
						|
# Obtenir le chemin vers le fichier de configuration pour le répertoire $1 Si
 | 
						|
# l'un des fichiers CONFIG.conf ou .CONFIG existent déjà, prendre ceux-là.
 | 
						|
# Sinon, si $2==nohideconfig, utiliser le nom CONFIG.conf, sinon utiliser
 | 
						|
# .CONFIG
 | 
						|
    local config="$(basename -- "$TEMPLATECTL_CONFIG")"
 | 
						|
    if [ -f "$1/$config.conf" ]; then echo "$1/$config.conf"
 | 
						|
    elif [ -f "$1/.$config" ]; then echo "$1/.$config"
 | 
						|
    elif [ "$2" == nohideconfig ]; then echo "$1/$config.conf"
 | 
						|
    else echo "$1/.$config"
 | 
						|
    fi
 | 
						|
}
 | 
						|
 | 
						|
function templatectl_loadvars() {
 | 
						|
# Charger les valeurs des variables depuis le fichier $1
 | 
						|
# Les variables suivantes doivent être définies:
 | 
						|
# - Le tableau TEMPLATECTL_DEFAULTS permet de donner une valeur par défaut aux
 | 
						|
#   variables mentionnées dans TEMPLATE_STATIC_VARS. C'est une liste de valeurs
 | 
						|
#   de la forme 'name=value'
 | 
						|
# - Le tableau TEMPLATECTL_VARS contient des variables supplémentaires
 | 
						|
#   spécifiées par l'utilisateur. C'est une liste de valeurs de la forme
 | 
						|
#   'name=value'
 | 
						|
# - TEMPLATE_STATIC_VARS doit contenir une liste de noms de variables qui
 | 
						|
#   peuvent être remplacés dans les fichiers de template.
 | 
						|
# - TEMPLATE_DYNAMIC_VARS contient une liste de noms de variables valides, mais
 | 
						|
#   qui ne doivent pas être remplacés, en effet, ils sont utilisés pour le
 | 
						|
#   déploiement des fichiers.
 | 
						|
# - TEMPLATE_NOWRITE_VARS contient une liste de noms de variables qui ne
 | 
						|
#   devraient pas être écrits dans le fichier des variables, sauf si elles
 | 
						|
#   reçoivent une valeur explicite de la part de l'utilisateur. Ce tableau est
 | 
						|
#   mis à jour lors de l'analyse du tableau TEMPLATECTL_VARS
 | 
						|
# - TEMPLATE_USER_VARS contient une liste de noms de tableaux qui sont définis
 | 
						|
#   en plus et qui peuvent être utilisés par des scripts annexes
 | 
						|
    local -a __template_vars __dynamic_vars
 | 
						|
    local __t_var __t_name __t_value
 | 
						|
 | 
						|
    array_copy __template_vars TEMPLATECTL_DEFAULTS
 | 
						|
    configdir="$(dirname -- "$1")"
 | 
						|
    [ -f "$1" ] && source "$1"
 | 
						|
 | 
						|
    for __t_var in "${__template_vars[@]}"; do
 | 
						|
        splitvar "$__t_var" __t_name __t_value
 | 
						|
        __template_set_var "$__t_name" "$__t_value"
 | 
						|
    done
 | 
						|
    array_contains TEMPLATE_STATIC_VARS configdir && __template_set_var configdir "$configdir"
 | 
						|
    for __t_var in "${__dynamic_vars[@]}"; do
 | 
						|
        splitvar "$__t_var" __t_name __t_value
 | 
						|
        array_del TEMPLATE_STATIC_VARS "$__t_name"
 | 
						|
        array_addu TEMPLATE_DYNAMIC_VARS "$__t_name"
 | 
						|
        __template_set_var "$__t_name" "$__t_value"
 | 
						|
    done
 | 
						|
    array_contains TEMPLATE_DYNAMIC_VARS configdir && __template_set_var configdir "$configdir"
 | 
						|
 | 
						|
    is_defined TEMPLATE_USER_VARS || TEMPLATE_USER_VARS=()
 | 
						|
    for __t_var in "${TEMPLATE_USER_VARS[@]}"; do
 | 
						|
        is_defined "$__t_var" || array_new "$__t_var"
 | 
						|
    done
 | 
						|
 | 
						|
    local __t_modified=1
 | 
						|
    for __t_var in "${TEMPLATECTL_VARS[@]}"; do
 | 
						|
        splitvar "$__t_var" __t_name __t_value
 | 
						|
        __template_set_var "$__t_name" "$__t_value" writable && __t_modified=0
 | 
						|
    done
 | 
						|
    return $__t_modified
 | 
						|
}
 | 
						|
 | 
						|
function templatectl_writevars() {
 | 
						|
# Ecrire les variables dans le fichier $1
 | 
						|
    local __t_var __t_desc
 | 
						|
    echo "# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8" >"$1"
 | 
						|
    for __t_var in "${TEMPLATE_USER_VARS[@]}"; do
 | 
						|
        __t_desc="__TEMPLATE_DESC_$__t_var"
 | 
						|
        [ -n "${!__t_desc}" ] && echo "# ${!__t_desc}" >>"$1"
 | 
						|
        if is_array "$__t_var"; then
 | 
						|
            set_array_cmd "$__t_var" >>"$1"
 | 
						|
        else
 | 
						|
            echo_setv "$__t_var" "${!__t_var}" >>"$1"
 | 
						|
        fi
 | 
						|
    done
 | 
						|
    if [ ${#TEMPLATE_DYNAMIC_VARS[*]} -gt 0 ]; then
 | 
						|
        echo "__dynamic_vars=(" >>"$1"
 | 
						|
        for __t_var in "${TEMPLATE_DYNAMIC_VARS[@]}"; do
 | 
						|
            array_contains TEMPLATE_NOWRITE_VARS "$__t_var" && continue
 | 
						|
            __t_desc="__TEMPLATE_DESC_$__t_var"
 | 
						|
            [ -n "${!__t_desc}" ] && echo "# ${!__t_desc}" >>"$1"
 | 
						|
            echo_setv "$__t_var" "${!__t_var}" >>"$1"
 | 
						|
        done
 | 
						|
        echo ")" >>"$1"
 | 
						|
    fi
 | 
						|
    echo "__template_vars=(# ne pas modifier" >>"$1"
 | 
						|
    for __t_var in "${TEMPLATE_STATIC_VARS[@]}"; do
 | 
						|
        array_contains TEMPLATE_NOWRITE_VARS "$__t_var" && continue
 | 
						|
        __t_desc="__TEMPLATE_DESC_$__t_var"
 | 
						|
        [ -n "${!__t_desc}" ] && echo "# ${!__t_desc}" >>"$1"
 | 
						|
        echo_setv "$__t_var" "${!__t_var}" >>"$1"
 | 
						|
    done
 | 
						|
    echo ")" >>"$1"
 | 
						|
}
 | 
						|
 | 
						|
function templatectl_list_vars() {
 | 
						|
# Afficher les valeurs des variables
 | 
						|
    local __var
 | 
						|
    echo "# template vars"
 | 
						|
    for __var in "${TEMPLATE_STATIC_VARS[@]}"; do
 | 
						|
        echo_setv "$__var=${!__var}"
 | 
						|
    done
 | 
						|
    if [ ${#TEMPLATE_DYNAMIC_VARS[*]} -gt 0 ]; then
 | 
						|
        echo "# dynamic vars"
 | 
						|
        for __var in "${TEMPLATE_DYNAMIC_VARS[@]}"; do
 | 
						|
            echo_setv "$__var=${!__var}"
 | 
						|
        done
 | 
						|
    fi
 | 
						|
}
 | 
						|
 | 
						|
__TEMPLATECTL_HELP="\
 | 
						|
-d, --destdir DESTDIR
 | 
						|
    Spécifier le répertoire local dans lequel copier les fichiers templates
 | 
						|
-s, --srcdir SRCDIR
 | 
						|
    Ajouter un répertoire à la liste des répertoires sources pour les templates.
 | 
						|
    Si ce n'est pas un chemin, c'est le nom d'un répertoire dans le répertoires
 | 
						|
    des templates par défaut.
 | 
						|
-l, --list
 | 
						|
    Lister les templates disponibles.
 | 
						|
-m, --merge
 | 
						|
    Copier les templates spécifiés dans le répertoire local s'il n'y existent
 | 
						|
    pas déjà. Les templates ayant l'extension '.template' doivent être demandés
 | 
						|
    explicitement. Sinon, ils sont ignorés.
 | 
						|
-z, --unmerge
 | 
						|
    Supprimer les fichiers du répertoire local s'ils n'ont pas été modifiés par
 | 
						|
    rapport aux templates.
 | 
						|
-C, --clean
 | 
						|
    Supprimer les répertoires vides dans le répertoire local. Peut être utile
 | 
						|
    après -z
 | 
						|
-g, --diff
 | 
						|
    Afficher les différences entre les templates et les fichiers du répertoire
 | 
						|
    local.
 | 
						|
-L, --list-vars
 | 
						|
    Afficher pour information les valeurs par défaut des variables de template.
 | 
						|
-v, --var NAME=VALUE
 | 
						|
    Spécifier la valeur d'une variable. Toutes les variables sont autorisées,
 | 
						|
    sauf celles qui figurent dans la liste des variables dynamiques.
 | 
						|
-w, --write-vars
 | 
						|
    Ecrire dans le fichier $TEMPLATECTL_CONFIG les valeurs des variables, ce qui
 | 
						|
    permet après édition du fichier d'éviter de les spécifier à chaque fois avec
 | 
						|
    l'option -v
 | 
						|
    Le fichier n'est pas écrasé s'il existe déjà."
 | 
						|
function __display_templatectl_help() { uecho "$__TEMPLATECTL_HELP"; }
 | 
						|
function templatectl() {
 | 
						|
# Fonction de haut niveau qui facilite l'utilisation des fonctions template_*
 | 
						|
# définir la fonction __display_templatectl_help() pour l'affichage de l'aide
 | 
						|
# - Le tableau TEMPLATECTL_SRCDIRS doit contenir la liste des répertoires
 | 
						|
#   sources pour les templates. Alternativement, il est possible de définir la
 | 
						|
#   variable TEMPLATECTL_SRCDIR s'il n'y a qu'un seul répertoire source pour le
 | 
						|
#   template
 | 
						|
# - TEMPLATECTL_CONFIG est le nom de base du fichier à partir duquel sont
 | 
						|
#   chargées les variables et dans lequel sont écrites les variables avec
 | 
						|
#   l'option --write-vars
 | 
						|
#   Si le nom de base est CONFIG, le fichier s'appelera .CONFIG si l'option
 | 
						|
#   --hide-config est utilisée (par défaut) ou CONFIG.conf si l'option
 | 
						|
#   --no-hide-config est utilisée
 | 
						|
# Les variables de template_loadvars() sont aussi prises en compte
 | 
						|
    local -a __tc_srcdirs; local __tc_srcdir
 | 
						|
    if [ ${#TEMPLATECTL_SRCDIRS[*]} -gt 0 ]; then
 | 
						|
        :
 | 
						|
    elif [ -n "$TEMPLATECTL_SRCDIR" ]; then
 | 
						|
        local -a TEMPLATECTL_SRCDIRS
 | 
						|
        TEMPLATECTL_SRCDIRS=("$TEMPLATECTL_SRCDIR")
 | 
						|
    fi
 | 
						|
    for __tc_srcdir in "${TEMPLATECTL_SRCDIRS[@]}"; do
 | 
						|
        if ! withpath "$__tc_srcdir"; then
 | 
						|
            __tc_srcdir="$(template_srcdir "$__tc_srcdir")"
 | 
						|
        fi
 | 
						|
        array_add __tc_srcdirs "$__tc_srcdir"
 | 
						|
    done
 | 
						|
 | 
						|
    local -a __tc_args
 | 
						|
    local __tc_auto=1 __tc_load_vars=1
 | 
						|
    local __tc_destdir __tc_config __tc_nohideconfig
 | 
						|
    local __tc_list __tc_merge __tc_unmerge __tc_clean __tc_diff __tc_list_vars __tc_write_vars
 | 
						|
    parse_opts "${PRETTYOPTS[@]}" \
 | 
						|
        --help '$exit_with __display_templatectl_help' \
 | 
						|
        -d:,--destdir: __tc_destdir= \
 | 
						|
        -s:,--srcdir: __tc_srcdirs \
 | 
						|
        --config: __tc_config= \
 | 
						|
        --no-hide-config __tc_nohideconfig=1 \
 | 
						|
        --hide-config __tc_nohideconfig= \
 | 
						|
        --load-vars __tc_load_vars=1 \
 | 
						|
        --no-load-vars __tc_load_vars= \
 | 
						|
        --noop __tc_auto= \
 | 
						|
        -l,--list '$__tc_list=1; __tc_auto=' \
 | 
						|
        -m,--merge '$__tc_merge=1; __tc_auto=' \
 | 
						|
        -z,--unmerge '$__tc_unmerge=1; __tc_auto=' \
 | 
						|
        -C,--clean '$__tc_clean=1; __tc_auto=' \
 | 
						|
        -g,--diff '$__tc_diff=1; __tc_auto=' \
 | 
						|
        -L,--list-vars '$__tc_list_vars=1; __tc_auto=' \
 | 
						|
        -v:,--var: TEMPLATECTL_VARS \
 | 
						|
        -w,--write-vars __tc_write_vars=1 \
 | 
						|
        @ __tc_args -- "$@" && set -- "${__tc_args[@]}" || { eerror "$__tc_args"; return 1; }
 | 
						|
 | 
						|
    [ -n "$__tc_destdir" ] || __tc_destdir=.
 | 
						|
    __template_check_destdir "$__tc_destdir" || return 1
 | 
						|
 | 
						|
    array_isempty __tc_srcdirs && return 1
 | 
						|
    for __tc_srcdir in "${__tc_srcdirs[@]}"; do
 | 
						|
        __template_check_srcdir "$__tc_srcdir" || return 1
 | 
						|
    done
 | 
						|
 | 
						|
    [ -n "$__tc_config" ] || __tc_config="$(templatectl_config "$destdir" ${__tc_nohideconfig:+nohideconfig})"
 | 
						|
    if [ -n "$__tc_load_vars" ]; then
 | 
						|
        templatectl_loadvars "$__tc_config"
 | 
						|
    fi
 | 
						|
    if [ -n "$__tc_write_vars" ]; then
 | 
						|
        if [ -f "$__tc_config" ]; then
 | 
						|
            ewarn "Refus d'écraser le fichier existant $(ppath "$__tc_config")"
 | 
						|
        else
 | 
						|
            templatectl_writevars "$__tc_config"
 | 
						|
        fi
 | 
						|
    fi
 | 
						|
 | 
						|
    [ -n "$__tc_auto" ] && __tc_list=1
 | 
						|
    [ -n "$__tc_list_vars" ] && templatectl_list_vars
 | 
						|
    [ -n "$__tc_list" ] && template_list "$__tc_destdir" "${__tc_srcdirs[@]}" -- "$@"
 | 
						|
    [ -n "$__tc_merge" ] && template_merge "$__tc_destdir" "${__tc_srcdirs[@]}" -- "$@"
 | 
						|
    [ -n "$__tc_unmerge" ] && template_unmerge "$__tc_destdir" "${__tc_srcdirs[@]}" -- "$@"
 | 
						|
    [ -n "$__tc_clean" ] && template_cleandest "$__tc_destdir" "$@"
 | 
						|
    [ -n "$__tc_diff" ] && template_diff "$__tc_destdir" "${__tc_srcdirs[@]}" -- "$@"
 | 
						|
}
 |