# [SCRIPT] rsync d'un petit bout d'arbre Portage

## TGL

Voilà ce qui m'arrive de temps en temps (because ~arch), et qui justifie le script que je vais coller ici :

 - je fais un "emerge sync", et arrive une nouvelle version 1.2.3 du paquet app-foo/bar ;

 - un quart d'heure après, je tombe dans mon flux RSS packages.gentoo.org sur une version 1.2.3-r1 de app-foo/bar, qui corrige un bug idiot de l'ebuild précédent ;

 - j'ai pas envie de refaire tout un "emerge sync" parceque c'est lourd pour les serveurs et que ça me prend du temps (mise à jour du cache, etc.), mais j'aimerais bien quand même récupérer cette version corrigée de app-foo/bar pour pouvoir faire tranquillement ma mise à jour.

Donc je voudrais pouvoir faire un rsync juste pour app-foo/bar... Et bah pas de problème, je tape : 

```
# gentoo-rsync app-foo/bar
```

 Voilà le script gentoo-rsync, que perso j'ai mis dans /usr/local/sbin : 

```
#!/bin/bash

# Usage:

#    gentoo-rsync <directory> [...]

# Example:

#    gentoo-rsync sys-apps/baselayout

die() { echo "${*}" >&2 ; exit 1 ; }

[[ -n ${1} ]] || die "Need at least one argument"

[[ ${#} -gt 3 ]] && die "Too many arguments, do a real 'emerge sync' please."

source "/etc/make.globals"

source "/etc/make.conf"

RSYNC_TIMEOUT=${RSYNC_TIMEOUT:-180}

PORTDIR="${PORTDIR:-/usr/portage}"

[[ -d "${PORTDIR}" ]] || die "Could not find PORTDIR: ${PORTDIR}"

[[ -n "${SYNC}" ]] || die "Could not find SYNC in /etc/make.conf"

while [[ $# -gt 0 ]]; do

   TARGET="${PORTDIR}/$(dirname ${1})"

   if [[ -d ${TARGET} ]] ; then

      rsync --recursive --links --safe-links --perms --times --compress \

         --force --whole-file --delete --delete-after --stats \

         --timeout=${RSYNC_TIMEOUT} --progress "${SYNC}/${1}" "${TARGET}"

   else

      echo "No such directory: ${TARGET}. Skipping ${1}." >&2

   fi

   shift

done
```

 Voilà, c'est pas grand chose mais c'est utile de temps en temps...

Note : N'utilisez ce script que ponctuellement, pour des besoins exceptionnels et très précis, et pour au plus deux ou trois répertoires ! Au delà, les nombreuses connexions engendrées serait vraiment une surcharge inacceptable pour les serveurs. Alors pas d'utilisation en boucle ou de lancement avec une liste d'arguments à rallonge SVP.

re-Note : Et gardez bien en tête qu'un sync partiel de l'arbre ne donne pas forcement un tout cohérent : par exemple, quand vous rsyncer app-foo/bar, vous êtes susceptible de récupérer un ebuild expérimental qui est connu pour être buggué et est listé comme tel dans le profiles/packages.mask ; mais puisque vous n'avez pas rsyncé profiles en même temps, le paquet n'est pas masqué pour vous, et patatra ! Bref, handle with care...

----------

## kopp

En fait, tu nous proposes des solutions pour tout casser si j'ai bien compris  :Wink: 

En tous cas, c'est un truc intéressant... ça m'était déjà arrivé, et par respect, je ne faisais pas un autre emerge sync

derrière parce que bon... voilà quoi.

En général, ça peut attendre un sync le lendemain ou après.

Mais c'est toujours bon à avoir, pour le coup où....

----------

## yoyo

Un script équivalent (enfin ayant le même objectif) avait déja été fait par l'un des membres du forum French qui maintenait gentoofr.org (ancienne équipe il me semble).

Il s'appelle powerge et fonctionne plutôt bien. Je n'ai pas regardé en détail les différences entre les deux mais je me permet de le coller ici vu qu'il est en GPL2 et bien commenté : 

```
powerge-0.6.0

#!/bin/bash

# powerge

# by gyo 07/2004

# version 0.6.0

# Distributed under the GNU General Public License version 2

NAME="powerge"

VERSION="0.6.0"

MIRROR="rsync://134.68.220.74"

PORTDIR="/usr/portage"

ebuild_finder="http://packages.gentoo.org/search/?sstring"

# récupération des variables de portage de l'environnement

USE_cmd=$USE

. /etc/make.profile/make.defaults

. /etc/make.conf

USE="$USE_cmd $USE"

EMERGE=1

# definition des couleurs ANSI

yellow="\e[1;33m"

d_yellow="\e[0;33m"

blue="\e[1;34m"

d_blue="\e[0;34m"

cyan="\e[1;36m"

d_cyan="\e[0;36m"

green="\e[1;32m"

d_green="\e[0;32m"

red="\e[1;31m"

d_red="\e[0;31m"

gray="\e[1;38m"

rien="\e[0m"

function version() {

       echo -e "${gray}$NAME v$VERSION${rien} - by gyo under the GPL v2 license"

}

function help() {

       echo -e "${gray}Utilisation :${rien}"

       echo -e "  ${cyan}${0##*/}${rien} [$green options $rien] categorie/nom_paquet"

       echo -e "  ${cyan}${0##*/}${rien} [$green options $rien] nom_paquet (processus plus long)"

       echo -e "  ${cyan}${0##*/}${rien} [$green options $rien] \"http://packages.gentoo.org/packages/?category=<categorie>;

name=<nom_paquet>\""

       echo

       echo -e "  ${green}options${rien} : -u = mode ~arch"

       echo -e "  ${green}options${rien} : -r = uniquement rsync"

       echo

       version

       exit 1

}

function avertissement() {

echo -e "$red"

cat << EOF

*** Vous ne faites pas partie du groupe portage. Vous pouvez rencontrer des

*** problèmes de caches dus au fait que les permissions empêchent

*** la création de caches sur le disque. Veuillez ajouter cet utilisateur

*** dans le group portage si vous voulez utiliser portage.

EOF

echo -e "$rien"

}

function echo_rsync() {

       echo -e "${yellow}*${green} RSYNC${rien} : $1"

}

function echo_emerge() {

       echo -e "${yellow}*${green} EMERGE${rien} : $1"

}

#set -- $(id)

#if [[ $1!=uid=0\(* || $@!=*\(portage\)* ]]; then avertissement; fi

# pas d'arguments ? on affiche l'aide

if [ $# -eq 0 ]; then help ;fi

# on parcourt les options de la ligne de commande

while getopts "hruv" Option ;do

case $Option in

   r     ) EMERGE=0;;

   u     ) export ACCEPT_KEYWORDS="~${ACCEPT_KEYWORDS/"~"/}";;

       v         ) version; exit;;

   h|*   ) help;;

esac

done

shift $(($OPTIND - 1))

# fonction de récupération des ebuilds

rsync_ebuilds() {

arguments="${1#*\?}"

case "$arguments" in

       *=*\;*=*) eval "$arguments" 2>/dev/null

esac

if [ "$category" == "" ]; then

       set -- ${1/\// }

       category="$1"

       if [ -n "$2" ]; then

               name="$2"

       else

               name="$1"

               res=`lynx -dump "$ebuild_finder=$1" | \

               (       while read; do

                               case $REPLY in

                                       *Description:*) break;;

                               esac

                               lprec=$REPLY

                       done

                       while read; do

                               case $REPLY in

                                       *Category*) break;;

                               esac

                       done

                       read;lcat=$REPLY;lpaq=$lprec; cataux=${lcat#*]}

                       echo "${cataux%% *} ${lpaq##* }"

               )`

               if [ "$res" == "" ]; then

                       echo "Ce paquet n'existe pas";exit 1

                       else

                       set -- $res

                       category="$1"

                       name="$2"

               fi

       fi

else

       eval $arguments

fi

PACKAGE="$category/$name"

echo_rsync "$PACKAGE"

echo

echo -en "${gray}Voulez vous continuer ?${rien} [${green}Oui${rien}/${red}Non${rien}] "

read

case $REPLY in

       O|o|Y|y);;

       "");;

       *) exit 0;;

esac

if ! rsync -avz "$MIRROR/gentoo-portage/$PACKAGE/" "$PORTDIR/$PACKAGE"; then

       echo -e "${red}Problème avec rsync ${rien}: la syntaxe du paquet est peut-être erronée"

       exit 1

fi

}

# fonction qui emerge le paquet voulu et récupère les derniers ebuilds qui en dépendent

emerge_dep() {

emerge -p "$1" | grep '\[.*\]' | grep -v "$1-[0-9]" | \

while read; do

       tmp=${REPLY#\[*\] }

       PACK="${tmp%-[0-9]*}"

       echo_rsync "$PACK"

       rsync_ebuilds "$PACK"

   if ((EMERGE)); then

               echo_emerge "$PACK"

               emerge "$PACK"

       fi

done

if ((EMERGE)); then

       echo_emerge "$1"

       emerge -av "$1"

fi

}

rsync_ebuilds "$1"

emerge_dep "$PACKAGE"
```

Les différentes options proposées : 

```
./powerge-0.6.0

Utilisation :

  powerge-0.6.0 [ options ] categorie/nom_paquet

  powerge-0.6.0 [ options ] nom_paquet (processus plus long)

  powerge-0.6.0 [ options ] "http://packages.gentoo.org/packages/?category=<categorie>;name=<nom_paquet>"

  options : -u = mode ~arch

  options : -r = uniquement rsync

powerge v0.6.0 - by gyo under the GPL v2 license
```

Enjoy !

EDIT : les avertissements/recommandations de TGL restent valables ...   :Rolling Eyes: 

----------

## TGL

Quelques précisions sur le script posté par yoyo, après une rapide lecture (pas essayé par contre) :

 - il est spécialisé dans le rsync de paquets ("catégorie/nom"), et ne permet pas le rsync des autres répertoires (genre "eclass" ou "profiles" par exemple) ;

 - il permet, en plus du rsync, d'enchainer un "emerge" derrière (c'est même le comportement par défaut, désactivable avec "-r") ;

 - il permet d'automatiser (avec "-u") le "ACCEPT_KEYWORDS=~arch emerge ...", ce que je trouve assez discutable (ACCEPT_KEYWORDS puxor, package.keywords roxor) ;

 - après le rsync d'un paquet, il en lance éventuellement d'autres pour obtenir aussi les derniers ebuilds des différentes dépendances.

Cette dernière feature elle, quoi que séduisante¹, ne me semble pas être une bonne chose, parceque là le nombre de connexions engendrées peut littéralement exploser (et c'est pas vraiment correctement implémenté en plus, parcequ'il faudrait répeter les "emerge -p" jusqu'à stabilisation une fois qu'on a récupéré les ebuilds des dépendances, vu que leurs dépendances peuvent avoir encore changées, etc.).

Et puis de manière plus subjective, j'ai un peu peur que ce script donne une trop grande impression de confort d'utilisation, et tente donc des utilisateurs pour un usage régulier. Or il faut vraiment garder en tête que l'état de votre arbre portage après sync partiel de ce style peut parfaitement être incorrect (exemple : la nouvelle version d'un ebuild requière qu'une eclass qu'il utilise ait été mise à jour... et paf !), et que ça n'est vraiment un truc à faire que ponctuellement, sur des cibles sciemment choisies (typiquement, après lecture d'un Changelog en ligne, la récupération d'une version -r1 et du petit patch qu'elle ajoute, mais guère plus à mon avis). 

-----

¹ le rsync à la fois sûr mais sélectif qui ne syncroniserait que les paquets de notre système et leurs dépendances, ou des trucs du genre, c'est clair qu'on en voudrait tous bien... Mais malheureusement, non, ça n'est pas possible de le faire de façon correcte actuellement sans multiplier lourdement les connexions. Ça demanderait, pour être faisable, d'avoir sur les serveurs un cache grossier des dépendances inter-paquets qui pourrait être récupéré par une première connexion, pour permettre d'en préparer une seconde visant elle effectivement les paquets et leurs dépendances. Bref ça demande un changement non-trivial au niveau de l'infrastructure.

----------

## yoyo

 *TGL wrote:*   

> Quelques précisions sur le script posté par yoyo, après une rapide lecture (pas essayé par contre) :
> 
>  - il est spécialisé dans le rsync de paquets ("catégorie/nom"), et ne permet pas le rsync des autres répertoires (genre "eclass" ou "profiles" par exemple) ;
> 
>  - il permet d'automatiser (avec "-u") le "ACCEPT_KEYWORDS=~arch emerge ...", ce que je trouve assez discutable (ACCEPT_KEYWORDS puxor, package.keywords roxor) ;

 Ce script date un peu en effet (juillet 2004 d'après l'entête) et portage a évolué depuis ...

 *TGL wrote:*   

>  - il permet, en plus du rsync, d'enchainer un "emerge" derrière (c'est même le comportement par défaut, désactivable avec "-r") ;
> 
>  - après le rsync d'un paquet, il en lance éventuellement d'autres pour obtenir aussi les derniers ebuilds des différentes dépendances.
> 
> Cette dernière feature elle, quoi que séduisante¹, ne me semble pas être une bonne chose, parceque là le nombre de connexions engendrées peut littéralement exploser (et c'est pas vraiment correctement implémenté en plus, parcequ'il faudrait répeter les "emerge -p" jusqu'à stabilisation une fois qu'on a récupéré les ebuilds des dépendances, vu que leurs dépendances peuvent avoir encore changées, etc.). 

 Perso, je ne l'utilise que pour le rsync. Quand je l'utilise (très ponctuellement), c'est toujours suivi d'un "emerge -vp" pour voir s'il y a des dépendances non-satisfaites auquel cas je fais un sync complet de l'arbre (si je n'en ai pas déja fait un récemment, la patience est une vertue   :Rolling Eyes:   ).  Je n'aime pas trop les trucs automatisés.

 *TGL wrote:*   

> Et puis de manière plus subjective, j'ai un peu peur que ce script donne une trop grande impression de confort d'utilisation, et tente donc des utilisateurs pour un usage régulier. Or il faut vraiment garder en tête que l'état de votre arbre portage après sync partiel de ce style peut parfaitement être incorrect (exemple : la nouvelle version d'un ebuild requière qu'une eclass qu'il utilise ait été mise à jour... et paf !), et que ça n'est vraiment un truc à faire que ponctuellement, sur des cibles sciemment choisies (typiquement, après lecture d'un Changelog en ligne, la récupération d'une version -r1 et du petit patch qu'elle ajoute, mais guère plus à mon avis). 

 C'est bien pour cela que j'ai renouvelé tes avertissements.

Mais si tu penses qu'il est préférable que je le retire ça ne me pose aucun problème.   :Wink: 

----------

## TGL

 *yoyo wrote:*   

> Mais si tu penses qu'il est préférable que je le retire ça ne me pose aucun problème.  

  Oh, bah non, ça ne me pose pas de problème qu'il soit là ; je crois qu'à nous deux on a largement mis ce qu'il fallait de warnings autour, donc c'est bon, à chacun de gérer ça comme un grand.

Et puis du bon vieux bash en plus à se mettre sous la dent, c'est toujours bienvenu  :Smile: 

----------

