Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
[script] gerer son fichier world avec eworld
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index French
View previous topic :: View next topic  
Author Message
kaworu
Guru
Guru


Joined: 07 Dec 2005
Posts: 450

PostPosted: Tue Jan 23, 2007 3:40 pm    Post subject: [script] gerer son fichier world avec eworld Reply with quote

Introduction
Salut !
depuis que je suis sous Gentoo j'aime bien avoir un contrôle sur mon fichier /var/lib/portage/world. Il y a plusieurs manipulation que je fais souvent, comme par exemple le trier et le copier pour regarder les paquets qu'il y a dedans, ou encore faire une copie de sauvegarde, ou simplement un petit grep <un_paquet> /var/lib/portage/world. Depuis quelques jour j'ai commencé à écrire un petit script pour faire tout ça (parce que je n'ai rien trouvé de tel dans les outils gentoo). Ce script s'apelle "naturelement" eworld, il est écris en bash et il est facilement extensible (il est simple de rajouter de nouvelles actions).

Utilisez eworld
Il suffit de copier le script dans un dossier de votre variable $PATH (comme par exemple /usr/local/bin) puis de le rendre exécutable grâce à la commande chmod.
Code:

# chmod +x /usr/local/bin/eworld

Maintenant vous pouvez lancer et utiliser ce script en tant q'utilisateur
Code:

$ eworld

Le lancer sans aucun argument reviens à afficher l'aide (eworld help).

Les actions disponibles

Pour toutes les actions il est maintenant possible de lancer eworld sans couleur. Décommentez la ligne "#NO_COLOR=1" dans le script, ou lancez eworld en exportant la variable $NO_COLOR avant :
Code:

$ export NO_COLOR=1
$ eworld

ou encore
Code:

$ NO_COLOR=1 eworld


eworld help : affiche chaques actions possible avec leur aide d'utilisation.

eworld copy : fait une copie triée du fichier /var/lib/portage/world. Si un argument est donné c'est ce fichier qui sera la copie, autrement le fichier ~/world est crée. /!\ si un fichier ~/world existe déjà il sera écrasé.
exemple :
Code:

$ eworld copy /home/alex/doc/world_copie
* copy : /var/lib/portage/world to /home/alex/doc/world_copie : OK
$ ls /home/alex/doc/world_copie
/home/alex/doc/world_copie


eworld backup : fais une sauvegarde du fichier /var/lib/portage/world actuel. La sauvegarde est faite dans le dossier ~/.eworld/backup (il est possible bien que déconseillé de changer ce répértoire de sauvegarde en changeant la variable $SAVE_DIR dans le script) et le nouveau fichier s'appelle world___<date> où <date> est au format de la commande date "+%Y-%m-%d_%H:%M:%S". Si la variable $AUTO_CLEAN est "yes", l'action clean est automatiquement appelée par backup. Vous pouvez changez cette variable directement dans le script ou si c'est temporaire par un export de variable
Code:

$ export AUTO_CLEAN="false"
$ eworld backup

ou encore
Code:

$ AUTO_CLEAN="false" eworld backup


eworld clean : Nettoie le dossier ~/.eworld/backup. Laisse les 10 fichiers les plus récents et supprime les autres. /!\ Cette action se base sur le nom des fichiers (qui contient la date de leur copie) pour supprimer les plus anciens, donc ne modifier pas leur nom. clean est automatiquement appelée par backup selon la variable $AUTO_CLEAN cf plus haut). Le nombre de fichier à garder peut être changé directement dans le script ou par un export juste avant l'appel à eworld clean :
Code:

$ export SAVE_DIR_MAXF=0
$ eworld clean

ou encore
Code:

$ SAVE_DIR_MAXF=0 eworld clean


eworld update : Met à jours le fichier /var/lib/portage/world. Le fichier donné en argument est copié vers /var/lib/portage/world, si aucun fichier n'est donné en argument le fichier ~/world est pris s'il existe. Si l'utilisateur n'as pas le droit d'écrire dans /var/lib/portage cette action tente de passer par sudo, sinon il vous faudra lancer cette commande avec des droits plus élevés (root ou membre du groupe portage). Avant la mise à jours, l'action backup est appellé afin de faire une sauvegarde. Après la mise à jour la commande /usr/sbin/emaint --check world est appelé pour voir si le nouveau fichier /var/lib/portage/world est correct. Si emaint découvre un problème, update le signalera mais ne tentera pas de réparer le fichier world, c'est à vous de faire le boulot ;) Comme l'action backup est appelée automatiquement il
n'y pas trop de risque.

eworld grep : fais un grep sur le fichier /var/lib/portage/world. simple, utile et évite de tapper le chemin complet du fichier world ;)
exemple :
Code:

$ eworld grep 'kde-base/.*'

est pareil à
Code:

$ grep --color=auto 'kde-base/.*' /var/lib/portage/world


eworld checkdep : Vérifie pour chaque paquet dans le world s'il dépend d'un autre. Cette action est très interessante, car elle permet de "nettoyer" intelligement son fichier world.
Si par exemple vous avez installé dev-lang/php, dev-db/mysql et dev-db/phpmyadmin. Vous utilisez mysql pour autre chose, mais php ne vous est utile uniquement pour phpmyadmin. Dans ce cas, le plus logique est d'avoir mysql et phpmyadmin dans votre world mais pas php. De cette manière le jour où vous décidez de vous séparer de phpmyadmin, le paquet php partira dans un emerge --depclean (si bien sûr, aucun autre programme ne dépend de lui), mais pas mysql (car il est dans votre world). De cette manière, si vous avez les trois dans votre world, eworld checkdep va vous signaler que php et mysql dépendent déjà de phpmyadmin, et vous pouvez vous poser la question "est ce que j'utilise php/mysql uniquement pour phpmyadmin ?". Si oui, vous pouvez retirer la ligne correspondante dans votre fichier world, ou sinon la laisser. Cela permet d'avoir un fichier world plus cohérent avec ce dont vous avez besoin, et permet de nettoyer beaucoup de paquets que l'on a emergé "vite
fais" qui font parti du système etc. Il y a actuellement deux implémentations de cette action. la première (celle par défaut) utilise le programme qdepends du paquet portage-utils et la deuxième utilise equery du paquet gentoolkit. la version avec qdepends est VRAIMENT plus rapide que equery (30secondes pour qdepends contre 15minutes avec equery) mais semble moins pertinente.

le script
Code:

#!/bin/bash
#
# eworld.sh
#
#
################################################################################
#       This program is free software; you can redistribute it and/or          #
#       modify it under the terms of the GNU General Public License            #
#       as published by the Free Software Foundation; either version 2         #
#       of the License, or (at your option) any later version.                 #
#                                                                              #
#       This program is distributed in the hope that it will be useful,        #
#       but WITHOUT ANY WARRANTY; without even the implied warranty of         #
#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          #
#       GNU General Public License for more details.                           #
#                                                                              #
#       You should have received a copy of the GNU General Public License      #
#       along with this program; if not, write to the Free Software            #
#       Foundation, Inc., 51 Franklin Street, Fifth Floor,                     #
#       Boston, MA  02110-1301, USA.                                           #
################################################################################
#
#
#
#-------------- VARIABLES -------------
# do not add variables unless you really
# think that it'll be useful for some
# other action.
# variables must be in UPPER_CASE and
# should be declared like :
# YOUR_VAR=${YOUR_VAR:-"<default>"}
#--------------------------------------
#

# script version
VERSION="0.2.1"
# default world file path/name
WORLD_FILE=${WORLD_FILE:-"/var/lib/portage/world"}
# default copy world file
WORLD_FILE_COPY=${WORLD_FILE_COPY:-"$HOME/world"}
# save directory
SAVE_DIR=${SAVE_DIR:-"$HOME/.eworld"}
# max files in $SAVE_DIR
SAVE_DIR_MAXF=${SAVE_DIR_MAXF:-10}
# auto-clean option
AUTO_CLEAN=${AUTO_CLEAN:-"yes"}
# uncomment the next line if you don't want colored output
#NO_COLOR=1



#-------------- TOOLS -------------
# do not add tools functions unless
# you really think that it'll be
# useful for some other action.
# declare them like :
# my_function() { ...
# and not like :
# function my_function() {
#----------------------------------
#

# error output and exit
# you can use cecho syntax. please do mainingful errors
error() {
    cecho -red "* " -bold "ERROR: " "$@"
    exit 1
}

# colored echo
# ex : cecho -green "Gen" -blue "too" -red "is the best"
#      cecho -nocolor -blue
cecho() {
    while [ "$1" ]; do
        case "$1" in
            -file)          color="\033[1m"  ;; # bold
            -dir)          color="\033[34;01m" ;; # blue
            -action)          color="\033[36;01m" ;; # cyan
            -cmd)         color="\033[32;01m" ;; # green
            -var)         color="\033[32;01m" ;; # green
            -args)        color="\033[33;01m" ;; # yellow

            -nc|-nocolor)   color="\033[00m" ;;
            -bold)          color="\033[1m"  ;;
            -black)         color="\033[30;01m" ;;
            -red)           color="\033[31;01m" ;;
            -green)         color="\033[32;01m" ;;
            -yellow)        color="\033[33;01m" ;;
            -blue)          color="\033[34;01m" ;;
            -magenta)       color="\033[35;01m" ;;
            -cyan)          color="\033[36;01m" ;;
            -white)         color="\033[37;01m" ;;
            -darkblack)     color="\033[30m" ;;
            -darkred)       color="\033[31m" ;;
            -darkgreen)     color="\033[32m" ;;
            -darkyellow)    color="\033[33m" ;;
            -darkblue)      color="\033[34m" ;;
            -darkmagenta)   color="\033[35m" ;;
            -darkcyan)      color="\033[36m" ;;
            -darkwhite)     color="\033[37m" ;;
            -n)             one_line=1;   shift ; continue ;;
            *)              echo -n "$1"; shift ; continue ;;
        esac

        shift
        [ ! "$NO_COLOR" ] && echo -en "$color"
        echo -en "$1"
        echo -en "\033[00m"
        shift
    done

    if [ ! $one_line ]; then
        echo
    fi
    unset one_line color
}

# test if a program is installed
need() {
    if which "$1" &>/dev/null; then
        return 0
    else
        prog=${2:-$1}
        error "this script need the \"$prog\" program. please run " -cmd "emerge --ask --verbose $prog"
    fi
}

# test if the world file is ok
emaint() {
    cecho -n -green "* " "Starting " -cmd "/usr/sbin/emaint --check world"
    emaint_error="$(/usr/sbin/emaint --check world | grep -v "Checking world for problems" | grep -v "Finished")"
    if [ "$emaint_error" ]; then
        echo
        error -cmd "emaint" " reported problems in your world file, please fix them."
    else
        cecho ": OK"
        return 0
    fi
}



#-------------- ACTIONS -------------
# add your function here. ALL new action
# function MUST begin like :
#
# function _<your_action_name>() {
# #help
#   if [ "$1" = "<your_action_name>" ]; then
#       cecho -action "<your_action_name> " ": description ..."
#       return 0
#    fi
# #/help
# ...
# <your code here>
# ...
# }
#
# any new action function will be automatically detected
# and added to help action if declared properly.
#------------------------------------
#

function _help() {
#help
    if [ "$1" = "help" ]; then
        cecho -action "help " ": display this help (you can use \"h\" or \"--help\" or \"-h\" also)"
        return 0
    fi
#/help
    cecho "$(basename $0) v$VERSION"
    cecho "usage : " -cmd "$(basename $0) " -action "<action> " -args "<arg>\n"
    cecho "actions :"
    for action in $ACTIONS; do
        echo -n "  "
        $action "help"
    done
    exit 0
}

function _copy() {
#help
    if [ "$1" = "help" ]; then
        cecho -action "copy " ": copy (and sort) " -file "$WORLD_FILE " "to " -args "<arg> " "(or " -file "$HOME/world " "if no arguments)"
        return 0
    fi
#/help
    dest=${1:-"$WORLD_FILE_COPY"}
    if sort "$WORLD_FILE" > "$dest"; then
        cecho -green "* " -action "copy " ": " -file "$WORLD_FILE " "to " -file "$dest " ": OK"
    else
        error -action "copy " ": " -file "$WORLD_FILE " "to " -file "$dest " ": Failed"
    fi
}

function _backup() {
#help
    if [ "$1" = "help" ]; then
        cecho -action "backup " ": save the current " -file "$WORLD_FILE " "to " -dir "$SAVE_DIR" ". use " -action "clean " "if " -var "\$AUTO_CLEAN " "is set to \"yes\" (current value is $AUTO_CLEAN)"
        return 0
    fi
#/help
    if [ ! -e "$SAVE_DIR/backup" ]; then
        mkdir "$SAVE_DIR/backup"
    fi
    now=$(date "+%Y-%m-%d_%H:%M:%S")
    backup_file="${SAVE_DIR}/backup/$(basename ${WORLD_FILE})___${now}"
    eworld_action copy $backup_file
    if [ "$AUTO_CLEAN" = "yes" ]; then
        eworld_action clean
    fi
    cecho -green "* " -action "backup " ": OK"
}

function _clean() {
#help
    if [ "$1" = "help" ]; then
        cecho -action "clean " ": clean the " -dir "$SAVE_DIR " "directory. Remove all files in this directory but the " -var "\$SAVE_DIR_MAXF " "latest (current value is $SAVE_DIR_MAXF)"
        return 0
    fi
#/help
    nb_files=$(ls -1 "$SAVE_DIR/backup" | wc -l)
    if [ $nb_files -gt $SAVE_DIR_MAXF ]; then
        let "nb_files_to_rm = nb_files - SAVE_DIR_MAXF"
        files_to_rm="$(ls -1 "$SAVE_DIR/backup" | head -n $nb_files_to_rm)"
        for _file in $files_to_rm; do
            rm -f "${SAVE_DIR}/backup/${_file}"
        done
        cecho -green "* " -action "clean " ": $nb_files_to_rm files removed"
    else
        cecho -green "* " -action "clean " ": Nothing need to be cleanned ;)"
    fi
}

function _update() {
#help
    if [ "$1" = "help" ]; then
        cecho -action "update " ": copy " -args "<arg> " "to " -file "$WORLD_FILE " "(" -file "$WORLD_FILE_COPY " "is used if no argument). use sudo if you're not allowed to write in " -dir "$(dirname $WORLD_FILE)" ". use " -action "backup" ". use " -cmd "/usr/sbin/emaint " "to check " -file "$WORLD_FILE " "after update."
        return 0
    fi
#/help
    if [ -w "$(dirname $WORLD_FILE)" ]; then
        copy_command="cp"
    else
        need sudo
        cecho -yellow "* " "using sudo"
        copy_command="sudo cp"
    fi
    src_file=${1:-"$WORLD_FILE_COPY"}
    if [ ! -f "$src_file" ]; then
        error "No " -file "$src_file " "to copy"
    fi
    eworld_action backup
    if $copy_command "$src_file" "$WORLD_FILE"; then
        cecho -green "* " -action "update " ": $copy_command " -file "$src_file " -file "$WORLD_FILE " ": OK"
    else
        error -action "update " ": $copy_command " -file "$src_file " -file "$WORLD_FILE " ": Failed"
    fi
    emaint
}

function _grep() {
#help
    if [ "$1" = "help" ]; then
        cecho -action "grep " ": grep " -args "<arg> " -file "$WORLD_FILE "
        return 0
    fi
#/help
    cecho -green "* " -action "grep" " : grep \"$@\" " -file "$WORLD_FILE"
    if [ ! "$NO_COLOR" ]; then
        grep "$@" "$WORLD_FILE" --color=auto
    else
        grep "$@" "$WORLD_FILE"
    fi
}

function _checkdep() {
#help
    if [ "$1" = "help" ]; then
        cecho -action "checkdep " ": for each pkg in " -file "$WORLD_FILE " "check if it depends on another pkg. if " -args "<arg> " "is " -args "e " "or " -args "equery " "this action use " -cmd "equery " "from " -cmd "gentoolkit " "otherwise it use " -cmd "q" " from " -cmd "portage-utils" ". " -cmd "q " "is used by default because it's faster (but maybe less reliable)."
        return 0
    fi
#/help
    emaint
    if [ "$1" = "equery" ] || [ "$1" = "e" ]; then
        need "equery" "gentoolkit"
    else
        need "qdepends" "portage-utils"
    fi
    for pkg in $(cat $WORLD_FILE | sort); do
        if [ "$1" = "equery" ] || [ "$1" = "e" ]; then
            depends="$(equery depends "$pkg" | grep -v 'Searching' | grep '^\w\+')"
        else
            # FIXME : maybe not the perfect regexp
            depends="$(qdepends --query $pkg --verbose --nocolor | grep -v '^'$pkg'*' | sed 's/^\([^ ]*\):.* \([^ ]*'`basename $pkg`'[^ ]*\).*/\1  (\2)/')"
        fi
        if [ "$depends" ]; then
           cecho -file "$pkg" " :"
           cecho "$depends"
        fi
    done
}



#-------------- TESTS -------------
# do not add test unless you really
# think that it'll be useful for some
# other action.
# please just add a little comment before
# the test.
#----------------------------------
#

# $WORLD_FILE must exists
if [ ! -f "$WORLD_FILE" ]; then
    error "file not found : " -file "$WORLD_FILE"
fi

# creat the $SAVE_DIR if not present
if [ ! -e "$SAVE_DIR" ]; then
mkdir "$SAVE_DIR/backup" || error "Failed while creating " -dir "$SAVE_DIR"
fi
# actions auto-detection.
ACTIONS=$(grep '^function \+_\w\+ *() *{ *$' "$0" | sed -e 's/function \(.*\)() *{/\1/')



# ------------- MAIN -------------
# lauch the appropriate action.
# if no args action help is called.
#---------------------------------
#

# action caller method
eworld_action() {
    for action in $ACTIONS; do
        if [ "_$1" = "$action" ]; then
            shift
            $action "$@"
            flag="ok"
        fi
    done
    if [ "$flag" != "ok" ]; then
        error -action "$1 " "is not a valid action, please run " -cmd "$0 help"
    fi
}

if [ $# -lt 1 ]; then
    eworld_action "help"
fi
case "$1" in
    h|--help|-h)    eworld_action "help"    ;;
    *)              eworld_action "$@"      ;;
esac




Comment aider ?
Simplement en utilisant le script. Vous pouvez proposer de nouvelles action (voir plus bas) facilement, faire des critiques conseils etc. Voici ma TODOlist pour ceux qui veulent m'aider :
1) tester eworld checkdep avec equery et qdepends et me dire les différences de temps et de output. Chez moi equery met beaucoup de temps (15-18 minutes) mais chez d'autres c'est plutôt dans les 3 minutes (un problème dans mon cache portage ???). qdepends lui est très rapide (30 secondes) mais moins "bavard" que equery qui me trouve plus de dépendances.

2) vérifier le script, particulièrement les deux expressions régulières (ligne 282 et 312). la regexp ligne 282 parse la sortie de qdepends pour qu'elle ressemble à celle d'equery. celle 312 cherche les actions possibles dans le script.

3) expliquer comment ajouter une nouvelle action. Docummenter les variables / fonctions outils à disposition.

Comment ajouter une action
TODO ;)

EDIT
2007-01-24
- v0.2.1
- fix du commentaire pour l'ajout d'actions
- checkdep démarre /usr/sbin/emaint --check world avant de commencer, pour s'assurer que le fichier world est correctement formé.
- Comme plusieurs action (checkdep et update et peut-être encore de futurs actions) utilisent emaint, une nouvelle fonction outil à été ajoutée (emaint).
- Ajout de la variable $NO_COLOR. Il est possible maintenant de démarrer le script en exportant cette variable (ou en l'initialisant dans le code) pour éviter un affichage coloré. Si vous ajouter une action qui produit un affichage coloré SANS passer par la fonction outils cecho n'oubliez pas de prendre cette variable en compte (comme c'est le cas pour l'action grep).
_________________
Macbook
Core2Duo @ 2.0GHz - 1Go RAM - HD 80Go - Intel GMA 945

Gentoo GNU/Linux
~amd64 - 2.6.24-gentoo-r2 - Fluxbox || (KDE && Compiz-Fusion)
Back to top
View user's profile Send private message
truc
Advocate
Advocate


Joined: 25 Jul 2005
Posts: 3199

PostPosted: Wed Jan 24, 2007 3:05 pm    Post subject: Reply with quote

sans vouloir discrediter ton travail, tu dis ne pas avoir trouver d'outil gerant ton ce fichier entre autre, as tu jeter un oeil à udept:
Code:
app-portage/udept
    gentoo:                0.5.96.2 0.5.99.0.2.95 0.5.99.0.2.95-r1* {:0}
    Homepage:              http://catmur.co.uk/gentoo/udept
    Description:           A Portage analysis toolkit
    License:               ( GPL-2 )
    Use flags:             bash-completion


il a d'ailleurs tout un thread qui lui est consacré: Clean out your world file
_________________
The End of the Internet!


Last edited by truc on Tue Feb 06, 2007 12:38 pm; edited 1 time in total
Back to top
View user's profile Send private message
kaworu
Guru
Guru


Joined: 07 Dec 2005
Posts: 450

PostPosted: Tue Feb 06, 2007 12:26 pm    Post subject: Reply with quote

Salut !
en faite j'ai testé udept et visiblement il n'as pas les même objectif que mon petit script.
udept intègre des fonctionnalités pour portage de manière générale (des fonctions que l'on retrouve dans equery ou q), des algo complexes, une syntaxe peu lisible (ça c'est mon avis ;) ).
Mon script est juste un petit outil qui permet de gagner du temps, sans algo compliqué (parce que d'autres plus capables que moi l'on déjà fait ;) ). Il faut qu'il reste simple.
Si j'ose la comparaison, udept me fais penser a equery (actions complexes comme les calculs de dépendances inverses), et eworld me fais plus penser à eselect, un outil pratique, pas indispensable mais drôlement utile ;)
_________________
Macbook
Core2Duo @ 2.0GHz - 1Go RAM - HD 80Go - Intel GMA 945

Gentoo GNU/Linux
~amd64 - 2.6.24-gentoo-r2 - Fluxbox || (KDE && Compiz-Fusion)
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index French All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum