##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 ## Gestion de la mise à jour des fichiers de ~/etc/{profile.d,bashrc.d,default} ##@cooked nocomments ##@require base ##@require uenv uprovide uenv_update urequire base uenv function __uenv_move_after() { # Dans le fichier $1, déplacer la ligne $2 après la ligne commençant par # l'expression régulière '^$3:' # Si la ligne $2 n'existe pas, ne rien faire # Si la ligne $3 n'existe pas ou vaut '*', mettre la ligne $2 en dernier. # Si $4 est spécifié, l'utiliser comme fichier temporaire. local tmpfile="$4" [ -n "$tmpfile" ] || ac_set_tmpfile tmpfile # XXX Il faudrait quoter $3 pour éviter les caractères spéciaux de grep! if quietgrep -F "$2" "$1"; then local re_after="$3" [ "$re_after" != "*" ] && re_after="^$re_after:" if [ "$re_after" != "*" ] && quietgrep "$re_after" "$1"; then awkrun line="$2" re_after="$re_after" ' BEGIN { found_line = 0 found_after = 0 } ! found_line && $0 == line { found_line = 1 if (! found_after) { next } } ! found_after && $0 ~ re_after { found_after = 1 if (found_line) { # si nous avons trouvé la ligne avant re_after, la mettre juste après # sinon, pas la peine de faire de modification print print line next } } { print } END { if (! found_after && re_after == "*") { if (found_line) { print line } } }' <"$1" >"$tmpfile" && cat "$tmpfile" >"$1" else grep -vF "$2" "$1" >"$tmpfile" echo "$2" >>"$tmpfile" cat "$tmpfile" >"$1" fi fi } function __uenv_move_before() { # Dans le fichier $1, déplacer la ligne $2 avant la ligne commençant par # l'expression régulière '^$3:' # Si la ligne $2 n'existe pas, ne rien faire # Si la ligne $3 n'existe pas ou vaut '*', mettre la ligne $2 en premier. # Si $4 est spécifié, l'utiliser comme fichier temporaire. local tmpfile="$4" [ -n "$tmpfile" ] || ac_set_tmpfile tmpfile # XXX Il faudrait quoter $3 pour éviter les caractères spéciaux de grep! if quietgrep -F "$2" "$1"; then local re_before="$3" [ "$re_before" != "*" ] && re_before="^$re_before:" if [ "$re_before" != "*" ] && quietgrep "$re_before" "$1"; then awkrun line="$2" re_before="$re_before" ' BEGIN { found_line = 0 found_before = 0 } ! found_line && $0 == line { found_line = 1 if (found_before) { next } } ! found_before && ($0 ~ re_before || re_before == "*") { found_before = 1 if (! found_line) { print line print next } } { print } ' <"$1" >"$tmpfile" && cat "$tmpfile" >"$1" else echo "$2" >"$tmpfile" grep -vF "$2" "$1" >>"$tmpfile" cat "$tmpfile" >"$1" fi fi } function uenv_update_dir() { # Mettre à jour l'ordre de chargement pour le répertoire $1 qui contient des # fichiers de profil pour le shell. L'ordre dans lequel le fichiers de # profil doivent être chargé est écrit dans le fichier $1/.source_in_order # Si $2 est spécifié, il s'agit d'un fichier temporaire utilisé pour les # calculs de l'ordre des chargements. # $3(=$1) est le répertoire de destination. Si $1 est un répertoire de # préparation temporaire, on peut spécifier grâce à $3 quel est le # répertoire final après préparation. # S'ils sont spécifiés, les arguments $4..* sont des répertoires contenant # des fichiers de profils supplémentaires qu'il faut considérer aussi. Dans # ce cas, $3 est ignoré. local dir="$(abspath "$1")"; shift local tmpfile="$1"; shift local destdir="${1:-$dir}"; shift local sio="$dir/.source_in_order" local before after file filename local -a files [ -n "$tmpfile" ] || ac_set_tmpfile tmpfile [ $# -gt 0 ] && destdir= set -- "$dir" "$@" local __uname_system="$UNAME_SYSTEM" local __myhostname="$MYHOSTNAME" >"$sio" for dir in "$@"; do [ -n "$dir" ] || continue for file in "$dir/"*; do [ -f "$file" ] || continue files=("${files[@]}" "$file") filename="$(basename -- "$file")" __uenv_check_file "$dir" "$filename" && echo "$filename:$file" >>"$sio" done done # traiter d'abord les fichiers qui ont '@before *' ou '@after *' local -a nfiles for file in "${files[@]}"; do filename="$(basename -- "$file")" before="$(<"$file" awk '$0 ~ /^##@before / { print $2; exit 0 }')" if [ "$before" == "*" ]; then __uenv_move_before "$sio" "$filename:$file" "$before" "$tmpfile" else array_set nfiles "$file" fi after="$(<"$file" awk '$0 ~ /^##@after / { print $2; exit 0 }')" if [ "$after" == "*" ]; then __uenv_move_after "$sio" "$filename:$file" "$after" "$tmpfile" else array_set nfiles "$file" fi done # Ensuite traiter les autres fichiers. # L'opération est faite en deux temps parce que si A est avant B, et que B # est avant *, si A est traité avant B, A risque de se trouver après B si B # est déplacé au début de la liste. for file in "${nfiles[@]}"; do filename="$(basename -- "$file")" before="$(<"$file" awk '$0 ~ /^##@before / { print $2; exit 0 }')" [ -n "$before" -a "$before" != "*" ] && __uenv_move_before "$sio" "$filename:$file" "$before" "$tmpfile" after="$(<"$file" awk '$0 ~ /^##@after / { print $2; exit 0 }')" [ -n "$after" -a "$after" != "*" ] && __uenv_move_after "$sio" "$filename:$file" "$after" "$tmpfile" done awkrun destdir="$destdir" '{ pos = match($0, /:/) if (pos != 0) { filename = substr($0, 1, pos - 1) file = substr($0, pos + 1) if (destdir != "") { print "source " destdir "/" filename } else { print "source " file } } else { print "source " destdir "/" $0 } }' <"$sio" >"$tmpfile" && cat "$tmpfile" >"$sio" } function uenv_set_destdirs() { if [ "$1" == --local-profiles ]; then local hostname="${HOSTNAME%%.*}" profiledestdir="$HOME/etc/profile.${hostname}.d" bashrcdestdir="$HOME/etc/bashrc.${hostname}.d" defaultdestdir="$HOME/etc/default.${hostname}" shared_profiledestdir="$HOME/etc/profile.d" shared_bashrcdestdir="$HOME/etc/bashrc.d" shared_defaultdestdir="$HOME/etc/default" else profiledestdir="$HOME/etc/profile.d" bashrcdestdir="$HOME/etc/bashrc.d" defaultdestdir="$HOME/etc/default" shared_profiledestdir= shared_bashrcdestdir= shared_defaultdestdir= fi } function uenv_sourced_in() { # vérifier que l'un des fichiers $2..$* est sourcé dans $1 local src="$1"; shift local file for file in "$@"; do grep -q "\\.[ \\t]*$file\$" "$src" && return 0 grep -q "source[ \\t]*$file\$" "$src" && return 0 done return 1 } function uenv_configure_profiles() { local destdir="$1" local LEGACY_PROFILE="$HOME/.profile" local PROFILE="$HOME/.bash_profile" local BASHRC="$HOME/.bashrc" if [ ! -f "$PROFILE" ]; then echo "# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 if [ -f ~/.bashrc ]; then . ~/.bashrc fi" >"$PROFILE" fi if [ ! -f "$BASHRC" ]; then touch "$BASHRC" fi if [ -f "$LEGACY_PROFILE" ]; then if ! uenv_sourced_in "$PROFILE" "~/.profile"; then ewarn "\ ~/.profile existe, il contient peut-être des instructions utiles. Si c'est le cas, il faut décommenter la ligne dans ~/.bash_profile qui source ~/.profile" estep "Configuration de l'inclusion de ~/.profile dans $PROFILE" echo >>"$PROFILE" " # decommenter si ~/.profile contient des commandes utiles #[ -f ~/.profile ] && source ~/.profile" fi fi if ! uenv_sourced_in "$PROFILE" "$destdir/profile"; then estep "Configuration de l'inclusion de $destdir/profile" echo >>"$PROFILE" " # source $destdir/profile.d scripts [ -f \"$destdir/profile\" ] && source $destdir/profile" fi if ! uenv_sourced_in "$BASHRC" "$destdir/bashrc"; then estep "Configuration de l'inclusion de $destdir/bashrc" echo >>"$BASHRC" " # source $destdir/bashrc.d scripts [ -f \"$destdir/bashrc\" ] && source $destdir/bashrc" fi } function uenv_install_profiles() { local local_profiles if [ "$1" == --local-profiles ]; then local_profiles=1 shift fi local projdir="$1" profiledir="$2" bashrcdir="$3" defaultdir="$4" local tmpfile shared local prefix envsrcdir envdestdir shadestdir envfiles envfile envsrc envdest shadest local shared_profiledestdir shared_bashrcdestdir shared_defaultdestdir local profiledestdir bashrcdestdir defaultdestdir uenv_set_destdirs ${local_profiles:+--local-profiles} ac_set_tmpfile tmpfile for prefix in profile bashrc default; do envsrcdir="${prefix}dir"; envsrcdir="$projdir/${!envsrcdir}" envdestdir="${prefix}destdir"; envdestdir="${!envdestdir}" shadestdir="shared_${prefix}destdir"; shadestdir="${!shadestdir}" [ -n "$envsrcdir" -a -d "$envsrcdir" ] || continue mkdir -p "$envdestdir" [ -n "$shadestdir" ] && mkdir -p "$shadestdir" array_from_lines envfiles "$(list_files "$envsrcdir")" for envfile in "${envfiles[@]}"; do envsrc="$envsrcdir/$envfile" if [ "${envfile%.shared}" != "$envfile" ]; then envfile="${envfile%.shared}" shared=1 else shared= fi if [ -n "$shadestdir" ]; then if [ -n "$shared" ]; then # si fichier partagé, toujours le copier dans le répertoire # des fichiers partagés envdest="$shadestdir/$envfile" else envdest="$envdestdir/$envfile" shadest="$shadestdir/$envfile" if [ ! -f "$envdest" -a -f "$shadest" ]; then # Si déjà installé en partagé, continuer à mettre à jour ce # fichier-là envdest="$shadest" fi fi else envdest="$envdestdir/$envfile" fi local actual_envdestdir="$(dirname -- "$envdest")" if [ ! -f "$envdest" ]; then estep "Installation du profil par défaut $envfile dans $(ppath "$actual_envdestdir")" /bin/cp -f "$envsrc" "$envdest" elif [ "$prefix" == "default" ]; then # ne jamais mettre à jour dans default if testdiff "$envdest" "$envsrc"; then estepi "Le profil $(ppath "$envdest") a été conservé" fi elif endswith "$envfile" ".userconf"; then # ne jamais mettre à jour les fichiers .userconf if testdiff "$envdest" "$envsrc"; then estepi "Le profil $(ppath "$envdest") a été conservé" fi elif testdiff "$envdest" "$envsrc"; then estep "Le profil par défaut $envfile dans $(ppath "$actual_envdestdir") a été modifié" if show_info; then eecho "Voici les différences détectées:" eecho "" diff -u "$envdest" "$envsrc" 1>&2 eecho "" fi if ask_yesno "Faut-il remplacer $(ppath "$envdest") par le profil par défaut?" O; then /bin/cp -f "$envsrc" "$envdest" fi fi done if [ "$prefix" != "default" ]; then estep "Mise à jour de l'ordre de lecture de $(ppath "$envdestdir")" uenv_update_dir "$envdestdir" "$tmpfile" "" "$shadestdir" fi done ac_clean "$tmpfile" }