##@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 -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 local srcdir local -a files local owner local -a modes local -a root_scripts local uinst2s 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] 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. Equivalent à l'option destdir=\"/path/to/destdir\" -a (par défaut) Si la source n'est pas spécifiée, déterminer le répertoire à déployer automatiquement. --no-auto Ne pas déterminer automatiquement le répertoire à déployer. --prefix (par défaut) Corriger les chemins srcdir et destdir qui commencent par des préfixes valides. 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. -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 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_' \ -a,--auto UINST_AUTOSRCDIR=1 \ --no-auto UINST_AUTOSRCDIR= \ --prefix UINST_AUTOPREFIX=1 \ --no-prefix UINST_AUTOPREFIX= \ --include-vcs UINST_COPY_METHOD=cpdir \ -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_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' 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_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[@]}" "$(set_var_cmd "$__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" 'set_var_cmd udir_desc "$udir_desc"; set_var_cmd 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=$(quoted_arg "$udir_desc")" "udir_note=$(quoted_arg "$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=($(quoted_arg "${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 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 "Le répertoire '$(ppath "$srcdir")' a été calculé automatiquement. Voulez-vous le déployer?" X || 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 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 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 "$(set_var_cmd "$1" "$2")" set_var "$1" "$2" if [ "$1" == "MYHOST" ]; then # cas particulier: initialiser aussi MYHOSTNAME set_var "MYHOSTNAME" "${2%%.*}" array_add UINST_CONFIG_VARCMDS "$(set_var_cmd "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 set_var_cmd 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" set_var_cmd ABORT "$__uinst_abort" >>"$__uinst_config" set_var_cmd CONFIG "$__uinst_updateconfig" >>"$__uinst_config" set_var_cmd __verbosity "$__verbosity" >>"$__uinst_config" set_var_cmd __interaction "$__interaction" >>"$__uinst_config" for __uinst_var in "${__uinst_vars[@]}"; do set_var_cmd "$__uinst_var" "${!__uinst_var}" >>"$__uinst_config" done for __uinst_var in "${__uinst_arrays[@]}"; do set_array_cmd "$__uinst_var" >>"$__uinst_config" done set_var_cmd "UINST_ISTMPDIR" "$UINST_ISTMPDIR" >>"$__uinst_config" set_var_cmd "UINST_ORIGSRC" "$UINST_ORIGSRC" >>"$__uinst_config" set_var_cmd "UINST_SRCDIR" "$UINST_SRCDIR" >>"$__uinst_config" set_var_cmd "ULIBDIR" "$ULIBDIR" >>"$__uinst_config" set_var_cmd "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. set_var_cmd "FORCED_ULIBDIR" "$ULIBDIR" >>"$__uinst_config" set_var_cmd "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" \ uenv_install_profiles "$srcdir" "$profiledir" "$bashrcdir" "$defaultdir" 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 # 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 # corriger éventuellement destdir [ -n "$UINST_AUTOPREFIX" ] && destdir="$(expand_prefix "$destdir")" # 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 ask_yesno "Synchroniser $srcdesc vers $(ppath "$destdir") sur $MYHOST?" O || return fi cd "$srcdir" || return 1 local localsync=1 if [[ "$destdir" == *:* ]]; then # Déploiement distant, on laisse rsync gérer localsync= 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 cmd=(rsync "${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 [ -n "$localsync" ]; then 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" 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" chmod -R "$mode" "${copied_files[@]}" || return 1 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 set_var_cmd "$__uinst_var" "${!__uinst_var}" >>"$__uinst_config" done set_var_cmd "UINST_ISTMPDIR" "$UINST_ISTMPDIR" >>"$__uinst_config" set_var_cmd "UINST_ORIGSRC" "$UINST_ORIGSRC" >>"$__uinst_config" set_var_cmd "UINST_SRCDIR" "$UINST_SRCDIR" >>"$__uinst_config" set_var_cmd "ULIBDIR" "$ULIBDIR" >>"$__uinst_config" set_var_cmd "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 set_var_cmd "$__uinst_var" "${!__uinst_var}" >>"$__uinst_config" done for __uinst_var in files modes; do set_array_cmd "$__uinst_var" >>"$__uinst_config" done set_var_cmd "UINST_ISTMPDIR" "$UINST_ISTMPDIR" >>"$__uinst_config" set_var_cmd "UINST_ORIGSRC" "$UINST_ORIGSRC" >>"$__uinst_config" set_var_cmd "UINST_SRCDIR" "$UINST_SRCDIR" >>"$__uinst_config" set_var_cmd "ULIBDIR" "$ULIBDIR" >>"$__uinst_config" set_var_cmd "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 cd "$srcdir" && python setup.py install }