##@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 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, 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 -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 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' \ -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_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 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 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_LOCAL_PROFILES" "$UINST_LOCAL_PROFILES" >>"$__uinst_config" 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" 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 # 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 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" 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 }