263 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
			
		
		
	
	
			263 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
##@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 $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 $2 et $3 pour éviter les caractères spéciaux de
 | 
						|
    # grep!
 | 
						|
    if quietgrep "^$2$" "$1"; then
 | 
						|
        if [ "$3" != "*" ] && quietgrep "^$3$" "$1"; then
 | 
						|
            awkrun line="$2" after="$3" '
 | 
						|
BEGIN {
 | 
						|
    found_line = 0
 | 
						|
    found_after = 0
 | 
						|
}
 | 
						|
! found_line && $0 == line {
 | 
						|
    found_line = 1
 | 
						|
    if (! found_after) {
 | 
						|
        next
 | 
						|
    }
 | 
						|
}
 | 
						|
! found_after && $0 == after {
 | 
						|
    found_after = 1
 | 
						|
    if (found_line) {
 | 
						|
        # si nous avons trouvé la ligne avant after, la mettre juste après
 | 
						|
        # sinon, pas la peine de faire de modification
 | 
						|
        print
 | 
						|
        print line
 | 
						|
        next
 | 
						|
    }
 | 
						|
}
 | 
						|
{ print }
 | 
						|
END {
 | 
						|
    if (! found_after && after == "*") {
 | 
						|
        if (found_line) {
 | 
						|
            print line
 | 
						|
        }
 | 
						|
    }
 | 
						|
}' <"$1" >"$tmpfile" &&
 | 
						|
            cat "$tmpfile" >"$1"
 | 
						|
        else
 | 
						|
            grep -v "^$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 $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 $2 et $3 pour éviter les caractères spéciaux de
 | 
						|
    # grep!
 | 
						|
    if quietgrep "^$2$" "$1"; then
 | 
						|
        if [ "$3" != "*" ] && quietgrep "^$3$" "$1"; then
 | 
						|
            awkrun line="$2" before="$3" '
 | 
						|
BEGIN {
 | 
						|
    found_line = 0
 | 
						|
    found_before = 0
 | 
						|
}
 | 
						|
! found_line && $0 == line {
 | 
						|
    found_line = 1
 | 
						|
    if (found_before) {
 | 
						|
        next
 | 
						|
    }
 | 
						|
}
 | 
						|
! found_before && ($0 == before || before == "*") {
 | 
						|
    found_before = 1
 | 
						|
    if (! found_line) {
 | 
						|
        print line
 | 
						|
        print
 | 
						|
        next
 | 
						|
    }
 | 
						|
}
 | 
						|
{ print }
 | 
						|
' <"$1" >"$tmpfile" &&
 | 
						|
            cat "$tmpfile" >"$1"
 | 
						|
        else
 | 
						|
            echo "$2" >"$tmpfile"
 | 
						|
            grep -v "^$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.
 | 
						|
    local dir="$(abspath "$1")"
 | 
						|
    local destdir="${3:-$dir}"
 | 
						|
    local tmpfile="$2"
 | 
						|
    [ -n "$tmpfile" ] || ac_set_tmpfile tmpfile
 | 
						|
    local sio="$dir/.source_in_order"
 | 
						|
    local before after file
 | 
						|
    local -a files
 | 
						|
 | 
						|
    local __uname_system="$UNAME_SYSTEM"
 | 
						|
    local __myhostname="$MYHOSTNAME"
 | 
						|
    >"$sio"
 | 
						|
    for file in "$dir/"*; do
 | 
						|
        file="$(basename "$file")"
 | 
						|
        files=("${files[@]}" "$file")
 | 
						|
        __uenv_check_file "$dir" "$file" && echo "$file" >>"$sio"
 | 
						|
    done
 | 
						|
 | 
						|
    # traiter d'abord les fichiers qui ont '@before *' ou '@after *'
 | 
						|
    local -a nfiles
 | 
						|
    for file in "${files[@]}"; do
 | 
						|
        before="$(<"$dir/$file" awk '$0 ~ /^##@before / { print $2; exit 0 }')"
 | 
						|
        if [ "$before" == "*" ]; then
 | 
						|
            __uenv_move_before "$sio" "$file" "$before" "$tmpfile"
 | 
						|
        else
 | 
						|
            array_set nfiles "$file"
 | 
						|
        fi
 | 
						|
        after="$(<"$dir/$file" awk '$0 ~ /^##@after / { print $2; exit 0 }')"
 | 
						|
        if [ "$after" == "*" ]; then
 | 
						|
            __uenv_move_after "$sio" "$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
 | 
						|
        before="$(<"$dir/$file" awk '$0 ~ /^##@before / { print $2; exit 0 }')"
 | 
						|
        [ -n "$before" -a "$before" != "*" ] && __uenv_move_before "$sio" "$file" "$before" "$tmpfile"
 | 
						|
        after="$(<"$dir/$file" awk '$0 ~ /^##@after / { print $2; exit 0 }')"
 | 
						|
        [ -n "$after" -a "$after" != "*" ] && __uenv_move_after "$sio" "$file" "$after" "$tmpfile"
 | 
						|
    done
 | 
						|
 | 
						|
    awkrun destdir="$destdir" '{ print "source " destdir "/" $0 }' <"$sio" >"$tmpfile" &&
 | 
						|
    cat "$tmpfile" >"$sio"
 | 
						|
}
 | 
						|
 | 
						|
function uenv_set_destdirs() {
 | 
						|
    profiledestdir="$HOME/etc/profile.d"
 | 
						|
    bashrcdestdir="$HOME/etc/bashrc.d"
 | 
						|
    defaultdestdir="$HOME/etc/default"
 | 
						|
}
 | 
						|
 | 
						|
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 projdir="$1" profiledir="$2" bashrcdir="$3" defaultdir="$4"
 | 
						|
    local tmpfile
 | 
						|
    local prefix envsrcdir envdestdir envfiles envfile envsrc envdest
 | 
						|
    local profiledestdir bashrcdestdir defaultdestdir
 | 
						|
    uenv_set_destdirs
 | 
						|
    
 | 
						|
    ac_set_tmpfile tmpfile
 | 
						|
    for prefix in profile bashrc default; do
 | 
						|
        envsrcdir="${prefix}dir"; envsrcdir="$projdir/${!envsrcdir}"
 | 
						|
        envdestdir="${prefix}destdir"; envdestdir="${!envdestdir}"
 | 
						|
        [ -n "$envsrcdir" -a -d "$envsrcdir" ] || continue
 | 
						|
 | 
						|
        array_from_lines envfiles "$(list_files "$envsrcdir")"
 | 
						|
        for envfile in "${envfiles[@]}"; do
 | 
						|
            envsrc="$envsrcdir/$envfile"
 | 
						|
            envdest="$envdestdir/$envfile"
 | 
						|
            
 | 
						|
            mkdir -p "$envdestdir"
 | 
						|
            if [ ! -f "$envdest" ]; then
 | 
						|
                estep "Installation du profil par défaut $envfile dans $(ppath "$envdestdir")"
 | 
						|
                /bin/cp -f "$envsrc" "$envdestdir"
 | 
						|
            elif [ "$prefix" != "default" ] && ! endswith "$envfile" ".userconf" && testdiff "$envdest" "$envsrc"; then
 | 
						|
                estep "Le profil par défaut $envfile dans $(ppath "$envdestdir") a été modifié"
 | 
						|
                if show_info; then
 | 
						|
                    eecho "Voici les différences détectées:"
 | 
						|
                    eecho ""
 | 
						|
                    diff -u "$envdest" "$envsrcdir" 1>&2
 | 
						|
                    eecho ""
 | 
						|
                fi
 | 
						|
                
 | 
						|
                if ask_yesno "Faut-il remplacer $(ppath "$envdestdir/$envfile") par le profil par défaut?" O; then
 | 
						|
                    /bin/cp -f "$envsrc" "$envdestdir"
 | 
						|
                fi
 | 
						|
            fi
 | 
						|
        done
 | 
						|
 | 
						|
        if [ "$prefix" != "default" ]; then
 | 
						|
            estep "Mise à jour de l'ordre de lecture de $(ppath "$envdestdir")"
 | 
						|
            uenv_update_dir "$envdestdir" "$tmpfile"
 | 
						|
        fi
 | 
						|
    done
 | 
						|
    ac_clean "$tmpfile"
 | 
						|
}
 |