nutools/lib/ulib/uinst

1622 lines
61 KiB
Bash

##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
## Fonctions de support pour uinst: déploiement local d'un fichier ou d'un répertoire.
##@cooked nocomments
##@require ulib
##@require base
##@require sysinfos
##@require compat
##@require udir
##@require prefixes
##@require pyulib/pyulib
##@require uinc
uprovide uinst
urequire ulib base sysinfos compat udir prefixes pyulib/pyulib uinc
function uinst() {
# lancer uinst en déclarant les variables locales, de façon à ne pas polluer
# l'environnement de l'appelant.
local UINST_CONFIGURE_FORCE
local UINST_COPY_METHOD
local UINST_LOCAL_PROFILES
local -a UINST_DEFAULTS
local -a UINST_CONFIG_VARS
local -a UINST_CONFIG_VARCMDS
local -a UINST_PROTECTED_VARS
local UINST_ORIGSRC
local UINST_SRCDIR
local UINST_ISTMPDIR
local UINST_TMPDIR
local UINST_AUTOPREFIX
local -a UDIR_VARS
local -a UDIR_ARRAYS
local UINST_ACTION
local UINST_AUTOSRCDIR
local UINST_PREPARE_DIR UINST_PREPARE_CONF UINST_PREPARE_ULIB
local udir_desc udir_note udir_types
local uinc
local -a uinc_options
local -a uinc_args
local -a preconfig_scripts
local -a configure_variables
local -a configure_dest_for
local -a config_scripts
local install_profiles
local profiledir
local bashrcdir
local defaultdir
local workdir_rsync_options
local workdir_excludes
local workdir_includes
local copy_files
local destdir destdir_override_userhost destdir_force_remote
local srcdir
local -a files
local owner
local -a modes
local -a root_scripts
local uinst2s
local ddb_enable ddb_profile ddb_conf
uinst_nolocal "$@"
}
function uinst_nolocal() {
# Interface en mode ligne de commande pour uinst. Appeler cette fonction
# avec les paramètres de la ligne de commande, e.g.:
# uinst_nolocal "$@"
function __uinst_display_help() {
uecho "$scriptname: Déployer en local un fichier, une archive, ou un répertoire
USAGE
$scriptname [options] <file|archive|dir>
OPTIONS
var=value
Spécifier la valeur d'une variable ou d'un préfixe, plutôt que de
laisser uprefix l'autodétecter. Utiliser 'uprefix -l' pour avoir une
liste de préfixes valides. Utiliser 'udir --help-vars' pour avoir une
liste de variables valides pour $scriptname.
-d /path/to/destdir
Spécifier le répertoire destination, exactement comme si la valeur
destdir avait été spécifiée, i.e destdir=\"/path/to/destdir\"
-h, --host [user@]host
Avec la méthode de déploiement uinst:rsync, permettre de spécifier un
hôte différent. Cette option est ignorée pour les autres méthodes de
déploiement. Si host vaut localhost, un déploiement local avec ssh est
effectué. Si host vaut '.', un déploiement local *sans passer par ssh*
est effectué, comme si seul le chemin avait été spécifié.
Cette option initialise la valeur destdir_override_userhost
-S, --ssh ssh
Avec la méthode de déploiement uinst:rsync, spécifier le programme à
utiliser pour la connection par ssh. Cette option initialise la valeur
destdir_ssh
--force-remote
Avec la méthode de déploiement uinst:rsync, si un hôte est spécifié dans
la valeur de destdir, forcer le déploiement distant avec ssh+rsync, même
si l'hôte et l'utilisateur correspondent aux valeurs courantes. Cette
option initialise la valeur destdir_force_remote
--deploydb
--nd, --no-deploydb
Autoriser (respectivement interdire) l'utilisation de la configuration
locale de déploiement pour identifier la source et/ou la destination
s'ils ne sont pas spécifiés. Par défaut, la configuration locale de
déploiement est utilisée.
Cette option et toutes celles associées n'est utilisée que pour la
méthode de déploiement uinst:rsync
-p, --dp, --deploydb-profile PROFILENAME
Spécifier un ou plusieurs profils séparés par des virgules pour le
déploiement avec la configuration locale de déploiement. NONE est la
valeur par défaut et signifie de ne sélectionner que les définitions
sans profil. ALL signifie de ne pas tenir compte des profils dans les
définitions.
-A, --all-profiles
-P, --prod
-T, --test
Raccourcis respectivement pour -pALL, -pprod et -ptest
-c, --dc, --deploydb-config CONFNAME
Cette option permet de spécifier un fichier de configuration ou le nom
de la configuration locale de déploiement à utiliser pour effectuer la
requête. Par défaut, utiliser le nom 'uinst.conf'
-a, --auto
Si la source n'est pas spécifiée, déterminer le répertoire à déployer
automatiquement (c'est la valeur par défaut)
--no-auto
Ne pas déterminer automatiquement le répertoire à déployer.
--prefix
Corriger les chemins srcdir et destdir qui commencent par des préfixes
valides (c'est la valeur par défaut). Utiliser 'uprefix -l' pour avoir
une liste de préfixes valides
--no-prefix
Ne jamais corriger un chemin.
--include-vcs
Inclure les fichiers de VCS dans les fichiers copiés. Par défaut, les
fichiers de VCS sont exclus.
-l, --local-profiles
Installer les profils locaux comme tels
--shared-profiles
Installer les profils locaux comme des profils partagés. C'est la valeur
par défaut pour compatibilité.
-C Configurer un répertoire pour le déploiement avec uinst
Ajouter l'option --force pour forcer la reconfiguration"
}
# Définir ULIBDIR, PYULIBDIR et UINST si ce n'est pas le cas.
# Ces variables sont utilisées par les scripts
if [ -z "$ULIBDIR" ]; then
if [ -d "$scriptdir/ulib" ]; then
ULIBDIR="$scriptdir/ulib"
elif [ -d "$scriptdir/lib/ulib" ]; then
ULIBDIR="$scriptdir/lib/ulib"
else
ULIBDIR="$scriptdir/ulib"
fi
fi
if [ -z "$PYULIBDIR" ]; then
if [ -d "$scriptdir/pyulib" ]; then
PYULIBDIR="$scriptdir/pyulib"
elif [ -d "$scriptdir/lib/pyulib" ]; then
PYULIBDIR="$scriptdir/lib/pyulib"
else
PYULIBDIR="$scriptdir/pyulib"
fi
fi
UINST="${UINST:-$script}"
eval "$(utools_local)"
__uinst_init
UINST_ACTION=
UINST_AUTOSRCDIR=1
ddb_enable='1'
ddb_profile='NONE'
ddb_conf='uinst.conf'
parse_opts "${PRETTYOPTS[@]}" \
--help '$exit_with __uinst_display_help' \
--is-tmpdir UINST_ISTMPDIR \
-O: '$__uinst_addvar owner "$value_"' \
-m: '$__uinst_addvar modes "$value_"' \
-d: '$__uinst_addvar destdir "$value_"' \
-h:,-H:,--host: '$__uinst_addvar destdir_override_userhost "$value_"' \
-S:,--ssh: '$__uinst_addvar destdir_ssh "$value_"' \
--force-remote '$__uinst_addvar destdir_force_remote 1' \
--deploydb ddb_enable=1 \
--nd,--no-deploydb ddb_enable= \
-p:,--dp:,--deploydb-profile ddb_profile= \
-A,--all-profiles ddb_profile=ALL \
-P,--prod ddb_profile=prod \
-T,--test ddb_profile=test \
-c:,--dc:,--deploydb-config ddb_conf= \
-a,--auto UINST_AUTOSRCDIR=1 \
--no-auto UINST_AUTOSRCDIR= \
--prefix UINST_AUTOPREFIX=1 \
--no-prefix UINST_AUTOPREFIX= \
--include-vcs UINST_COPY_METHOD=cpdir \
-l,--local-profiles UINST_LOCAL_PROFILES=1 \
--shared-profiles UINST_LOCAL_PROFILES= \
-C UINST_ACTION=configure \
-f,--force UINST_CONFIGURE_FORCE=1 \
--prepare-1s: UINST_PREPARE_DIR \
--prepare-2s UINST_ACTION=prepare-2s \
--prepare-conf: UINST_PREPARE_CONF \
--prepare-with-ulib UINST_PREPARE_ULIB \
@ args -- "$@" &&
set -- "${args[@]}" || {
eerror "$args"
return 1
}
# configuration de la phase, dans le mode prepare
[ -n "$UINST_PREPARE_DIR" -a -z "$UINST_ACTION" ] && UINST_ACTION=prepare-1s
# action par défaut
[ -n "$UINST_ACTION" ] || UINST_ACTION=uinst
if [ "$UINST_ACTION" == "configure" ]; then
__uinst_configure "${args[@]}" || return 1
elif [ "$UINST_ACTION" == prepare-1s ]; then
UINST_PREPARE_DIR="$(abspath "$UINST_PREPARE_DIR")"
mkdir -p "$UINST_PREPARE_DIR" || return 1
if [ -z "$UINST_PREPARE_CONF" ]; then
UINST_PREPARE_CONF="$UINST_PREPARE_DIR/uinst_prepare.conf"
fi
UINST_PREPARE_CONF="$(abspath "$UINST_PREPARE_CONF")"
__uinst_do "${args[@]}" || return 1
elif [ "$UINST_ACTION" == prepare-2s ]; then
UINST_ISTMPDIR=1
__uinst_do "${args[@]}" || return 1
else
__uinst_do "${args[@]}" || return 1
fi
return 0
}
function __uinst_init() {
UINST_CONFIGURE_FORCE=
UINST_COPY_METHOD="${UINST_COPY_METHOD:-cpdirnovcs}"
UINST_LOCAL_PROFILES="${UTOOLS_LOCAL_PROFILES:-auto}"
UINST_DEFAULTS=(
uinc='release'
uinc_options='()'
uinc_args='()'
preconfig_scripts='()'
configure_variables='(dest)'
configure_dest_for='()'
config_scripts='()'
install_profiles='false'
profiledir='lib/profile.d'
bashrcdir='lib/bashrc.d'
defaultdir='lib/default'
workdir_rsync_options='()'
workdir_excludes='()'
workdir_includes='()'
copy_files='true'
destdir='/usr/local'
destdir_override_userhost=
destdir_ssh=
destdir_force_remote=
srcdir='.'
files='()'
owner='root:'
modes='(u=rwX,g=rX,o=rX)'
root_scripts='()'
)
UINST_CONFIG_VARS=()
UINST_CONFIG_VARCMDS=()
UINST_PROTECTED_VARS=(UINST_PROTECTED_VARS UINST_CONFIG_VARS UINST_CONFIG_VARCMDS UINST_STANDALONE)
__uinst_protectvars configure_variables \
UINST_ORIGSRC UINST_SRCDIR \
UINST_ISTMPDIR UINST_TMPDIR \
UINST_AUTOPREFIX \
UDIR_VARS UDIR_ARRAYS
UINST_ORIGSRC=
UINST_SRCDIR=
UINST_ISTMPDIR=
UINST_TMPDIR=
UINST_AUTOPREFIX=1
UDIR_VARS=()
UDIR_ARRAYS=()
}
function __uinst_configure() {
# Configurer le répertoire $1 pour installation avec uinst
srcdir="${1:-.}"; shift
[ -d "$srcdir" ] || {
eerror "$srcdir: répertoire inexistant"
return 1
}
srcdir="$(abspath "$srcdir")"
urequire udir
function __uinst_update_types() {
udir_types=("${udir_types[@]}" uinst)
set_array_cmd udir_types
}
function __uinst_should_update() {
local udir_type
for udir_type in "${udir_types[@]}"; do
if [ "$udir_type" == "uinst" ]; then
echo "false"; return
elif [[ "$udir_type" == uinst:* ]]; then
echo "false"; return
fi
done
__uinst_update_types uinst
}
if [ -z "$UINST_CONFIGURE_FORCE" ]; then
if udir_check "$srcdir"; then
# Nous avons déjà un fichier .udir
# Si le répertoire n'est pas du type uinst, le migrer en rajoutant
# les options par défaut
if eval "$(udir_eval "$srcdir" __uinst_should_update)"; then
udir_update "$srcdir" "$(set_array_cmd udir_types)" "${UINST_DEFAULTS[@]}"
enote "Le répertoire $(ppath "$srcdir") a déjà été configuré pour uinst.
Utilisez 'udir -e $(ppath "$srcdir")' pour modifier les paramètres qui ont été rajoutés."
fi
return 0
elif [ -f "$srcdir/.uinst.conf" ]; then
# Nous avons un fichier .uinst.conf
# proposer de migrer le répertoire vers .udir
check_interaction -c && enote "Ce répertoire contient un fichier .uinst.conf"
if ask_yesno "Voulez-vous le migrer vers le format .udir?" N; then
estep "Configuration de $(ppath "$srcdir") pour uinst"
__uinst_migrate_legacy "$srcdir"
__uinst_varcmds=()
for __uinst_v in "${UDIR_VARS[@]}"; do
__uinst_varcmds=("${__uinst_varcmds[@]}" "$(echo_setv "$__uinst_v" "${!__uinst_v}")")
done
for __uinst_a in "${UDIR_ARRAYS[@]}"; do
__uinst_varcmds=("${__uinst_varcmds[@]}" "$(set_array_cmd "$__uinst_a")")
done
udir_update "$srcdir" 'udir_types=(uinst)' "${__uinst_varcmds[@]}"
enote "Vous pouvez maintenant supprimer le fichier: rm -f '$(ppath "$srcdir/.uinst.conf")'"
else
estep "Configuration de $(ppath "$srcdir") pour uinst:legacy"
udir_update "$srcdir" 'udir_types=(uinst:legacy)'
fi
return 0
fi
fi
# Sans fichier .udir, faire la configuration par défaut
# Poser des questions pour déterminer le type de configuration à faire
local udir_desc udir_note udir_types
local profiles conf rootconf ulibsync copy_files
eval "$(udir_eval "$srcdir" 'echo_setv udir_desc "$udir_desc"; echo_setv udir_note "$udir_note"')"
etitle "Description du projet"
check_interaction -c && estepn "La description courte de l'objet de ce projet est affichée avec udir -i"
read_value "Entrez une description de ce projet" udir_desc "$udir_desc" N
check_interaction -c && estepn "La note est affichée quand on entre dans le répertoire du projet.
Elle peut être utilisée pour diriger le visiteur vers des informations importantes."
read_value "Entrez une note associée au répertoire de ce projet" udir_note "$udir_note" N
eend
udir_update "$srcdir" "udir_desc=$(qval "$udir_desc")" "udir_note=$(qval "$udir_note")"
estepn "La configuration par défaut permet de créer un projet qui utilise les outils et librairies de nutools.
Ce projet pourra ensuite être installé avec uinst"
if ask_yesno "Voulez-vous utiliser la configuration par défaut?" O; then
udir_types='(uinst)'
etitle "Configuration du module"
ask_yesno "Faut-il installer des profils pour bash?" O && profiles=1
ask_yesno "Faut-il créer un script de configuration?" O && conf=1
ask_yesno "Faut-il créer un script de configuration root?" O && rootconf=1
check_interaction -c && estep "Configuration avancée"
ask_yesno "Faut-il faire une copie locale de ulib?" O && ulibsync=1
ask_yesno "Faut-il déployer le projet dans /usr/local?" O && copy_files=1
eend
mkdir -p "$srcdir/lib"
[ -n "$ulibsync" ] && ulibsync "$srcdir/lib"
udir_update "$srcdir" "udir_types=$udir_types" "${UINST_DEFAULTS[@]}"
[ -n "$copy_files" ] && copy_files=true || copy_files=false
udir_update "$srcdir" \
${profiles:+install_profiles=true} \
${conf:+config_scripts='(lib/uinst/conf)'} \
copy_files="$copy_files" \
${rootconf:+root_scripts='(lib/uinst/rootconf)'}
local genfile
if [ -n "$profiles" ]; then
genfile="$srcdir/lib/profile.d/$(basename "$srcdir")"
mkdirof "$genfile"
[ -f "$genfile" ] || echo '# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
__uaddpath "@@dest@@" PATH' >"$genfile"
udir_update "$srcdir" "configure_dest_for=($(qvalm "${genfile#"$srcdir/"}"))"
fi
if [ -n "$conf" ]; then
genfile="$srcdir/lib/uinst/conf"
mkdirof "$genfile"
[ -f "$genfile" ] || echo '# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
source "$@" || exit 1
source "$ULIBDIR/ulib" || exit 1
urequire DEFAULTS' >"$genfile"
fi
if [ -n "$rootconf" ]; then
genfile="$srcdir/lib/uinst/rootconf"
mkdirof "$genfile"
[ -f "$genfile" ] || echo '# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
source "$@" || exit 1
source "$ULIBDIR/ulib" || exit 1
urequire DEFAULTS' >"$genfile"
fi
else
local -a udir_typess
udir_typess=(uinst uinst:rsync uinst:python)
udir_types=uinst
simple_menu udir_types udir_typess -t "Choix du type d'installation" -m "Veuillez choisir le type d'installation pour ce projet"
if [ "$udir_types" == uinst ]; then
udir_update "$srcdir" "udir_types=($udir_types)" "${UINST_DEFAULTS[@]}"
elif [ "$udir_types" == uinst:rsync ]; then
local rsync_options
estepn "Les options suivantes sont définies pour la synchronisation par rsync:
-av --exclude CVS --exclude .svn --exclude /.git/
Vous pouvez en définir d'autres"
read_value "Entrez des options de rsync" rsync_options "" N
udir_update "$srcdir" "udir_types=($udir_types)" "${UINST_DEFAULTS[@]}" "rsync_options=($rsync_options)"
elif [ "$udir_types" == uinst:python ]; then
udir_update "$srcdir" "udir_types=($udir_types)"
fi
fi
enote "Le répertoire $(ppath "$srcdir") a été configuré avec les valeurs par défaut pour uinst.
Utilisez 'udir -e $(ppath "$srcdir")' pour modifier les paramètres."
}
function __uinst_defaultvars() {
eval "$(array_join UINST_DEFAULTS ';')"
UDIR_VARS=(uinc install_profiles profiledir bashrcdir defaultdir copy_files destdir destdir_override_userhost destdir_ssh destdir_force_remote srcdir owner)
UDIR_ARRAYS=(uinc_options uinc_args preconfig_scripts configure_variables configure_dest_for config_scripts workdir_rsync_options workdir_excludes workdir_includes files modes root_scripts)
}
function __uinst_protectvars() {
local __uinst_var
if [ -n "$*" ]; then
# Enregistrer les noms des variables à protéger de la modification dans
# une fonction qui source un fichier externe
for __uinst_var in "$@"; do
array_set UINST_PROTECTED_VARS "$__uinst_var"
done
else
# Afficher des commandes à lancer pour protéger les variables dans la
# fonction. A utiliser ainsi:
# eval "$(__uinst_protectvars)"
for __uinst_var in "${UINST_PROTECTED_VARS[@]}"; do
if [ "$__uinst_var" == UINST_PROTECTED_VARS ]; then
echo "local $__uinst_var"
else
echo "local $__uinst_var=\"\$$__uinst_var\""
fi
done
fi
}
function __uinst_do() {
# Installer le répertoire $1. L'environnement doit d'abord être initialisé
# avec __uinst_init() et éventuellement uinst()
srcdir=
for __uinst_var in "$@"; do
if [[ "$__uinst_var" == *=* ]]; then
__uinst_name="${__uinst_var%%=*}"
__uinst_value="${__uinst_var#*=}"
__uinst_addvar "$__uinst_name" "$__uinst_value"
elif [ -z "$srcdir" ]; then
srcdir="$__uinst_var"
UINST_ORIGSRC="$srcdir"
else
ewarn "$__uinst_var: cet argument a été ignoré"
fi
done
if [ -z "$srcdir" ]; then
if __uinst_check_dir .; then
srcdir="."
UINST_ORIGSRC="$srcdir"
fi
fi
if [ -z "$srcdir" ]; then
__uinst_found=
if [ -n "$UINST_AUTOSRCDIR" ]; then
parentdirs srcdirs ..
for srcdir in "${srcdirs[@]}"; do
if __uinst_check_dir "$srcdir"; then
__uinst_found=1
break
fi
done
fi
[ -n "$__uinst_found" ] || {
eerror "\
Impossible de déterminer automatiquement le répertoire à installer
Essayez avec 'uinst -C'"
return 1
}
ask_yesno -y "Le répertoire '$(ppath "$srcdir")' a été calculé automatiquement. Voulez-vous le déployer?" O || return 1
UINST_ORIGSRC="$srcdir"
fi
# Tester s'il faut bootstrapper
if [ -f "$srcdir/.nutools-bootstrap" ]; then
local need_python need_gawk
has_python || need_python=1
has_gawk || need_gawk=1
if check_sysinfos -s linux; then
if [ -n "$need_python" -o -n "$need_gawk" ]; then
eimportant "Il FAUT installer Python 2 et $(get_color y)*GNU*$(get_color z)awk pour que nutools fonctionne correctement."
if check_sysinfos -d debian; then
if ask_yesno "Voulez-vous que ce script essaye d'installer automatiquement ces dépendances (requière les droits root)?" O; then
urequire debian
pkg_install ${need_python:+python} ${need_gawk:+gawk} || {
eerror "Une erreur s'est produite pendant l'installation. Veuillez faire l'installation manuellement"
return 1
}
need_python=
need_gawk=
fi
fi
fi
fi
if [ -n "$need_python" ]; then
eerror "Python 2 est requis. Veuillez faire l'installation avant de relancer ce script."
return 1
fi
if [ -n "$need_gawk" ]; then
ewarn "$(get_color y)*GNU*$(get_color z)awk est requis mais n'est pas installé. Ce script va continuer, mais les résultats ne sont pas garantis."
fi
# s'assurer que les libraries *locales* sont dans PYTHONPATH
source "$ULIBDIR/pyulib/pyulib"
fi
if [ -n "$UINST_AUTOPREFIX" ]; then
# initialiser le moteur de préfixes
urequire PREFIXES-DEFAULTS
compute_all_prefixes
srcdir="$(expand_prefix "$srcdir")"
fi
[ -e "$srcdir" ] || {
eerror "$srcdir: fichier ou répertoire introuvable"
return 1
}
UINST_SRCDIR="$(abspath "$srcdir")"
__uinst_addvar srcdir "$UINST_SRCDIR"
__uinst_dispatch
}
function __uinst_addvarnf() {
# Ajouter une variable et sa valeurs, sans l'enregistrer dans la liste des
# variables modifiées par l'utilisateur.
# $1=name, $2=value
if array_contains UINST_PROTECTED_VARS "$1"; then
local OENC="$UTF8"
eerror "La variable $1 est protégée"
return 1
else
array_add UINST_CONFIG_VARCMDS "$(echo_setv "$1" "$2")"
_setv "$1" "$2"
if [ "$1" == "MYHOST" ]; then
# cas particulier: initialiser aussi MYHOSTNAME
_setv "MYHOSTNAME" "${2%%.*}"
array_add UINST_CONFIG_VARCMDS "$(echo_setv "MYHOSTNAME" "$MYHOSTNAME")"
fi
return 0
fi
}
function __uinst_addvar() {
# Ajouter une variable et sa valeur, et l'enregistrer dans la liste des
# variables spécifiées par l'utilisateur.
# $1=name, $2=value
if __uinst_addvarnf "$@"; then
array_set UINST_CONFIG_VARS "$1"
fi
}
function __uinst_setvar() {
# Evaluer la variable $1 en prenant sa valeur dans CONFIG_VARCMDS
local __uinst_varcmd
for __uinst_varcmd in "${UINST_CONFIG_VARCMDS[@]}"; do
if beginswith "$__uinst_varcmd" "$1="; then
eval "$__uinst_varcmd"
# ne pas faire break, parce que plusieurs occurences peuvent
# exister, les dernières écrasant les premières
fi
done
}
function __uinst_setvars() {
# Evaluer toute les variables de CONFIG_VARCMDS pour initialiser leurs
# valeurs
local __uinst_varcmd
for __uinst_varcmd in "${UINST_CONFIG_VARCMDS[@]}"; do
eval "$__uinst_varcmd"
done
}
function __uinst_printmergedvars() {
# Construire une liste de variables dont il faut afficher la valeur:
# - les variables qui ont été mentionnées sur la ligne de commandes
# - les variables mentionnées dans le tableau configure_variables
# Puis afficher ces variables et leurs valeurs
local -a __uinst_mvars
local __uinst_mvar
array_copy __uinst_mvars UINST_CONFIG_VARS
array_extend __uinst_mvars configure_variables
for __uinst_mvar in "${__uinst_mvars[@]}"; do
estep "$__uinst_mvar=${!__uinst_mvar}"
done
}
function __uinst_check_dir() {
# Tester si le répertoire $1 est installable par uinst
__uinst_check_udir "$1" ||
__uinst_check_legacy "$1" ||
__uinst_check_rsync "$1" ||
__uinst_check_python "$1"
}
function __uinst_check_uinst2s() {
# Vérifier le script de second étage $1 existe, et initialiser la variable
# uinst2s avec le chemin vers le script
uinst2s="$ULIBDIR/support/${1:-uinst2s}"
[ -x "$uinst2s" ] || {
eerror "Script ${uinst2s#$ULIBDIR/support/} introuvable dans '$(dirname "$uinst2s")'"
return 1
}
}
function __uinst_dispatch() {
# Sélectionner la méthode appropriée pour installer $srcdir
if __uinst_check_udir "$srcdir"; then
# Répertoire uinst configuré avec udir
__uinst_udir || return 1
elif __uinst_check_legacy "$srcdir"; then
# Répertoire uinst original
__uinst_legacy || return 1
elif __uinst_check_rsync "$srcdir"; then
# Fichiers à déployer avec rsync
__uinst_rsync || return 1
elif __uinst_check_python "$srcdir"; then
# Package python
__uinst_python || return 1
elif __uinst_check_archive "$srcdir"; then
# Archive
__uinst_archive || return 1
elif [ -f "$srcdir" ]; then
# Fichier simple
__uinst_file || return 1
else
eerror "$srcdir: impossible de déployer un répertoire non préparé.
Veuillez préparer ce répertoire avec 'uinst -C $(ppath "$srcdir")'
Si le répertoire a déjà été préparé, vérifier la présence de l'une des valeurs
'uinst', 'uinst:legacy', 'uinst:rsync' ou 'uinst:python' dans la variable
udir_types."
return 1
fi
}
function __uinst_prepare_workdir() {
# Faire une copie de travail de $srcdir dans $1
# srcdir est modifié pour devenir la nouvelle valeur
local srcname="$(basename "$srcdir")"
local destdir="$1/$srcname"
estep "Création d'une copie de travail dans $1..."
if [ ${#workdir_excludes[*]} -gt 0 -o ${#workdir_includes[*]} ]; then
# on a spécifié des inclusions ou exclusions pour le répertoire de
# travail
(
if ! array_isempty workdir_rsync_options; then
array_copy __CPNOVCS_RSYNC_ARGS workdir_rsync_options
fi
for exclude in "${workdir_excludes[@]}"; do
array_add __CPNOVCS_RSYNC_ARGS --exclude "$exclude"
done
for include in "${workdir_includes[@]}"; do
array_add __CPNOVCS_RSYNC_ARGS --include "$include"
done
cd "$srcdir"
"${UINST_COPY_METHOD:-cpdirnovcs}" . "$destdir"
)
else
# copie simple du répertoire de travail
"${UINST_COPY_METHOD:-cpdirnovcs}" "$srcdir" "$destdir"
fi
srcdir="$destdir"
chmod -R +w "$srcdir" || return 1
return 0
}
function __uinst_prepare_ulib() {
# Copie l'environnement de déploiement dans $UINST_PREPARE_DIR
estep "Copie de l'environnement de déploiement"
ulibsync "$UINST_PREPARE_DIR"
pyulibsync "$UINST_PREPARE_DIR"
echo '#!/bin/sh
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
if . `dirname "$0"`/ulib/ulibsh; then
urequire DEFAULTS sysinfos compat uinst udir prefixes uinc
else
exit 1
fi
OENC="$UTF8"
uinst "$@"' >"$UINST_PREPARE_DIR/uinst.sh"
chmod +x "$UINST_PREPARE_DIR/uinst.sh"
}
function __uinst_prepare_conf() {
# créer le fichier de configuration $UINST_PREPARE_CONF avec
# prepare_name=$srcdir
# srcdir est un chemin relatif à $UINST_PREPARE_DIR (si la source était une
# archive, il est possible que ce chemin soit en plusieurs parties
echo_setv prepare_name "$(relpath "$srcdir" "$UINST_PREPARE_DIR")" >"$UINST_PREPARE_CONF"
}
################################################################################
# uinst: udir
function __uinst_check_udir() {
# Vérifier si $1 est un répertoire configuré avec udir, installable avec
# uinst
if [ -d "$1" -a -f "$1/.udir" ]; then
udir_eval "$1" 'array_contains udir_types uinst' && return 0
fi
return 1
}
function __uinst_udir() {
# Installer le répertoire $srcdir qui contient la configuration dans le
# fichier .udir
local uinst2s
__uinst_check_uinst2s || return 1
# initialiser les valeurs par défaut, mais penser à restaurer srcdir
__uinst_defaultvars
__uinst_setvar srcdir
# puis charger les valeurs de $srcdir/.udir, mais penser à restaurer srcdir
eval "$(udir_dump "$srcdir")"
__uinst_setvar srcdir
# initialiser UDIR_VARS et UDIR_ARRAYS. cela permettra de construire le
# fichier de configuration pour les scripts et le déploiement
udir_parse "$srcdir"
# puis charger les valeurs de la ligne de commande
__uinst_setvars
# corriger éventuellement destdir
[ -n "$UINST_AUTOPREFIX" ] && destdir="$(expand_prefix "$destdir")"
# afficher les valeurs dignes d'intérêt
__uinst_printmergedvars
# puis lancer le déploiement
__uinst_udir2s
}
function __uinst_udir2s() {
# Installer le répertoire $srcdir
local OENC="$UTF8"
if [ "$UINST_ACTION" == prepare-1s ]; then
: # pas de confirmation en mode prépare
elif is_yes "$copy_files"; then
ask_yesno "Déployer $(ppath "$srcdir") dans $(ppath "$destdir") sur $MYHOST?" O || return 1
else
ask_yesno "Déployer $(ppath "$srcdir") sur $MYHOST?" O || return 1
fi
local origsrcdir="$srcdir" # utilisé par uinc
local srcname="$(basename "$srcdir")"
local dest="$destdir/$srcname"
## Configurer la source: faire éventuellement une copie de travail
if [ -z "$UINST_ISTMPDIR" ]; then
if [ "$UINST_ACTION" == prepare-1s ]; then
# Faire la copie de travail pour le prédéploiement dans le
# répertoire spécifié
__uinst_prepare_workdir "$UINST_PREPARE_DIR" || return 1
else
# Si nous ne sommes pas dans un répertoire temporaire, alors faire
# une copie de travail
ac_set_tmpdir UINST_TMPDIR
__uinst_prepare_workdir "$UINST_TMPDIR" || return 1
fi
fi
## Déplier les inclusions
# Ne déplier les inclusions que maintenant, parce que le répertoire initial
# était peut-être protégé en écriture.
# ne pas déplier si on est dans la deuxième phase de l'étape de préparation
if [ "$UINST_ACTION" != prepare-2s ] && is_yes "$uinc"; then
# uinc doit charger les paramètres de .udir/.uinst.conf, d'où le --auto
# par contre, on doit forcer les paramètres --refdir et -u
etitle "Dépliage des inclusions" \
uinc -y --auto --refdir "$origsrcdir" -C uinst -u "$srcdir"
fi
## Prédéploiement
if [ "$UINST_ACTION" == prepare-1s ]; then
# Fin de traitement si on est dans la première phase de l'étape de
# préparation
[ -n "$UINST_PREPARE_ULIB" ] && __uinst_prepare_ulib
__uinst_prepare_conf
return 0
fi
## Faire le fichier de configuration
local __uinst_configdir __uinst_config __uinst_abort
local __uinst_var
local -a __uinst_vars __uinst_arrays
for __uinst_var in "${UINST_CONFIG_VARS[@]}" "${configure_variables[@]}"; do
if array_contains UDIR_ARRAYS "$var_"; then
array_set __uinst_arrays "$__uinst_var"
else
array_set __uinst_vars "$__uinst_var"
fi
done
for __uinst_var in "${UDIR_VARS[@]}"; do
array_set __uinst_vars "$__uinst_var"
done
for __uinst_var in "${UDIR_ARRAYS[@]}"; do
array_set __uinst_arrays "$__uinst_var"
done
ac_set_tmpdir __uinst_configdir
__uinst_config="$__uinst_configdir/config"
__uinst_abort="$__uinst_configdir/abort"
__uinst_updateconfig="$__uinst_configdir/updateconfig"
echo_setv ABORT "$__uinst_abort" >>"$__uinst_config"
echo_setv CONFIG "$__uinst_updateconfig" >>"$__uinst_config"
echo_setv __verbosity "$__verbosity" >>"$__uinst_config"
echo_setv __interaction "$__interaction" >>"$__uinst_config"
for __uinst_var in "${__uinst_vars[@]}"; do
echo_setv "$__uinst_var" "${!__uinst_var}" >>"$__uinst_config"
done
for __uinst_var in "${__uinst_arrays[@]}"; do
set_array_cmd "$__uinst_var" >>"$__uinst_config"
done
echo_setv "UINST_LOCAL_PROFILES" "$UINST_LOCAL_PROFILES" >>"$__uinst_config"
echo_setv "UINST_ISTMPDIR" "$UINST_ISTMPDIR" >>"$__uinst_config"
echo_setv "UINST_ORIGSRC" "$UINST_ORIGSRC" >>"$__uinst_config"
echo_setv "UINST_SRCDIR" "$UINST_SRCDIR" >>"$__uinst_config"
echo_setv "ULIBDIR" "$ULIBDIR" >>"$__uinst_config"
echo_setv "UINST" "$UINST" >>"$__uinst_config"
# ulib recalcule systématiquement la valeur de ULIBDIR. Pareil pour
# pyulib/pyulib. Mais cela ne fonctionne pas si nous déployons sur une
# machine avec bash 2.x. Il faut donc forcer l'utilisation de la valeur
# calculée.
echo_setv "FORCED_ULIBDIR" "$ULIBDIR" >>"$__uinst_config"
echo_setv "FORCED_PYULIBDIR" "$PYULIBDIR" >>"$__uinst_config"
## Lancer les scripts de préconfiguration
function __uinst_preconfig_scripts() {
for preconfig_script in "${preconfig_scripts[@]}"; do
rm -f "$__uinst_abort" "$__uinst_updateconfig"
etitle "$preconfig_script" \
"${BASH:-/bin/sh}" "$srcdir/$preconfig_script" "$__uinst_config"
[ -f "$__uinst_abort" ] && return 1
if [ -f "$__uinst_updateconfig" ]; then
cat "$__uinst_updateconfig" >>"$__uinst_config"
source "$__uinst_updateconfig"
fi
done
return 0
}
etitle "Lancement des scripts de préconfiguration" __uinst_preconfig_scripts || return 1
## Configurer les variables
if [ -n "${configure_variables[*]}" ]; then
function __uinst_config_variables() {
local __uinst_cvar __uinst_cvarname __uinst_cfilespecs
for __uinst_cvarname in "${configure_variables[@]}"; do
__uinst_cvar="${!__uinst_cvarname}"
__uinst_cvar="${__uinst_cvar//,/\\,}"
etitle -s "$__uinst_cvarname"
__uinst_cfilespecs="configure_${__uinst_cvarname}_for[*]"
if [ -n "${!__uinst_cfilespecs}" ]; then
array_copy __uinst_cfilespecs "configure_${__uinst_cvarname}_for"
for __uinst_cfilespec in "${__uinst_cfilespecs[@]}"; do
splitwcs "$__uinst_cfilespec" __uinst_cfilen __uinst_cfilewc
if [ -n "$__uinst_cfilewc" ]; then
# il y a des wildcards
array_from_lines __uinst_cfiles "$(list_files "$srcdir/$__uinst_cfilen" "$__uinst_cfilewc")"
for __uinst_cfile in "${__uinst_cfiles[@]}"; do
__uinst_cfile="$__uinst_cfilen/$__uinst_cfile"
estep "$__uinst_cfile"
if quietgrep "@@${__uinst_cvarname}@@" "$srcdir/$__uinst_cfile"; then
sedi "s|@@${__uinst_cvarname}@@|$__uinst_cvar|g" "$srcdir/$__uinst_cfile"
fi
done
else
# pas de wildcards
__uinst_cfile="$__uinst_cfilespec"
estep "$__uinst_cfile"
if quietgrep "@@${__uinst_cvarname}@@" "$srcdir/$__uinst_cfile"; then
sedi "s|@@${__uinst_cvarname}@@|$__uinst_cvar|g" "$srcdir/$__uinst_cfile"
fi
fi
done
fi
eend
done
}
etitle "Configuration des variables" __uinst_config_variables
fi
## Lancer les scripts de configuration
function __uinst_config_scripts() {
for config_script in "${config_scripts[@]}"; do
rm -f "$__uinst_abort"
etitle "$config_script" \
"${BASH:-/bin/sh}" "$srcdir/$config_script" "$__uinst_config"
[ -f "$__uinst_abort" ] && return 1
done
return 0
}
etitle "Lancement des scripts de configuration" __uinst_config_scripts || return 1
## Installer les profils
if is_yes "$install_profiles"; then
urequire uenv uenv_update
etitle "Installation des profils"
local local_profiles="$UINST_LOCAL_PROFILES"
[ "$local_profiles" == auto ] && local_profiles=
uenv_install_profiles ${local_profiles:+--local-profiles} "$srcdir" "$profiledir" "$bashrcdir" "$defaultdir"
eend
fi
## Déploiement
# seulement s'il y a des copies de fichier ou des scripts roo
if is_yes "$copy_files" || [ -n "${root_scripts[*]}" ]; then
etitle "Lancement du déploiement" runscript_as_root "$uinst2s" "$__uinst_config"
fi
return 0
}
################################################################################
# uinst: rsync
function __uinst_check_rsync() {
# Vérifier si $1 est un répertoire à déployer avec rsync
if [ -d "$1" -a -f "$1/.udir" ]; then
udir_eval "$1" 'array_contains udir_types uinst:rsync' && return 0
fi
return 1
}
function __uinst_rsync() {
# Déployer les fichiers de $srcdir avec rsync
# configuration locale de déploiement
if [ -n "$ddb_enable" -a -n "$UINST_STANDALONE" ]; then
local -a deploydb cmds tmpcmds
deploydb=(
"$scriptdir/lib/nulib/deploydb"
--missing-ok
${ddb_conf:+-c "$ddb_conf"}
-m uinst
--run -r uinst.query_xuinst "$script"
)
cmds=()
array_from_lines tmpcmds "$("${deploydb[@]}" "$srcdir" "" "$ddb_profile" "$@")"
array_extend cmds tmpcmds
if [ ${#cmds[*]} -gt 0 ]; then
if check_interaction -c; then
if [ ${#cmds[*]} -eq 1 ]; then
einfo "La commande suivante va être lancée:"
eecho "\$ $script --no-deploydb \\"
for cmd in "${cmds[0]}"; do
eecho " ${cmd#$script --no-deploydb }"
done
else
einfo "Les commandes suivantes seront lancées:"
eecho "\$ $script --no-deploydb \\"
for cmd in "${cmds[@]}"; do
eecho " ... ${cmd#$script --no-deploydb }"
done
fi
read -p "Confirmez ou attendez 4 secondes [On] " -t 4 r
if [ $? -gt 128 ]; then
echo # cosmetic
elif [ $? -le 128 -a -n "$r" ]; then
is_yes "$r" || die
fi
fi
r=0
for cmd in "${cmds[@]}"; do
einfo "$cmd"
eval "$cmd" || r=1
done
exit $r
elif [ "$ddb_profile" != "ALL" ]; then
ewarn "Aucune configuration locale de déploiement n'a été trouvée pour le profil $ddb_profile"
fi
fi
# initialiser les valeurs par défaut, mais penser à restaurer srcdir
force_rsync_options=(-av --exclude CVS --exclude .svn --exclude /.git/)
rsync_options=()
__uinst_defaultvars
__uinst_setvar srcdir
# puis charger les valeurs de $srcdir/.udir, mais penser à restaurer srcdir
eval "$(udir_dump "$srcdir")"
__uinst_setvar srcdir
# puis charger les valeurs de la ligne de commande
__uinst_setvars
# vérifier la destination
local __destdir_userhost __destdir_path __destdir_user __destdir_host
splitfsep2 "$destdir" : __destdir_userhost __destdir_path
splituserhost "$__destdir_userhost" __destdir_user __destdir_host
# si un hôte a été spécifié avec --host, utiliser cette valeur
if [ -n "$destdir_override_userhost" ]; then
local __override_user __override_host
splituserhost "$destdir_override_userhost" __override_user __override_host
[ -n "$__override_user" ] || __override_user="$__destdir_user"
if [ "$__override_host" == . ]; then
# forcer déploiement local
__override_user=
__override_host=
fi
__destdir_user="$__override_user"
__destdir_host="$__override_host"
fi
# vérifier s'il faut faire une copie distante ou locale
local __destdir_remote=
if [ -n "$__destdir_host" ]; then
if [ -n "$destdir_force_remote" ]; then
__destdir_remote=1
else
if [ "$__destdir_host" == localhost ]; then
:
elif [[ "$__destdir_host" == *.* ]]; then
[ "$__destdir_host" == "$MYHOST" ] || __destdir_remote=1
else
[ "$__destdir_host" == "$MYHOSTNAME" ] || __destdir_remote=1
fi
fi
if [ -z "$__destdir_remote" -a -n "$__destdir_user" ]; then
[ "$__destdir_user" == "$USER" ] || __destdir_remote=1
fi
fi
# corriger éventuellement destdir s'il contient un préfixe
if [ -n "$UINST_AUTOPREFIX" ] && has_prefix "$__destdir_path"; then
if [ -n "$__destdir_remote" ]; then
estep "Calcul des informations sur l'hôte distant"
eval "$SYSINFOSLOCALS"
local APACHE_PREFIXES_CHECK_OR_FIRST=1
compute_remote_sysinfos "${__destdir_user:+$__destdir_user@}$__destdir_host" "$destdir_ssh"
recompute_all_prefixes
fi
__destdir_path="$(expand_prefix "$__destdir_path")"
fi
# valeur finale de destdir
if [ -n "$__destdir_remote" ]; then
destdir="${__destdir_user:+$__destdir_user@}$__destdir_host:$__destdir_path"
else
destdir="$__destdir_path"
fi
# les variables de configure_variables ne sont pas prises en compte. pas la
# peine de les afficher
configure_variables=()
# afficher les valeurs dignes d'intérêt
__uinst_printmergedvars
if [ "$UINST_ACTION" == prepare-1s ]; then
# Faire la copie de travail pour le prédéploiement dans le répertoire
# spécifié
__uinst_prepare_workdir "$UINST_PREPARE_DIR" || return 1
[ -n "$UINST_PREPARE_ULIB" ] && __uinst_prepare_ulib
__uinst_prepare_conf
return 0
else
local srcdesc="$(ppath "$srcdir")"
if [ -n "${files[*]}" ]; then
srcdesc="$srcdesc/{$(array_join files ,)}"
fi
if [ -n "$__destdir_host" ]; then
ask_yesno "Synchroniser $srcdesc vers $(ppath "$destdir")?" O || return
else
ask_yesno "Synchroniser $srcdesc vers $(ppath "$destdir") sur $MYHOST?" O || return
fi
fi
cd "$srcdir" || return 1
if [ -n "$__destdir_remote" ]; then
# Déploiement distant, on laisse rsync gérer
:
else
# Déploiement local. S'assurer que le répertoire de destination existe
mkdir -p "$destdir" || return 1
fi
local -a cmd tmp_files actual_files copied_files
local file filename
local UTOOLS_USSH_RSYNC_SUPPORT=1; export UTOOLS_USSH_RSYNC_SUPPORT
cmd=(rsync ${destdir_ssh:+-e "$destdir_ssh"} "${force_rsync_options[@]}" "${rsync_options[@]}")
if [ -n "${files[*]}" ]; then
for file in "${files[@]}"; do
file="${file#/}" # les chemins sont toujours relatifs
if [ -e "$file" ]; then
tmp_files=("$file")
else
array_from_lines tmp_files "$(list_all . "$file")"
fi
array_extend actual_files tmp_files
done
for file in "${actual_files[@]}"; do
cmd=("${cmd[@]}" "$file")
filename="$(basename "$file")"
copied_files=("${copied_files[@]}" "$destdir/$filename")
done
else
cmd=("${cmd[@]}" ./)
array_from_lines actual_files "$(list_all . "*" ".*")"
for file in "${actual_files[@]}"; do
filename="$(basename "$file")"
copied_files=("${copied_files[@]}" "$destdir/$filename")
done
fi
cmd=("${cmd[@]}" "$destdir")
# Faire la synchro
"${cmd[@]}"
if [ -z "$__destdir_remote" ]; then
if [ -n "$owner" -a -n "${copied_files[*]}" ]; then
## Initialiser le propriétaire
estep "Initialisation du propriétaire à $owner"
for file in "${copied_files[@]}"; do
# ignorer les fichiers qui n'ont pas été copiés
[ -e "$file" ] || continue
chown -R "$owner" "$file" || return 1
done
fi
if [ -n "${modes[*]}" ]; then
## Initialiser les modes
for mode in "${modes[@]}"; do
file="${mode%:*}"
if [ "$file" != "$mode" ]; then
# une spécification de mode pour un fichier spécifique
mode="${mode##*:}"
estep "Initialisation du mode à $mode pour $file"
chmod "$mode" "$destdir/$file" || return 1
elif [ -n "${copied_files[*]}" ]; then
# une spécification de mode pour tous les fichiers déployés
estep "Initialisation du mode à $mode"
for file in "${copied_files[@]}"; do
# ignorer les fichiers qui n'ont pas été copiés
[ -e "$file" ] || continue
chmod -R "$mode" "$file" || return 1
done
fi
done
fi
fi
}
################################################################################
# uinst: legacy
function __uinst_check_legacy() {
# Vérifier si $1 est un répertoire à installer avec la version originale de
# uinst
if [ -d "$1" -a -f "$1/.udir" ]; then
udir_eval "$1" 'array_contains udir_types uinst:legacy' && return
fi
[ -d "$1" -a -f "$1/.uinst.conf" ]
}
function __uinst_migrate_legacy() {
local srcdir # XXX srcdir ne doit pas être écrasé, bien que .uinst.conf
# contienne la variable srcdir. Il faut donc protéger cette
# variable avec 'local srcdir'
local __uinst_srcdir="$1"
# initialiser les valeurs par défaut
update_inc=false
update_inc_options=
update_inc_args=.
configure_variables=dest
configure_dest_for=
config_scripts=
install_profiles=false
profiledir=lib/profile.d
bashrcdir=lib/bashrc.d
defaultdir=lib/default
copy_files=true
destdir=/usr/local
srcdir=.
files=
owner="root:"
modes="u=rwX,g=rX,o=rX"
root_scripts=
# puis charger les valeurs de $srcdir/.uinst.conf
# initialiser aussi UDIR_VARS et UDIR_ARRAYS. cela permettra de construire
# le fichier de configuration pour les scripts et le déploiement
if [ -f "$__uinst_srcdir/.uinst.conf" ]; then
# note: les regex qui sont entre "" au lieu de // le sont à cause d'un bug
# de awk sous macosx
source "$__uinst_srcdir/.uinst.conf"
eval "$(<"$__uinst_srcdir/.uinst.conf" filter_comment -m | awk 'BEGIN {
vars = "UDIR_VARS=("; first_var = 1;
arrays = "UDIR_ARRAYS=("; first_array = 1;
}
/^[ \t]*#/ { next }
$0 ~ /^[ \t]*[a-zA-Z_][a-zA-Z0-9_]*=\(/ {
match($0, /^[ \t]*[a-zA-Z_][a-zA-Z0-9_]*=\(/)
name = substr($0, RSTART, RLENGTH)
sub(/^([ \t]*)?/, "", name)
sub("=\\($", "", name)
if (first_array) first_array = 0
else arrays = arrays " "
arrays = arrays name
next
}
$0 ~ /^[ \t]*[a-zA-Z_][a-zA-Z0-9_]*=/ {
match($0, /^[ \t]*[a-zA-Z_][a-zA-Z0-9_]*=/)
name = substr($0, RSTART, RLENGTH)
sub(/^([ \t]*)?/, "", name)
sub("=$", "", name)
if (first_var) first_var = 0
else vars = vars " "
vars = vars name
next
}
END {
print vars ")"
print arrays ")"
}')"
else
UDIR_VARS=(copy_files destdir srcdir files owner modes update_inc update_inc_options update_inc_args configure_variables configure_dest_for config_scripts install_profiles profiledir bashrcdir defaultdir root_scripts)
UDIR_ARRAYS=()
fi
# traduire les valeurs à la mode udir.
#XXX à commenter tant que l'on ne fait pas clairement la différence entre
# srcdir, le répertoire qu'il faut *copier* et uinstdir (ou projdir), le
# répertoire qu'il faut déployer
#if [ "$srcdir" != "." ]; then
# __uinst_addvar srcdir "$(abspath "$srcdir" "$__uinst_srcdir")"
#fi
uinc="$update_inc"; \
unset update_inc; \
array_del UDIR_VARS update_inc; \
array_set UDIR_VARS uinc
uinc_options=($update_inc_options); \
unset update_inc_options; \
array_del UDIR_VARS update_inc_options; \
array_set UDIR_ARRAYS uinc_options
uinc_args=($update_inc_args); \
unset update_inc_args; \
array_del UDIR_VARS update_inc_args; \
array_set UDIR_ARRAYS uinc_args
for __uinst_a in configure_variables config_scripts root_scripts files; do
array_from_lines "$__uinst_a" "${!__uinst_a}"; \
array_del UDIR_VARS "$__uinst_a"; \
array_set UDIR_ARRAYS "$__uinst_a"
done
for __uinst_cv in "${configure_variables[@]}"; do
__uinst_cv="configure_${__uinst_cv}_for"
array_from_lines "$__uinst_cv" "${!__uinst_cv}"; \
array_del UDIR_VARS "$__uinst_cv"; \
array_set UDIR_ARRAYS "$__uinst_cv"
done
modes=($modes); \
array_del UDIR_VARS modes; \
array_set UDIR_ARRAYS modes
}
function __uinst_legacy() {
# Installer le répertoire $srcdir qui contient la configuration dans le
# fichier .uinst.conf
local uinst2s
__uinst_check_uinst2s || return 1
# charger les valeurs de $srcdir/.uinst.conf
__uinst_migrate_legacy "$srcdir"
# puis charger les valeurs de la ligne de commande
__uinst_setvars
# corriger éventuellement destdir
[ -n "$UINST_AUTOPREFIX" ] && destdir="$(expand_prefix "$destdir")"
# afficher les valeurs dignes d'intérêt
__uinst_printmergedvars
# puis lancer le déploiement
__uinst_udir2s
}
################################################################################
# uinst: python
function __uinst_check_python() {
# Vérifier si $1 est un répertoire d'un produit python à installer avec
# setup.py
[ -d "$1" -a -f "$1/setup.py" ]
}
function __uinst_python() {
# Installer le package python $srcdir
local uinst2s
__uinst_check_uinst2s uinst2s_python || return 1
if [ "$UINST_ACTION" == prepare-1s ]; then
# Faire la copie de travail pour le prédéploiement dans le répertoire
# spécifié
__uinst_prepare_workdir "$UINST_PREPARE_DIR" || return 1
[ -n "$UINST_PREPARE_ULIB" ] && __uinst_prepare_ulib
__uinst_prepare_conf
return 0
else
ask_yesno "Déployer $(ppath "$srcdir") sur $MYHOST?" O || return 1
UINST_ORIGSRC="$srcdir"
UINST_SRCDIR="$(abspath "$srcdir")"
fi
local __uinst_config __uinst_var
ac_set_tmpfile __uinst_config
for __uinst_var in srcdir; do
echo_setv "$__uinst_var" "${!__uinst_var}" >>"$__uinst_config"
done
echo_setv "UINST_ISTMPDIR" "$UINST_ISTMPDIR" >>"$__uinst_config"
echo_setv "UINST_ORIGSRC" "$UINST_ORIGSRC" >>"$__uinst_config"
echo_setv "UINST_SRCDIR" "$UINST_SRCDIR" >>"$__uinst_config"
echo_setv "ULIBDIR" "$ULIBDIR" >>"$__uinst_config"
echo_setv "UINST" "$UINST" >>"$__uinst_config"
runscript_as_root "$uinst2s" "$__uinst_config"
}
################################################################################
# uinst: archive
function __uinst_check_archive() {
# Vérifier si $1 est une archive installable avec uinst
is_archive "$1"
}
function __uinst_archname() {
# essayer de déterminer un nom de base pour le répertoire de destination
# d'une archive à décompresser: l'extension et le numéro de version sont
# supprimés du nom de l'archive
local archname="$(basename "$1")"
# supprimer l'extension
archname="${archname%.zip}"
archname="${archname%.tgz}"
archname="${archname%.tar.gz}"
archname="${archname%.tbz2}"
archname="${archname%.tar.bz2}"
archname="${archname%.tar}"
archname="${archname%.jar}"
archname="${archname%.war}"
# supprimer la version
archname="$(echo "$archname" | awk '{sub(/-[0-9]+(\.[0-9]+)*$/, ""); print}')"
# résultat
echo "${archname:-archive}"
}
function __uinst_archive() {
# Installer l'archive $srcdir. Elle est décompactée pour déterminer le type
# d'installation qu'il faut pour elle
if [ "$UINST_ACTION" == prepare-1s ]; then
# Décompacter l'archive dans le répertoire spécifié
UINST_TMPDIR="$UINST_PREPARE_DIR"
else
# Décompacter l'archive dans un répertoire temporaire
ac_set_tmpdir UINST_TMPDIR
UINST_ORIGSRC="$srcdir"
fi
estep "Décompactage d'une copie de travail dans $UINST_TMPDIR..."
local archdir="$UINST_TMPDIR/$(__uinst_archname "$srcdir")"
mkdir -p "$archdir" || return 1
extract_archive "$srcdir" "$archdir" || return 1
UINST_SRCDIR="$(abspath "$archdir")"
# Décomptacter l'archive dans un répertoire temporaire
# s'il n'y a qu'un seul répertoire dans l'archive, le considérer comme le
# répertoire à déployer
local -a contents_
array_lsall contents_ "$archdir"
if [ "${#contents_[*]}" -eq 1 ]; then
archdir="${contents_[0]}"
fi
UINST_ISTMPDIR=1
__uinst_addvarnf srcdir "$archdir"
__uinst_dispatch
}
################################################################################
# uinst: file
function __uinst_check_file() {
# Vérifier si $1 est un fichier installable avec uinst
[ -f "$1" ]
}
function __uinst_file() {
# Installer le fichier simple $srcdir
local uinst2s
__uinst_check_uinst2s || return 1
__uinst_defaultvars
__uinst_setvars
[ -n "$UINST_AUTOPREFIX" ] && destdir="$(expand_prefix "$destdir")"
__uinst_printmergedvars
if [ "$UINST_ACTION" == prepare-1s ]; then
# Faire la copie de travail pour le prédéploiement dans le répertoire
# spécifié
local srcname="$(basename "$srcdir")"
estep "Création d'une copie de travail dans $UINST_PREPARE_DIR..."
"${UINST_COPY_METHOD:-cpnovcs}" "$srcdir" "$UINST_PREPARE_DIR"
srcdir="$UINST_PREPARE_DIR/$srcname"
chmod +w "$srcdir" || return 1
[ -n "$UINST_PREPARE_ULIB" ] && __uinst_prepare_ulib
__uinst_prepare_conf
return 0
else
ask_yesno "Déployer $(ppath "$srcdir") dans $(ppath "$destdir")?" O || return 1
UINST_ORIGSRC="$srcdir"
UINST_SRCDIR="$(dirname "$(abspath "$srcdir")")"
fi
local __uinst_config __uinst_var
ac_set_tmpfile __uinst_config
for __uinst_var in copy_files destdir srcdir owner modes; do
echo_setv "$__uinst_var" "${!__uinst_var}" >>"$__uinst_config"
done
for __uinst_var in files modes; do
set_array_cmd "$__uinst_var" >>"$__uinst_config"
done
echo_setv "UINST_ISTMPDIR" "$UINST_ISTMPDIR" >>"$__uinst_config"
echo_setv "UINST_ORIGSRC" "$UINST_ORIGSRC" >>"$__uinst_config"
echo_setv "UINST_SRCDIR" "$UINST_SRCDIR" >>"$__uinst_config"
echo_setv "ULIBDIR" "$ULIBDIR" >>"$__uinst_config"
echo_setv "UINST" "$UINST" >>"$__uinst_config"
runscript_as_root "$uinst2s" "$__uinst_config"
}
################################################################################
# uinst2s
function __uinst2s_copy_files() {
# Copier les fichiers files de srcdir dans destdir
# Cette fonction est utilisée par le script uinst2s
srcname="$(basename "$srcdir")"
destdir="$(abspath "$destdir")"
dest="$destdir/$srcname"
copied_files=()
# pour la copie "atomique" du répertoire de destination (en réalité, on
# cherche à minimiser le temps d'indisponibilité du répertoire destination)
atomic=
actualdest=
if [ -f "$srcdir" ]; then
## Copie d'un fichier dans un répertoire
if [ ! -d "$destdir" ]; then
estep "Création de $destdir"
mkdir -p "$destdir" || return 1
fi
estep "Copie de $(ppath "$srcdir") dans $destdir"
cpdir "$srcdir" "$destdir" || return 1
copied_files=("${copied_files[@]}" "$destdir/$(basename "$srcdir")")
elif [ -d "$srcdir" ]; then
## Copie d'un répertoire ou d'une partie de son contenu dans un
## répertoire de destination
if [ -z "${files[*]}" ]; then
# On n'a pas spécifié de liste de fichiers. C'est tout le répertoire
# source qui est copié, et il remplace la destination.
if [ -d "$dest" ]; then
# Le répertoire existe déjà. Tenter de faire une copie la plus
# atomique possible: déployer dans un répertoire temporaire, qui
# sera renommé vers la destination au dernier moment
eimportant "Le répertoire destination $dest sera écrasé"
if is_interaction -C; then
ebegin "Attente de 3 secondes"
sleep 1; edot
sleep 1; edot
sleep 1; edot
eend
fi
atomic=1
actualdest="$dest"
dest="$actualdest.copy$$"
i=0
while [ -d "$dest" ]; do
dest="$actualdest.copy$$-$i"
i=$(($i + 1))
done
else
enote "Le répertoire destination est $dest"
fi
mkdir -p "$dest" || return 1
estep "Copie de $(ppath "$srcdir")"
cpdir "$srcdir" "$dest" || return 1
copied_files=("${copied_files[@]}" "$dest")
else
# On a spécifié une liste de fichiers. Seuls ces fichiers sont
# copiés, et le répertoire de destination n'est pas écrasé
enote "La copie se fera dans $destdir"
mkdir -p "$destdir" || return 1
for file in "${files[@]}"; do
estep "Copie de $file"
if [ -e "$srcdir/$file" ]; then
# fichier existant
actual_files=("$file")
wildcards=
else
# fichier non existant: c'est peut-être une spécification de
# fichier avec des wildcards
array_from_lines actual_files "$(list_all "$srcdir" "$file")"
wildcards=1
fi
local srcfile srcfilename
for file in "${actual_files[@]}"; do
srcfile="$srcdir/$file"
srcfilename="$(basename "$file")"
[ -n "$wildcards" ] && echo "... $file" 1>&2
if [ -d "$srcfile" ]; then
cpdir "$srcfile" "$destdir/$srcfilename" || return 1
else
cpdir "$srcfile" "$destdir" || return 1
fi
copied_files=("${copied_files[@]}" "$destdir/$srcfilename")
done
done
fi
else
ewarn "$srcdir: fichier ignoré"
fi
if [ -n "$owner" -a -n "${copied_files[*]}" ]; then
## Initialiser le propriétaire
estep "Initialisation du propriétaire à $owner"
chown -R "$owner" "${copied_files[@]}" || return 1
fi
if [ -n "${modes[*]}" ]; then
## Initialiser les modes
for mode in "${modes[@]}"; do
file="${mode%:*}"
if [ "$file" != "$mode" ]; then
# une spécification de mode pour un fichier spécifique
mode="${mode##*:}"
estep "Initialisation du mode à $mode pour $file"
if [ -z "${files[*]}" ]; then
chmod "$mode" "$dest/$file" || return 1
else
chmod "$mode" "$destdir/$file" || return 1
fi
elif [ -n "${copied_files[*]}" ]; then
# une spécification de mode pour tous les fichiers déployés
estep "Initialisation du mode à $mode"
chmod -R "$mode" "${copied_files[@]}" || return 1
fi
done
fi
if [ -n "$atomic" ]; then
tmpdest="$actualdest.tmp$$"
i=0
while [ -d "$tmpdest" ]; do
tmpdest="$actualdest.tmp$$-$i"
i=$(($i + 1))
done
estep "Installation du nouveau répertoire"
mv "$actualdest" "$tmpdest" &&
mv "$dest" "$actualdest" || return 1
estep "Suppression de l'ancien répertoire"
rm -rf "$tmpdest" || return 1
fi
}
function __uinst2s_root_scripts() {
# Lancer les scripts de root_scripts avec les arguments de cette fonction
if is_yes "$copy_files"; then
if [ -d "$dest" ]; then
cd "$dest" || return 1
else
cd "$destdir" || return 1
fi
fi
for root_script in "${root_scripts[@]}"; do
etitle "$root_script" \
"${BASH:-/bin/sh}" "$srcdir/$root_script" "$@"
done
}
function __uinst2s_python_setup() {
# Installer le package python
local PYTHON; progexists python2 && PYTHON=python2 || PYTHON=python
cd "$srcdir" && "$PYTHON" setup.py install
}