implémentation simplifiée avec conf_upgrade()

This commit is contained in:
Jephté Clain 2017-09-24 14:07:09 +04:00
parent efc60b36ab
commit ea45055864
2 changed files with 86 additions and 91 deletions

81
TODO.md
View File

@ -1,84 +1,3 @@
# TODO
Faire des fonctions pour faciliter la gestion de configuration par défaut
La configuration est décrite dans un tableau nommé CONFIG par défaut
~~~
CONFIG=(
"-*- coding: utf-8 mode: sh -*-"
"# description de la variable NAME"
NAME=default_value
"# description de la variable LONG"
"# sur plusieurs lignes"
LONG="very long value"
)
~~~
* si le premier élément commence par `-*-` alors il contient les informations
pour générer la ligne de mode pour le fichier de config s'il faut le créer de
toutes pièces.
* chaque élément qui commence par `#` est une description de la variable qui
suit. plusieurs éléments sont fusionnés le cas échéant.
* les éléments de la forme NAME=DEFAULT_VALUE définissent une variable et sa
valeur par défaut.
A partir de ce tableau, la fonction upgrade_config() permet de créer un fichier
de config s'il n'existe pas, ou de la mettre à jour avec de nouvelles variables
s'il existe. Soit la commande suivante
~~~
upgrade_config path/to/config.conf CONFIG
~~~
Si le fichier config.conf n'existe pas, il est créé ainsi:
~~~
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
# description de la variable NAME
#NAME=default_value
# description de la variable LONG
# sur plusieurs lignes
#LONG="very long value"
~~~
Si le fichier config contenait ceci:
~~~
# -*- coding: utf-8 mode: conf -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
# description de la variable LONG
LONG="my value"
~~~
il est transformé en ceci, c'est à dire que la définition manquante de NAME est
rajoutée:
~~~
# -*- coding: utf-8 mode: conf -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
# description de la variable LONG
LONG="my value"
# description de la variable NAME
#NAME=default_value
~~~
A partir du tableau, la fonction load_config() permet de charger le fichier de
config en ne sélectionnant que les variables qui sont mentionnées dans le
tableau. Soit le fichier de configuration suivant
~~~
NAME=value
LONG=something
ROGUE=data
~~~
et les commandes suivantes
~~~
NAME=x
LONG=y
ROGUE=inchangée
load_config path/to/config.conf CONFIG
echo "NAME=$NAME, LONG=$LONG, ROGUE=$ROGUE"
~~~
le résultat est le suivant
~~~
NAME=value, LONG=something, ROGUE=inchangée
~~~
-*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary

View File

@ -9,7 +9,7 @@ function conf_local() {
# par les fonctions conf_*
# cela permet d'utiliser ces fonctions à l'intérieur d'autres fonctions sans
# polluer l'espace de nom
echo "local -a __CONF_ARRAY_VARS __CONF_PATH_VARS"
echo "local -a __CONF_DESCS __CONF_ARRAY_VARS __CONF_PATH_VARS"
}
function conf_auto() {
@ -46,7 +46,9 @@ function conf_auto() {
function conf_init() {
# définir les variables attendues lors du chargement des fichiers de
# configuration par conf_load_files
# configuration par conf_load_files()
# Si cette fonction n'a pas d'argument, le contenu du tableau CONFIG s'il
# est existe est utilisé
# par défaut, les variables sont en mode scalaire: la définition d'une
# variable écrase la valeur précédente. Avec l'option -a les variables sont
# en mode tableau: les nouvelles valeurs sont rajoutées à la fin du tableau.
@ -61,28 +63,70 @@ function conf_init() {
# conf_init VAR=value MYPATH=a:b:c
# Les variables tableaux sont toujours initialisées à la valeur vide
# L'option -s permet de revenir au mode scalaire
# Note: il est possible d'associer une description à chaque variable ainsi
# qu'un en-tête, ce qui permet de construire le fichier de configuration ou
# de mettre à jour un fichier existant avec conf_upgrade(). Par exemple, les
# commandes suivantes:
# CONFIG=(
# "# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8"
# "# configurer l'application"
# -s
# "NAME=payet//nom de l'administrateur"
# "MAIL=admin@host.tld//mail de contact"
# -a
# "HOSTS//hôtes autorisés à se connecter"
# )
# conf_init
# permettent de générer automatiquement le fichier de configuration suivant:
# # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
# # configurer l'application
#
# # nom de l'administrateur
# #NAME=payet
#
# # mail de contact
# #MAIL=admin@host.tld
#
# # hôtes autorisés à se connecter
# #HOSTS=()
__CONF_DESCS=()
__CONF_ARRAY_VARS=()
__CONF_PATH_VARS=()
local __var __type=scalar
local __type=scalar __initial=1 __prefix __var __desc
[ $# -eq 0 ] && is_array CONFIG && set -- "${CONFIG[@]}"
while [ $# -gt 0 ]; do
if [ -n "$__initial" ]; then
if [ "${1:0:1}" == "#" ]; then
[ ${#__prefix} -gt 0 ] && __prefix="$__prefix"$'\n'
__prefix="$__prefix$1"
shift
continue
else
[ -n "$__prefix" ] && array_add __CONF_DESCS "$__prefix"
__initial=
fi
fi
case "$1" in
-a|--array) __type=array;;
-p|--path) __type=path;;
-s|--scalar) __type=scalar;;
*)
array_add __CONF_DESCS "$1"
splitfsep "$1" // __var __desc
case "$__type" in
array)
eval "${1%%=*}=()"
array_addu __CONF_ARRAY_VARS "${1%%=*}"
array_del __CONF_PATH_VARS "${1%%=*}"
eval "${__var%%=*}=()"
array_addu __CONF_ARRAY_VARS "${__var%%=*}"
array_del __CONF_PATH_VARS "${__var%%=*}"
;;
path)
setv "$1"
array_addu __CONF_PATH_VARS "${1%%=*}"
array_del __CONF_ARRAY_VARS "${1%%=*}"
setv "$__var"
array_addu __CONF_PATH_VARS "${__var%%=*}"
array_del __CONF_ARRAY_VARS "${__var%%=*}"
;;
scalar)
setv "$1"
setv "$__var"
;;
esac
;;
@ -223,3 +267,35 @@ function conf_install() {
done
done
}
function conf_upgrade() {
# USAGE: conf_upgrade DEST VARS...
# Si les variables VARS... sont spécifiées, on appelle au préalable conf_init()
local dest="$1"; shift
if [ $# -gt 0 ]; then
eval "$(conf_local)"
conf_init "$@"
fi
local desc namevalue name value
# calculer le préfixe et initialiser le fichier le cas échéant
if [ ! -f "$dest" ]; then
local prefix
for desc in "${__CONF_DESCS[@]}"; do
[ "${desc:0:1}" == "#" ] && echo "$desc" >"$dest"
break
done
>>"$dest"
fi
# vérifier la présence de chaque variable
for desc in "${__CONF_DESCS[@]}"; do
[ "${desc:0:1}" == "#" ] && continue
splitfsep "$desc" // namevalue desc
splitvar "$namevalue" name value
if ! grep -qE "^\s*#*(\s*export)?\s*$name=" "$dest"; then
echo >>"$dest"
[ -n "$desc" ] && echo "# $desc" >>"$dest"
echo -n "#" >>"$dest"
echo_setv "$name" "$value" >>"$dest"
fi
done
}