diff --git a/lib/ulib/multiconf b/lib/ulib/multiconf index ac9efb8..91f4e64 100644 --- a/lib/ulib/multiconf +++ b/lib/ulib/multiconf @@ -6,6 +6,8 @@ uprovide multiconf function conf_local() { # afficher les commandes pour définir comme locales les variables utilisées # 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" } @@ -35,20 +37,27 @@ function conf_auto() { [ -n "$__name" ] || return 1 [ $# -gt 0 ] && conf_init "$@" local -a __CONF_FILES - conf_resolve __CONFS_FILES "$HOME/etc/default/$name.conf" "$HOME/$name.d/*.conf" + if [[ "$__name" == */* ]]; then + conf_resolve __CONFS_FILES "$__name.conf" "$__name.d/*.conf" + else + conf_resolve __CONFS_FILES "$HOME/etc/default/$__name.conf" "$HOME/etc/$__name.d/*.conf" + fi conf_load "${__CONFS_FILES[@]}" } function conf_init() { - # définir les variables attendues pour chargement par conf_load + # définir les variables attendues lors du chargement des fichiers de + # configuration par conf_load # 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. # dans l'exemple suivant: # conf_init NAME VALUE -a SRCDIRS DESTDIRS # NAME et VALUE sont scalaires alors que SRCDIRS et DESTDIRS sont tableaux - # Les variables sont initialisées à la valeur vide ou à la valeur spécifiée: + # Les variables scalaires sont initialisées à la valeur vide ou à la valeur + # spécifiée e.g.: # conf_init VAR=value + # Les variables tableaux sont toujours initialisées à la valeur vide # L'option -s permet de revenir au mode scalaire __CONF_ARRAY_VARS=() local __var __array @@ -57,8 +66,12 @@ function conf_init() { -a|--array) __array=1;; -s|--scalar) __array=;; *) - setv "$1" - [ -n "$__array" ] && array_addu __CONF_ARRAY_VARS "${1%%=*}" + if [ -n "$__array" ]; then + eval "${1%%=*}=()" + array_addu __CONF_ARRAY_VARS "${1%%=*}" + else + setv "$1" + fi ;; esac shift @@ -74,11 +87,52 @@ function conf_resolve() { # - si on spécifie un pattern e.g path/to/*.conf alors tous les fichiers # correspondant au pattern sont pris # - sinon l'argument est ignoré - : + local __conf_dest="$1"; shift + local -a __conf_files + local __conf_spec __conf_dir __conf_wc + array_new "$__conf_dest" + for __conf_spec in "$@"; do + if [ -f "$__conf_spec" ]; then + array_add "$__conf_dest" "$__conf_spec" + continue + elif [ -d "$__conf_spec" ]; then + __conf_spec="$__conf_spec/*.conf" + fi + splitwcs "$__conf_spec" __conf_dir __conf_wc + array_lsfiles __conf_files "${__conf_dir:-.}" "$__conf_wc" + array_extend "$__conf_dest" __conf_files + done } function conf_load() { # sourcer les fichiers spécifiés en faisant ce qui est nécessaire pour que # les variables de __CONF_ARRAY_VARS soient correctement traitées. - : + local -a __conf_backups __conf_values + local __conf_file __conf_name __conf_i __conf_backup + for __conf_file in "$@"; do + # faire une copie de sauvegarde puis supprimer les variables tableaux + __conf_backups=() + for __conf_name in "${__CONF_ARRAY_VARS[@]}"; do + __conf_backups=("${__conf_backups[@]}" "$(declare -p "$__conf_name")") + unset "$__conf_name" + done + # charger le fichier + source "$__conf_file" + # puis restaurer les variables ou les fusionner avec une éventuelle nouvelle valeur + __conf_i=0 + for __conf_name in "${__CONF_ARRAY_VARS[@]}"; do + __conf_backup="${__conf_backups[$__conf_i]}" + __conf_backup="${__conf_backup#declare * }" + if [ -n "$(declare -p "$__conf_name" 2>/dev/null)" ]; then + # la variable a été redéfinie, la fusionner avec la précédente valeur + array_copy __conf_values "$__conf_name" + eval "$__conf_backup" + array_extend "$__conf_name" __conf_values + else + # la variable n'a pas été redéfinie, restaurer la précédente valeur + eval "$__conf_backup" + fi + __conf_i=$(($__conf_i + 1)) + done + done }