2014-10-22 23:36:24 +04:00
|
|
|
##@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
|
2014-10-22 23:39:43 +04:00
|
|
|
##@require base
|
2014-10-22 23:36:24 +04:00
|
|
|
uprovide template
|
|
|
|
urequire base
|
|
|
|
|
|
|
|
function __template_prel_abspath() {
|
2015-11-02 14:29:50 +04:00
|
|
|
# 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.
|
2014-10-22 23:36:24 +04:00
|
|
|
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}'
|
|
|
|
}
|
2015-10-29 12:43:19 +04:00
|
|
|
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" ]
|
|
|
|
}
|
2014-10-22 23:36:24 +04:00
|
|
|
|
2014-10-23 22:58:26 +04:00
|
|
|
# liste des variables qu'il faut remplacer dans les fichiers sources
|
2015-10-29 12:43:19 +04:00
|
|
|
TEMPLATE_STATIC_VARS=()
|
2014-10-24 00:34:53 +04:00
|
|
|
function __template_setup_tmpfile() {
|
2015-10-29 12:43:19 +04:00
|
|
|
if [ ${#TEMPLATE_STATIC_VARS[*]} -gt 0 ]; then
|
2014-10-24 00:34:53 +04:00
|
|
|
# S'il y a des variables à remplacer, préparer un fichier temporaire
|
|
|
|
ac_set_tmpfile tmpfile
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
function __template_clean_tmpfile() {
|
2015-10-29 12:43:19 +04:00
|
|
|
if [ ${#TEMPLATE_STATIC_VARS[*]} -gt 0 ]; then
|
2014-10-24 00:34:53 +04:00
|
|
|
ac_clean "$tmpfile"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
function __template_fillvars() {
|
2015-10-29 12:43:19 +04:00
|
|
|
# Pour chacune des variables VAR de TEMPLATE_STATIC_VARS, remplacer dans le
|
|
|
|
# fichier $1 les occurences de @@VAR@@ par la valeur $VAR
|
2014-10-24 00:34:53 +04:00
|
|
|
# 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.
|
2015-10-29 12:43:19 +04:00
|
|
|
[ ${#TEMPLATE_STATIC_VARS[*]} -eq 0 ] && { echo "$1"; return; }
|
2014-10-24 00:34:53 +04:00
|
|
|
|
2015-10-29 12:43:19 +04:00
|
|
|
# chercher si le fichier contient au moins un des tags de
|
|
|
|
# TEMPLATE_STATIC_VARS
|
2014-10-24 00:34:53 +04:00
|
|
|
local __var __tag __found
|
2015-10-29 12:43:19 +04:00
|
|
|
for __var in "${TEMPLATE_STATIC_VARS[@]}"; do
|
2014-10-24 00:34:53 +04:00
|
|
|
__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
|
2015-10-30 21:46:49 +04:00
|
|
|
local __script __first=1 __repl
|
2015-10-29 12:43:19 +04:00
|
|
|
for __var in "${TEMPLATE_STATIC_VARS[@]}"; do
|
2014-10-24 00:34:53 +04:00
|
|
|
[ -n "$__first" ] || __script="$__script"$'\n'
|
|
|
|
__first=
|
|
|
|
__script="${__script}s/@@${__var}@@/$(qseds "${!__var}")/g"
|
|
|
|
done
|
|
|
|
|
|
|
|
sed "$__script" <"$1" >"$2"
|
|
|
|
echo "$2"
|
|
|
|
}
|
2014-10-23 22:58:26 +04:00
|
|
|
|
2014-10-22 23:36:24 +04:00
|
|
|
function template_list() {
|
2015-10-29 12:43:19 +04:00
|
|
|
# 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...
|
2014-10-22 23:36:24 +04:00
|
|
|
local destdir="${1:-.}"; shift
|
|
|
|
__template_check_destdir "$destdir" || return 1
|
|
|
|
setx destdir=abspath "$destdir"
|
|
|
|
|
2015-10-29 12:43:19 +04:00
|
|
|
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
|
|
|
|
|
2014-10-22 23:36:24 +04:00
|
|
|
local rel2pwd
|
|
|
|
withinpath "$destdir" "$(pwd)" && rel2pwd=1
|
|
|
|
|
|
|
|
if [ $# -eq 0 ]; then
|
|
|
|
[ -n "$rel2pwd" ] && set -- . || set -- "$destdir"
|
|
|
|
fi
|
|
|
|
|
2014-10-24 00:34:53 +04:00
|
|
|
local tmpfile; __template_setup_tmpfile
|
|
|
|
|
|
|
|
local spec srcspec src content dest list
|
2014-10-22 23:36:24 +04:00
|
|
|
local -a srcfiles
|
|
|
|
for spec in "$@"; do
|
|
|
|
setx srcspec=__template_prel_abspath "$spec" "$destdir"
|
|
|
|
withinpath "$destdir" "$srcspec" || continue
|
|
|
|
srcspec="${srcspec#$destdir}"
|
|
|
|
|
2015-10-29 12:43:19 +04:00
|
|
|
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
|
2014-10-22 23:36:24 +04:00
|
|
|
|
2015-10-29 12:43:19 +04:00
|
|
|
if [ -n "$rel2pwd" ]; then
|
|
|
|
relpath "$dest"
|
|
|
|
else
|
|
|
|
echo "${src#$srcdir/}"
|
|
|
|
fi
|
|
|
|
done
|
2014-10-22 23:36:24 +04:00
|
|
|
done
|
|
|
|
done | csort -u
|
2014-10-24 00:34:53 +04:00
|
|
|
|
|
|
|
__template_clean_tmpfile
|
2014-10-22 23:36:24 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
function template_merge() {
|
2015-10-29 12:43:19 +04:00
|
|
|
# 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.
|
2014-10-24 01:24:56 +04:00
|
|
|
# Les fichiers sources ayant l'extension .template sont ignorés par défaut, sauf
|
2015-10-29 12:43:19 +04:00
|
|
|
# s'ils sonts demandés explicitement. Exemple:
|
|
|
|
# template_merge destdir srcdirs... -- specs...
|
2014-10-22 23:36:24 +04:00
|
|
|
local destdir="${1:-.}"; shift
|
|
|
|
__template_check_destdir "$destdir" || return 1
|
|
|
|
setx destdir=abspath "$destdir"
|
|
|
|
|
2015-10-29 12:43:19 +04:00
|
|
|
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
|
|
|
|
|
2014-10-22 23:36:24 +04:00
|
|
|
[ $# -gt 0 ] || set -- "$destdir"
|
|
|
|
|
2014-10-24 00:34:53 +04:00
|
|
|
local tmpfile; __template_setup_tmpfile
|
|
|
|
|
2014-10-24 01:24:56 +04:00
|
|
|
local spec template srcspec src content dest
|
2014-10-22 23:36:24 +04:00
|
|
|
local srcfiles
|
|
|
|
for spec in "$@"; do
|
2014-10-24 01:24:56 +04:00
|
|
|
setb template=[ "${spec%.template}" != "$spec" ]
|
2014-10-22 23:36:24 +04:00
|
|
|
setx srcspec=__template_prel_abspath "$spec"
|
|
|
|
if ! withinpath "$destdir" "$srcspec"; then
|
|
|
|
ewarn "$spec: fichier ignoré"
|
|
|
|
continue
|
|
|
|
fi
|
|
|
|
srcspec="${srcspec#$destdir}"
|
|
|
|
|
2015-10-29 12:43:19 +04:00
|
|
|
for srcdir in "${srcdirs[@]}"; do
|
2015-11-02 14:29:50 +04:00
|
|
|
if [ -z "$template" -a ! -e "$srcdir$srcspec" -a -e "$srcdir$srcspec.template" ]; then
|
|
|
|
srcspec="$srcspec.template"
|
|
|
|
template=1
|
|
|
|
fi
|
2015-10-29 12:43:19 +04:00
|
|
|
[ -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}"
|
2014-10-22 23:36:24 +04:00
|
|
|
|
2015-10-29 12:43:19 +04:00
|
|
|
if [ -L "$dest" ]; then
|
2014-10-22 23:36:24 +04:00
|
|
|
edotw 0 "LOCALLY MODIFIED: $(ppath "$dest")"
|
2015-10-29 12:43:19 +04:00
|
|
|
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
|
2014-10-22 23:36:24 +04:00
|
|
|
fi
|
2015-10-29 12:43:19 +04:00
|
|
|
done
|
|
|
|
eend $s
|
2014-10-22 23:36:24 +04:00
|
|
|
done
|
|
|
|
done
|
2014-10-24 00:34:53 +04:00
|
|
|
|
|
|
|
__template_clean_tmpfile
|
2014-10-22 23:36:24 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
function template_unmerge() {
|
2015-10-29 12:43:19 +04:00
|
|
|
# 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...
|
2014-10-22 23:36:24 +04:00
|
|
|
local destdir="${1:-.}"; shift
|
|
|
|
__template_check_destdir "$destdir" || return 1
|
|
|
|
setx destdir=abspath "$destdir"
|
|
|
|
|
2015-10-29 12:43:19 +04:00
|
|
|
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
|
|
|
|
|
2014-10-22 23:36:24 +04:00
|
|
|
[ $# -gt 0 ] || set -- "$destdir"
|
|
|
|
|
2014-10-24 00:34:53 +04:00
|
|
|
local tmpfile; __template_setup_tmpfile
|
|
|
|
|
|
|
|
local spec srcspec src content dest
|
2014-10-22 23:36:24 +04:00
|
|
|
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}"
|
|
|
|
|
2015-10-29 12:43:19 +04:00
|
|
|
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/}"
|
2014-10-22 23:36:24 +04:00
|
|
|
|
2015-10-29 12:43:19 +04:00
|
|
|
if [ -L "$dest" ]; then
|
2014-10-22 23:36:24 +04:00
|
|
|
edotw 0 "LOCALLY MODIFIED: $(ppath "$dest")"
|
2015-10-29 12:43:19 +04:00
|
|
|
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")"
|
2014-10-22 23:36:24 +04:00
|
|
|
fi
|
2015-10-29 12:43:19 +04:00
|
|
|
done
|
|
|
|
eend $s
|
2014-10-22 23:36:24 +04:00
|
|
|
done
|
|
|
|
done
|
2014-10-24 00:34:53 +04:00
|
|
|
|
|
|
|
__template_clean_tmpfile
|
2014-10-22 23:36:24 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
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()
|
2015-10-30 21:46:49 +04:00
|
|
|
# Ignorer les chemins qui contiennent .git/ et .svn/
|
2014-10-22 23:36:24 +04:00
|
|
|
local -a dirs
|
|
|
|
[ -d "$1" ] || return 1
|
2015-10-30 21:46:49 +04:00
|
|
|
array_from_lines dirs "$(cd "$1"; find . -type d | grep -v .git/ | grep -v .svn/ | __template_plsort -r)"
|
2014-10-23 15:47:21 +04:00
|
|
|
array_del dirs .
|
|
|
|
(cd "$1"; rmdir "${dirs[@]}" 2>/dev/null)
|
2014-10-22 23:36:24 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
function template_diff() {
|
2015-10-29 12:43:19 +04:00
|
|
|
# Afficher les différences entre les fichiers du répertoire de destination $1 et
|
|
|
|
# les fichiers des répertoires sources $2..@
|
2014-10-22 23:36:24 +04:00
|
|
|
local destdir="${1:-.}"; shift
|
|
|
|
__template_check_destdir "$destdir" || return 1
|
|
|
|
setx destdir=abspath "$destdir"
|
|
|
|
|
2015-10-29 12:43:19 +04:00
|
|
|
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
|
|
|
|
|
2014-10-24 00:34:53 +04:00
|
|
|
local tmpfile; __template_setup_tmpfile
|
|
|
|
|
|
|
|
local src content dest
|
2014-10-22 23:36:24 +04:00
|
|
|
local -a srcfiles
|
2015-10-29 12:43:19 +04:00
|
|
|
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
|
2014-10-22 23:36:24 +04:00
|
|
|
done | page_maybe -S
|
2014-10-24 00:34:53 +04:00
|
|
|
|
|
|
|
__template_clean_tmpfile
|
2014-10-22 23:36:24 +04:00
|
|
|
}
|
|
|
|
|
2015-10-29 12:43:19 +04:00
|
|
|
function template_srcdir() {
|
|
|
|
# Obtenir le chemin vers le répertoire source de templates $1, situé dans
|
|
|
|
# ULIBDIR/templates
|
2014-10-23 21:26:42 +04:00
|
|
|
urequire ulib
|
|
|
|
if [ -n "$ULIBDIR" ]; then
|
|
|
|
echo "$ULIBDIR/templates/$1"
|
|
|
|
else
|
|
|
|
abspath "templates/$1"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2016-12-30 18:21:25 +04:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2015-10-29 12:43:19 +04:00
|
|
|
function templatectl_config() {
|
2016-12-30 18:21:25 +04:00
|
|
|
# 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
|
2015-10-30 21:46:49 +04:00
|
|
|
local config="$(basename -- "$TEMPLATECTL_CONFIG")"
|
2016-12-30 18:21:25 +04:00
|
|
|
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"
|
2015-10-30 21:46:49 +04:00
|
|
|
fi
|
2014-10-23 15:47:21 +04:00
|
|
|
}
|
2014-10-23 22:58:26 +04:00
|
|
|
|
2015-10-29 12:43:19 +04:00
|
|
|
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
|
2016-12-30 18:21:25 +04:00
|
|
|
# - 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
|
2015-10-29 12:43:19 +04:00
|
|
|
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"
|
|
|
|
|
2016-12-30 18:21:25 +04:00
|
|
|
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
|
|
|
|
|
2015-10-29 12:43:19 +04:00
|
|
|
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
|
2014-10-22 23:36:24 +04:00
|
|
|
}
|
2014-10-23 22:58:26 +04:00
|
|
|
|
2015-10-29 12:43:19 +04:00
|
|
|
function templatectl_writevars() {
|
|
|
|
# Ecrire les variables dans le fichier $1
|
2016-12-30 18:21:25 +04:00
|
|
|
local __t_var __t_desc
|
2015-10-29 12:43:19 +04:00
|
|
|
echo "# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8" >"$1"
|
2016-12-30 18:21:25 +04:00
|
|
|
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
|
2015-10-30 21:46:49 +04:00
|
|
|
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
|
2016-12-30 18:21:25 +04:00
|
|
|
__t_desc="__TEMPLATE_DESC_$__t_var"
|
|
|
|
[ -n "${!__t_desc}" ] && echo "# ${!__t_desc}" >>"$1"
|
|
|
|
echo_setv "$__t_var" "${!__t_var}" >>"$1"
|
2015-10-30 21:46:49 +04:00
|
|
|
done
|
|
|
|
echo ")" >>"$1"
|
|
|
|
fi
|
|
|
|
echo "__template_vars=(# ne pas modifier" >>"$1"
|
2015-10-29 12:43:19 +04:00
|
|
|
for __t_var in "${TEMPLATE_STATIC_VARS[@]}"; do
|
|
|
|
array_contains TEMPLATE_NOWRITE_VARS "$__t_var" && continue
|
2016-12-30 18:21:25 +04:00
|
|
|
__t_desc="__TEMPLATE_DESC_$__t_var"
|
|
|
|
[ -n "${!__t_desc}" ] && echo "# ${!__t_desc}" >>"$1"
|
|
|
|
echo_setv "$__t_var" "${!__t_var}" >>"$1"
|
2015-10-29 12:43:19 +04:00
|
|
|
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"; }
|
2014-10-23 15:47:21 +04:00
|
|
|
function templatectl() {
|
2015-10-29 12:43:19 +04:00
|
|
|
# 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
|
2015-10-30 21:46:49 +04:00
|
|
|
# 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
|
2015-10-29 12:43:19 +04:00
|
|
|
# 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
|
2015-10-30 21:46:49 +04:00
|
|
|
local __tc_destdir __tc_config __tc_nohideconfig
|
|
|
|
local __tc_list __tc_merge __tc_unmerge __tc_clean __tc_diff __tc_list_vars __tc_write_vars
|
2015-10-29 12:43:19 +04:00
|
|
|
parse_opts "${PRETTYOPTS[@]}" \
|
|
|
|
--help '$exit_with __display_templatectl_help' \
|
|
|
|
-d:,--destdir: __tc_destdir= \
|
|
|
|
-s:,--srcdir: __tc_srcdirs \
|
2015-10-30 21:46:49 +04:00
|
|
|
--config: __tc_config= \
|
|
|
|
--no-hide-config __tc_nohideconfig=1 \
|
|
|
|
--hide-config __tc_nohideconfig= \
|
2015-10-29 12:43:19 +04:00
|
|
|
--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
|
|
|
|
|
2015-10-30 21:46:49 +04:00
|
|
|
[ -n "$__tc_config" ] || __tc_config="$(templatectl_config "$destdir" ${__tc_nohideconfig:+nohideconfig})"
|
2015-10-29 12:43:19 +04:00
|
|
|
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[@]}" -- "$@"
|
2014-10-23 15:47:21 +04:00
|
|
|
}
|