ajout de template.sh

This commit is contained in:
Jephté Clain 2024-03-11 22:09:59 +04:00
parent 7cbddf02a3
commit f659f293cb
9 changed files with 319 additions and 0 deletions

4
bash/src/TEMPLATE Normal file
View File

@ -0,0 +1,4 @@
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
##@cooked nocomments
module: TEMPLATE "DESCRIPTION"

180
bash/src/template.sh Normal file
View File

@ -0,0 +1,180 @@
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
##@cooked nocomments
module: template "Mise à jour de templates à partir de modèles"
function: template_copy_replace "\
Copier \$1 vers \$2 de façon inconditionnelle
Si \$2 n'est pas spécifié, on assume que \$1 est de la forme '.file.ext'
et \$2 vaudra alors 'file'
Ajouter file au tableau userfiles"
function template_copy_replace() {
local src="$1" dest="$2"
if [ -z "$dest" ]; then
local srcdir srcname
setx srcname=basename "$src"
dest="${srcname#.}"
dest="${dest%.*}"
setx srcdir=dirname "$src"
dest="$srcdir/$dest"
fi
userfiles+=("$dest")
cp -P "$src" "$dest"
return 0
}
function: template_copy_missing "\
Copier \$1 vers \$2 si ce fichier n'existe pas déjà
Si \$2 n'est pas spécifié, on assume que \$1 est de la forme '.file.ext'
et \$2 vaudra alors 'file'
Ajouter file au tableau userfiles"
function template_copy_missing() {
local src="$1" dest="$2"
if [ -z "$dest" ]; then
local srcdir srcname
setx srcname=basename "$src"
dest="${srcname#.}"
dest="${dest%.*}"
setx srcdir=dirname "$src"
dest="$srcdir/$dest"
fi
userfiles+=("$dest")
if [ ! -e "$dest" ]; then
cp -P "$src" "$dest"
return 0
fi
return 1
}
function: template_dump_vars "\
Lister les variables mentionnées dans les fichiers \$@
Seules sont prises en compte les variables dont le nom est de la forme [A-Z][A-Za-z_]*"
function template_dump_vars() {
cat "$@" |
grep -E '^[A-Z][A-Za-z_]*=' |
sed 's/=.*//' |
sort -u
}
function: template__source_envs "\
Cette fonction doit être implémentée par l'utilisateur et doit:
- initialiser le tableau template_vars qui donne la liste des variables scalaires
- initialiser te tableau template_lists qui donne la liste des variables listes
- charger ces variables depuis les fichiers \$@"
function template__source_envs() {
local e_
for e_ in "$@"; do
[ -f "$e_" ] && source "$e_"
done
setx -a template_vars=template_dump_vars "$@"
template_lists=()
}
function: template_resolve_scripts "\
Générer le script awk \$1 et le script sed \$2 qui remplacent dans les fichiers
destination les marqueurs @@VAR@@ par la valeur de la variable \$VAR
correspondante
Les fichiers \$3..@ contiennent les valeurs des variables
Les marqueurs supportés sont les suivants et sont évalués dans cet ordre:
- XXXRANDOMXXX remplacer cette valeur par une chaine de 16 caractères au hasard
- @@FOR:VARS@@ VARS étant une liste de valeurs séparées par des espaces:
dupliquer la ligne autant de fois qu'il y a de valeurs dans \$VARS
dans chaque ligne, remplacer les occurrences de @@VAR@@ par la valeur
de l'itération courante
- #@@IF:VAR@@ afficher la ligne si VAR est non vide, supprimer la ligne sinon
- #@@UL:VAR@@ afficher la ligne si VAR est vide, supprimer la ligne sinon
- #@@if:VAR@@
- #@@ul:VAR@@ variantes qui ne suppriment pas la ligne mais sont remplacées par #
"
function template_generate_scripts() {
local awkscript="$1"; shift
local sedscript="$1"; shift
(
template__source_envs "$@"
NL=$'\n'
# random, for
exec >"$awkscript"
echo '@include "base.tools.awk"'
echo 'BEGIN {'
for list in "${template_lists[@]}"; do
items="${!list}"; read -a items <<<"${items//
/ }"
let i=0
echo " $list[0] = 0; delete $list"
for item in "${items[@]}"; do
item="${item//\\/\\\\}"
item="${item//\"/\\\"}"
echo " $list[$i] = \"$item\""
let i=i+1
done
done
echo '}'
echo '{ if (should_generate_password()) { generate_password() } }'
for list in "${template_lists[@]}"; do
items="${!list}"; read -a items <<<"${items//
/ }"
echo "/@@FOR:$list@@/ {"
if [ ${#items[*]} -gt 0 ]; then
if [ "${list%S}" != "$list" ]; then item="${list%S}"
elif [ "${list%s}" != "$list" ]; then item="${list%s}"
else item="$list"
fi
echo " sub(/@@FOR:$list@@/, \"\")"
echo " for (i in $list) {"
echo " print gensub(/@@$item@@/, $list[i], \"g\")"
echo " }"
fi
echo " next"
echo "}"
done
echo '{ print }'
# if, ul, var
exec >"$sedscript"
for var in "${template_vars[@]}"; do
value="${!var}"
value="${value//\//\\\/}"
value="${value//[/\\[}"
value="${value//\*/\\\*}"
value="${value//$NL/\\n}"
if [ -n "$value" ]; then
echo "s/#@@IF:${var}@@//g"
echo "s/#@@if:${var}@@//g"
echo "/#@@UL:${var}@@/d"
echo "s/#@@ul:${var}@@/#/g"
else
echo "/#@@IF:${var}@@/d"
echo "s/#@@if:${var}@@/#/g"
echo "s/#@@UL:${var}@@//g"
echo "s/#@@ul:${var}@@//g"
fi
echo "s/@@${var}@@/${value}/g"
done
)
#etitle "awkscript" cat "$awkscript"
#etitle "sedscript" cat "$sedscript"
}
function template_process_userfiles() {
local awkscript sedscript workfile userfile
ac_set_tmpfile awkscript
ac_set_tmpfile sedscript
template_generate_scripts "$awkscript" "$sedscript" "$@"
ac_set_tmpfile workfile
for userfile in "${userfiles[@]}"; do
cat "$userfile" | awk -f "$awkscript" | sed -f "$sedscript" >"$workfile" &&
cat "$workfile" >"$userfile"
done
ac_clean "$awkscript" "$sedscript" "$workfile"
}

1
bash/tests/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/template-dest.txt

View File

@ -0,0 +1,21 @@
---
PROFILES vaut prod test
c'est à dire, si on fait un par ligne:
- prod
- test
---
PASSWORD is vaeRL6ADYKmWndEA
---
hosts:
- first
- second
---
---
IF valeur
if valeur
#ul valeur
---
#if
UL
ul
---

View File

@ -0,0 +1,23 @@
---
PROFILES vaut @@PROFILES@@
c'est à dire, si on fait un par ligne:
@@FOR:PROFILES@@- @@PROFILE@@
---
PASSWORD is XXXRANDOMXXX
---
#@@IF:HOSTS@@hosts:
@@FOR:HOSTS@@- @@HOST@@
---
#@@IF:VALUES@@values:
@@FOR:VALUES@@- @@VALUE@@
---
#@@IF:PLEIN@@IF @@PLEIN@@
#@@if:PLEIN@@if @@PLEIN@@
#@@UL:PLEIN@@UL @@PLEIN@@
#@@ul:PLEIN@@ul @@PLEIN@@
---
#@@IF:VIDE@@IF @@VIDE@@
#@@if:VIDE@@if @@VIDE@@
#@@UL:VIDE@@UL @@VIDE@@
#@@ul:VIDE@@ul @@VIDE@@
---

View File

@ -0,0 +1,19 @@
#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
echo "\
source ./_template-values.env
template_vars=(
PROFILES
PASSWORD
HOSTS
VALUES
PLEIN
VIDE
)
template_lists=(
PROFILES
HOSTS
VALUES
)
"

View File

@ -0,0 +1,12 @@
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
PROFILES="prod test"
HOSTS="
first
second
"
VALUES=
PLEIN=valeur
VIDE=

29
bash/tests/test-template.sh Executable file
View File

@ -0,0 +1,29 @@
#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
source "$(dirname -- "$0")/../src/nulib.sh" || exit 1
require: template
#NULIB_NO_DISABLE_SET_X=1
args=(
"description"
#"usage"
)
parse_args "$@"; set -- "${args[@]}"
function template__source_envs() {
eval "$("$MYDIR/_template-source_envs")"
}
cd "$MYDIR"
#template_generate_scripts \
# /tmp/awkscript /tmp/sedscript \
# template_values.env
#
#for i in awk sed; do
# etitle "$i" cat "/tmp/${i}script"
#done
template_copy_replace _template-source.txt _template-dest.txt
template_process_userfiles _template_values.env
cat _template-dest.txt

30
bash/tests/test.awk Normal file
View File

@ -0,0 +1,30 @@
#@include "base.tools.awk"
BEGIN {
PROFILES[0] = 0; delete PROFILES
PROFILES[0] = "prod"
PROFILES[1] = "test"
HOSTS[0] = 0; delete HOSTS
HOSTS[0] = "first"
HOSTS[1] = "second"
VALUES[0] = 0; delete VALUES
}
{ if (should_generate_password()) { generate_password() } }
/\#@@EACH:PROFILES@@/ {
sub(/\#@@EACH:PROFILES@@/, "")
for (index in PROFILES) {
print gensub(/@@PROFILE@@/, PROFILES[index], "g")
}
next
}
/\#@@EACH:HOSTS@@/ {
sub(/\#@@EACH:HOSTS@@/, "")
for (index in HOSTS) {
print gensub(/@@HOST@@/, HOSTS[index], "g")
}
next
}
/\#@@EACH:VALUES@@/ {
sub(/\#@@EACH:VALUES@@/, "")
next
}
{ print }