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() {
|
|
|
|
# afficher le chemin absolu du fichier $1 si on est dans le répertoire de
|
|
|
|
# destination $2, sinon l'exprimer par rapport au répertoire de destination
|
|
|
|
# $2 si c'est un chemin relatif.
|
|
|
|
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}'
|
|
|
|
}
|
|
|
|
|
2014-10-23 22:58:26 +04:00
|
|
|
# liste des variables qu'il faut remplacer dans les fichiers sources
|
|
|
|
TEMPLATE_VARS=()
|
2014-10-24 00:34:53 +04:00
|
|
|
function __template_setup_tmpfile() {
|
|
|
|
if [ ${#TEMPLATE_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_VARS[*]} -gt 0 ]; then
|
|
|
|
ac_clean "$tmpfile"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
function __template_fillvars() {
|
|
|
|
# Pour chacune des variables VAR de TEMPLATE_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_VARS[*]} -eq 0 ] && { echo "$1"; return; }
|
|
|
|
|
|
|
|
# chercher si le fichier contient au moins un des tags de TEMPLATE_VARS
|
|
|
|
local __var __tag __found
|
|
|
|
for __var in "${TEMPLATE_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
|
|
|
|
for __var in "${TEMPLATE_VARS[@]}"; do
|
|
|
|
[ -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() {
|
|
|
|
# Lister les fichiers du répertoire source $1 qui seraient fusionnées avec
|
|
|
|
# template_merge() ou supprimés avec template_unmerge() du répertoire
|
|
|
|
# destination $2. Si des chemins sont spécifiés avec les arguments $3..@, ne
|
|
|
|
# traiter que les fichiers qui correspondent à ces spécifications
|
|
|
|
local srcdir="$1"; shift
|
|
|
|
__template_check_srcdir "$srcdir" || return 1
|
|
|
|
setx srcdir=abspath "$srcdir"
|
|
|
|
|
|
|
|
local destdir="${1:-.}"; shift
|
|
|
|
__template_check_destdir "$destdir" || return 1
|
|
|
|
setx destdir=abspath "$destdir"
|
|
|
|
|
|
|
|
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}"
|
|
|
|
|
|
|
|
[ -e "$srcdir$srcspec" ] || continue
|
|
|
|
array_from_lines srcfiles "$(find "$srcdir$srcspec" -type f)"
|
|
|
|
for src in "${srcfiles[@]}"; do
|
2014-10-24 00:34:53 +04:00
|
|
|
setx content=__template_fillvars "$src" "$tmpfile"
|
2014-10-22 23:36:24 +04:00
|
|
|
dest="$destdir/${src#$srcdir/}"
|
|
|
|
|
|
|
|
list=
|
|
|
|
if [ -L "$dest" ]; then
|
|
|
|
:
|
|
|
|
elif [ -f "$dest" ]; then
|
2014-10-24 00:34:53 +04:00
|
|
|
testsame "$content" "$dest" && list=1
|
2014-10-22 23:36:24 +04:00
|
|
|
else
|
|
|
|
list=1
|
|
|
|
fi
|
|
|
|
[ -n "$list" ] || continue
|
|
|
|
|
|
|
|
if [ -n "$rel2pwd" ]; then
|
|
|
|
relpath "$dest"
|
|
|
|
else
|
|
|
|
echo "${src#$srcdir/}"
|
|
|
|
fi
|
|
|
|
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() {
|
|
|
|
# Copier dans le répertoire destination $2 tous les fichiers provenant du
|
|
|
|
# répertoire source $1 correspondant aux spécifications $3..@, 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
|
|
|
|
# s'ils sonts demandés explicitement.
|
2014-10-22 23:36:24 +04:00
|
|
|
local srcdir="$1"; shift
|
|
|
|
__template_check_srcdir "$srcdir" || return 1
|
|
|
|
setx srcdir=abspath "$srcdir"
|
|
|
|
|
|
|
|
local destdir="${1:-.}"; shift
|
|
|
|
__template_check_destdir "$destdir" || return 1
|
|
|
|
setx destdir=abspath "$destdir"
|
|
|
|
|
|
|
|
[ $# -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}"
|
|
|
|
|
|
|
|
[ -e "$srcdir$srcspec" ] || continue
|
2014-10-23 15:47:21 +04:00
|
|
|
ebegin "$(ppath "$destdir$srcspec")"
|
2014-10-22 23:36:24 +04:00
|
|
|
s=0
|
2014-10-24 01:24:56 +04:00
|
|
|
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
|
2014-10-22 23:36:24 +04:00
|
|
|
for src in "${srcfiles[@]}"; do
|
2014-10-24 00:34:53 +04:00
|
|
|
setx content=__template_fillvars "$src" "$tmpfile"
|
2014-10-22 23:36:24 +04:00
|
|
|
dest="$destdir/${src#$srcdir/}"
|
2014-10-24 01:24:56 +04:00
|
|
|
[ -n "$template" ] && dest="${dest%.template}"
|
2014-10-22 23:36:24 +04:00
|
|
|
|
|
|
|
if [ -L "$dest" ]; then
|
|
|
|
edotw 0 "LOCALLY MODIFIED: $(ppath "$dest")"
|
|
|
|
elif [ -f "$dest" ]; then
|
2014-10-24 00:34:53 +04:00
|
|
|
if testsame "$content" "$dest"; then
|
2014-10-22 23:36:24 +04:00
|
|
|
show_debug && edot 0 "ALREADY COPIED: $(ppath "$dest")"
|
|
|
|
else
|
|
|
|
edotw 0 "LOCALLY MODIFIED: $(ppath "$dest")"
|
|
|
|
fi
|
|
|
|
else
|
|
|
|
mkdirof "$dest"
|
2014-10-24 00:34:53 +04:00
|
|
|
cp "$content" "$dest"; r=$?
|
2014-10-22 23:36:24 +04:00
|
|
|
edot $r "COPY: $(ppath "$dest")"
|
|
|
|
[ $r -eq 0 ] || s=$r
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
eend $s
|
|
|
|
done
|
2014-10-24 00:34:53 +04:00
|
|
|
|
|
|
|
__template_clean_tmpfile
|
2014-10-22 23:36:24 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
function template_unmerge() {
|
|
|
|
# Supprimer du répertoire de destination $2 tous les fichiers provenant du
|
|
|
|
# répertoire source $1 et qui n'ont pas été modifiés. Si des chemins sont
|
|
|
|
# spécifiés avec les arguments $3..@, ne traiter que les fichiers qui
|
|
|
|
# correspondent à ces spécifications.
|
|
|
|
local srcdir="$1"; shift
|
|
|
|
__template_check_srcdir "$srcdir" || return 1
|
|
|
|
setx srcdir=abspath "$srcdir"
|
|
|
|
|
|
|
|
local destdir="${1:-.}"; shift
|
|
|
|
__template_check_destdir "$destdir" || return 1
|
|
|
|
setx destdir=abspath "$destdir"
|
|
|
|
|
|
|
|
[ $# -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}"
|
|
|
|
|
|
|
|
[ -e "$srcdir$srcspec" ] || continue
|
|
|
|
s=0
|
2014-10-23 15:47:21 +04:00
|
|
|
ebegin "$(ppath "$destdir$srcspec")"
|
2014-10-22 23:36:24 +04:00
|
|
|
array_from_lines files "$(find "$srcdir$srcspec" -type f)"
|
|
|
|
for src in "${files[@]}"; do
|
2014-10-24 00:34:53 +04:00
|
|
|
setx content=__template_fillvars "$src" "$tmpfile"
|
2014-10-22 23:36:24 +04:00
|
|
|
dest="$destdir/${src#$srcdir/}"
|
|
|
|
|
|
|
|
if [ -L "$dest" ]; then
|
|
|
|
edotw 0 "LOCALLY MODIFIED: $(ppath "$dest")"
|
|
|
|
elif [ -f "$dest" ]; then
|
2014-10-24 00:34:53 +04:00
|
|
|
if testsame "$content" "$dest"; then
|
2014-10-22 23:36:24 +04:00
|
|
|
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
|
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()
|
|
|
|
local -a dirs
|
|
|
|
[ -d "$1" ] || return 1
|
2014-10-23 15:47:21 +04:00
|
|
|
array_from_lines dirs "$(cd "$1"; find . -type d | __template_plsort -r)"
|
|
|
|
array_del dirs .
|
|
|
|
(cd "$1"; rmdir "${dirs[@]}" 2>/dev/null)
|
2014-10-22 23:36:24 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
function template_diff() {
|
|
|
|
# Afficher les différences entre les fichiers du répertoire de destination $2 et
|
|
|
|
# les fichiers du répertoire source $1
|
|
|
|
local srcdir="$1"; shift
|
|
|
|
__template_check_srcdir "$srcdir" || return 1
|
|
|
|
setx srcdir=abspath "$srcdir"
|
|
|
|
|
|
|
|
local destdir="${1:-.}"; shift
|
|
|
|
__template_check_destdir "$destdir" || return 1
|
|
|
|
setx destdir=abspath "$destdir"
|
|
|
|
|
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
|
|
|
|
array_from_lines srcfiles "$(find "$srcdir" -type f)"
|
|
|
|
for src in "${srcfiles[@]}"; do
|
2014-10-24 00:34:53 +04:00
|
|
|
setx content=__template_fillvars "$src" "$tmpfile"
|
2014-10-22 23:36:24 +04:00
|
|
|
dest="$destdir/${src#$srcdir/}"
|
2014-10-24 00:34:53 +04:00
|
|
|
if [ -f "$dest" ] && testdiff "$content" "$dest"; then
|
|
|
|
diff -uwB "$content" "$dest"
|
2014-10-22 23:36:24 +04:00
|
|
|
fi
|
|
|
|
done | page_maybe -S
|
2014-10-24 00:34:53 +04:00
|
|
|
|
|
|
|
__template_clean_tmpfile
|
2014-10-22 23:36:24 +04:00
|
|
|
}
|
|
|
|
|
2014-10-23 21:26:42 +04:00
|
|
|
function templatesrc() {
|
2014-10-23 22:41:20 +04:00
|
|
|
# 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
|
|
|
|
}
|
|
|
|
|
2014-10-23 15:47:21 +04:00
|
|
|
function __templatectl_display_help() { :; }
|
2014-10-23 22:56:22 +04:00
|
|
|
__TEMPLATECTL_SUPPLOPTS=()
|
2014-10-23 15:47:21 +04:00
|
|
|
function __templatectl_parseopts() {
|
2014-10-22 23:36:24 +04:00
|
|
|
parse_opts "${PRETTYOPTS[@]}" \
|
2014-10-23 15:47:21 +04:00
|
|
|
--help '$exit_with __templatectl_display_help' \
|
2014-10-24 00:34:53 +04:00
|
|
|
-s:,--srcdir: __templatectl_srcdir= \
|
|
|
|
-d:,--destdir: __templatectl_destdir= \
|
2014-10-24 01:04:02 +04:00
|
|
|
-l,--list '$__templatectl_list=1; __templatectl_opt=1' \
|
|
|
|
-m,--merge '$__templatectl_merge=1; __templatectl_opt=1' \
|
|
|
|
-z,--unmerge '$__templatectl_unmerge=1; __templatectl_opt=1' \
|
|
|
|
-C,--clean '$__templatectl_clean=1; __templatectl_opt=1' \
|
|
|
|
-g,--diff '$__templatectl_diff=1; __templatectl_opt=1' \
|
2014-10-23 22:56:22 +04:00
|
|
|
"${__TEMPLATECTL_SUPPLOPTS[@]}" \
|
2014-10-23 15:47:21 +04:00
|
|
|
@ args -- "$@"
|
|
|
|
}
|
2014-10-23 22:58:26 +04:00
|
|
|
|
2014-10-23 15:47:21 +04:00
|
|
|
function __templatectl_do() {
|
2014-10-24 00:34:53 +04:00
|
|
|
__template_check_srcdir "$__templatectl_srcdir" || return 1
|
|
|
|
[ -n "$__templatectl_destdir" ] || __templatectl_destdir=.
|
|
|
|
__template_check_destdir "$__templatectl_destdir" || return 1
|
2014-10-24 01:04:02 +04:00
|
|
|
[ -n "$__templatectl_auto" ] && __templatectl_list=1
|
2014-10-24 00:34:53 +04:00
|
|
|
|
|
|
|
[ -n "$__templatectl_list" ] && template_list "$__templatectl_srcdir" "$__templatectl_destdir" "$@"
|
|
|
|
[ -n "$__templatectl_merge" ] && template_merge "$__templatectl_srcdir" "$__templatectl_destdir" "$@"
|
|
|
|
[ -n "$__templatectl_unmerge" ] && template_unmerge "$__templatectl_srcdir" "$__templatectl_destdir" "$@"
|
|
|
|
[ -n "$__templatectl_clean" ] && template_cleandest "$__templatectl_destdir" "$@"
|
|
|
|
[ -n "$__templatectl_diff" ] && template_diff "$__templatectl_srcdir" "$__templatectl_destdir" "$@"
|
2014-10-22 23:36:24 +04:00
|
|
|
return 0
|
|
|
|
}
|
2014-10-23 22:58:26 +04:00
|
|
|
|
2014-10-23 15:47:21 +04:00
|
|
|
function templatectl() {
|
|
|
|
# fonction de haut niveau qui facilite l'utilisation des fonctions template_*
|
|
|
|
# définir la fonction override_display_templatectl_help() pour l'affichage de l'aide
|
|
|
|
local -a args
|
2014-10-24 01:04:02 +04:00
|
|
|
local __templatectl_list __templatectl_merge __templatectl_unmerge __templatectl_clean __templatectl_diff __templatectl_opt __templatectl_auto
|
2014-10-24 00:34:53 +04:00
|
|
|
local __templatectl_destdir
|
2014-10-23 15:47:21 +04:00
|
|
|
|
|
|
|
__templatectl_parseopts "$@" && set -- "${args[@]}" || { eerror "$args"; return 1; }
|
2014-10-24 01:04:02 +04:00
|
|
|
[ -z "$__templatectl_opt" ] && __templatectl_auto=1
|
2014-10-23 15:47:21 +04:00
|
|
|
__templatectl_do "$@"
|
|
|
|
}
|