##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
## Fonctions de base: outils divers
##@cooked nocomments
##@include base.args
uprovide base.tools
urequire base.args #XXX il manque des dépendances!

function base_umove() {
# Outil de haut niveau pour déplacer un fichier ou un lien. Si c'est un lien qui
# est déplacé, la destination du lien est mise à jour si elle est relative.
# l'option '-d UPDATEDIR' permet de spécifier un répertoire dans lequel tous les
# liens qui pointent vers le fichier déplacé sont mis à jour si le déplacement
# du fichier se fait avec succès.
    local -a args
    local updatedir
    args=(-d:,--updatedir: .)
    parse_args_check "$@" || return; set -- "${args[@]}"

    eerror_unless [ -z "$updatedir" -o -d "$updatedir" ] "$updatedir: doit être un répertoire" || return
    eerror_if [ $# -eq 0 ] "Vous devez spécifier les fichiers à déplacer" || return
    eerror_if [ $# -eq 1 ] "Vous devez spécifier la destination" || return

    local -a srcs
    local src dest

    srcs=("$@")
    setx dest=last_value srcs
    array_del_last srcs

    if [ $# -eq 2 ]; then
        # S'il n'y a que deux arguments, permettre que le deuxième argument ne
        # soit pas un répertoire
        if [ -d "$dest" ]; then
            : # ce cas sera traité ci-dessous
        elif [ -e "$dest" ]; then
            eerror "$dest: refus d'écraser la destination"
            return 1
        else
            src="${srcs[0]}"
            if [ -n "$updatedir" ]; then
                if [ -L "$src" ]; then
                    ldest="$(readlinka "$src")"
                    array_find_links update_links "$ldest" "$updatedir"
                else
                    array_find_links update_links "$src" "$updatedir"
                fi
                move_file "$src" "$dest" "${update_links[@]}"
            else
                move_link "$src" "$dest"
            fi
            return $?
        fi
    fi

    # S'il y a plus de deux arguments, il FAUT que dest soit un répertoire
    [ -d "$dest" ] || {
        eerror "$dest: doit être un répertoire"
        return 1
    }
    local r=0
    for src in "${srcs[@]}"; do
        if [ -n "$updatedir" ]; then
            if [ -L "$src" ]; then
                move_link "$src" "$dest" || r=$?
            else
                array_find_links update_links "$src" "$updatedir"
                move_file "$src" "$dest" "${update_links[@]}" || r=$?
            fi
        else
            move_link "$src" "$dest" || r=$?
        fi
    done
    return $r
}

function base_udelete() {
# Outil de haut niveau pour supprimer un fichier ou un lien. Si on doit
# supprimer un fichier, et que l'option '-d UPDATEDIR' est spécifiée, et que des
# liens du répertoire UPDATEDIR pointent vers le fichier supprimé, ces liens
# sont supprimés aussi.
    local -a args
    local updatedir
    args=(-d:,--updatedir: .)
    parse_args_check "$@" || return; set -- "${args[@]}"

    eerror_unless [ -z "$updatedir" -o -d "$updatedir" ] "$updatedir: doit être un répertoire" || return
    eerror_if [ $# -eq 0 ] "Vous devez spécifier les fichiers à supprimer" || return

    local file r=0
    for file in "$@"; do
        if [ -n "$updatedir" ]; then
            if [ -L "$file" ]; then
                rm "$file" || r=$?
            else
                array_find_links update_links "$file" "$updatedir"
                rm "$file" "${update_links[@]}" || r=$?
            fi
        else
            rm "$file" || r=$?
        fi
    done
    return $r
}

function base_ucopy() {
# Outil de haut niveau pour copier un fichier ou un lien. Si c'est un lien qui
# est copié, la destination du lien est mise à jour si elle est relative.
    eerror_if [ $# -eq 0 ] "Vous devez spécifier les fichiers à copier" || return
    eerror_if [ $# -eq 1 ] "Vous devez spécifier la destination" || return

    local -a srcs
    local src dest

    srcs=("$@")
    setx dest=last_value srcs
    array_del_last srcs

    if [ $# -eq 2 ]; then
        # S'il n'y a que deux arguments, permettre que le deuxième argument ne
        # soit pas un répertoire
        if [ -d "$dest" ]; then
            : # ce cas sera traité ci-dessous
        elif [ -e "$dest" ]; then
            eerror "$dest: refus d'écraser la destination"
            return 1
        else
            src="${srcs[0]}"
            copy_link "$src" "$dest"
            return $?
        fi
    fi

    # S'il y a plus de deux arguments, il FAUT que dest soit un répertoire
    [ -d "$dest" ] || {
        eerror "$dest: doit être un répertoire"
        return 1
    }
    local r=0
    for src in "${srcs[@]}"; do
        copy_link "$src" "$dest" || r=$?
    done
    return $r
}