Usage de equivs pour la gestion des dépendances

Suite à la discussion sur le salon et pour mettre les choses à plat, je poursuis ici la discussion autour de l’usage de equivs pour la gestion des dépendances des applications.

La problématique est la suivante:
Les packages d’applications nécessitent souvent l’installation de paquets supplémentaires en dépendances indirecte. Or ces paquets sont installés manuellement lorsque l’application n’est pas installée par apt-get.

Par exemple, lutim nécessite carton et perlmagick. Mais ces dépendances sont installées manuellement.

Il est bien évidemment possible de supprimer ces paquets à la suppression de l’app, mais aucun mécanisme ne permet de savoir si une autre application utilise également ces paquets.
Leur suppression pourrait donc casser d’autres applications.

Jerome, semble-t-il, a créé un helpers à base de equivs pour pallier ce problème de dépendance.
Le principe est simple, créer un faux paquet debian ayant comme dépendance les paquets nécessaires pour l’app. Ce faisant, les dépendances sont installées par l’installation du faux paquet, on n’installe pas les dépendances manuellement. On peut donc supprimer le faux paquet dans le script remove, les paquets installés manuellement deviennent donc inutiles et seront supprimés par un autoremove.
L’intérêt ici, c’est que si une autre application avait des paquets en commun, ils restent en dépendance du faux paquet de cette application. Ils ne seront donc pas supprimés par l’autoremove.

Ça semble donc une solution idéale. Dommage de la découvrir que maintenant.

Par contre, les commentaires de code n’étant pas de mise… le helper n’est pas forcément très lisible, je propose donc une relecture de celui-ci
Le helper au complet est ici

Il prend en argument un fichier .control, un exemple avec owncloud qui donne le numéro de version, le nom du package et ses fameuses dépendances.

Le helper en détail:

ynh_package_is_installed 'equivs' \
|| ynh_package_install equivs

equivs n’est pas installé par défaut, il faut installer le paquet avant tout.

pkgname=$(grep '^Package: ' $controlfile | cut -d' ' -f 2)
pkgversion=$(grep '^Version: ' $controlfile | cut -d' ' -f 2)
[[ -z "$pkgname" || -z "$pkgversion" ]] \
    && echo "Invalid control file" && exit 1

Récupère le nom du paquet et son numéro de version, définit dans le fichier .control

ynh_package_update

apt-get update simplement.

TMPDIR=$(ynh_mkdir_tmp)

Le helper à remplacer par un simple mktemp -d, qui créer donc simplement un dossier de travail temporaire.

cp "$controlfile" "${TMPDIR}/control" \
    && cd "$TMPDIR" \

Sans commentaire, c’est simple.

equivs-build ./control 1>/dev/null \

Création du paquet deb à partir du fichier .control
Le fichier deb sera toutefois vide, c’est juste un faux paquet pour les dépendances.

sudo dpkg --force-depends \
    -i "./${pkgname}_${pkgversion}_all.deb" 2>&1 \

Installation du paquet deb créé précédemment, et donc en particulier de ses dépendances.
Le –force-depends à un effet que je ne comprend pas… Mais j’ai pas fait d’essais.

ynh_package_install -f

apt-get avec les options -o Dpkg::Options::=--force-confdef et -o Dpkg::Options::=--force-confold install
Je ne sais pas ce que ça fait, pas la force de fouiller à cette heure tardive.
Je ne sais pas pourquoi il y a cette commande après le dpkg -i.

rm -rf $TMPDIR

Nettoyage à la fin, qui n’est pas forcément nécessaire je pense avec un dossier temporaire. (Quoique, sur un serveur qui redémarre rarement… Je ne sais pas comment sont géré les temporaires dans ce cas.)

ynh_package_is_installed "$pkgname"

Le helper termine en vérifiant que le faux paquet a été correctement installé.

Je pense que ce helper peux être remanié et éclairci. Et le fichier .control simplifié au maximum et renseigné automatiquement avec sed pour lui donner un nom de package adapté à l’id de l’app en cas d’app multi-instance.

Cette solution avec equivs me semble la solution la plus intéressante à notre disposition pour gérer les dépendances des packages d’applications Yunohost.

2 Likes

dpkg est un outil bas niveau d’installation de paquet debian.

En particulier, il ne s’occupe pas d’installer/supprimer des dépendances. Ceci est laissé à des outils plus haut niveau type apt-get, aptitude, …

Cependant, si un paquet X dépend d’autres paquets Y & Z : si Y ou Z n’est pas déjà installé sur le système, dpkg refuse par défaut l’installation de X. Pour éviter ce refus, on passe à dpkg l’option --force-depends, qui transforme ces erreurs de dépendances en simples warning.
L’étape suivante, apt-get install -f, permet de résoudre les problèmes de dépendances. Dans notre cas, elle va justement installer Y & Z, et les marquer en mode automatique (càd que si X est désinstallé, alors Y & Z seront désintallés à moins qu’un autre paquet installé ne dépendent d’eux).

Pour le répertoire temporaire, c’est bien nécessaire de le supprimer, sinon il faut attendre le prochain reboot…

Concernant les évolutions que tu proposes, je suis tout à fait d’accord :

  • automatisation du nommage du paquet, quelque chose comme yunohost-app-depends-${YNH_APP_INSTANCE_NAME}
  • pour la version automatisée, il faut prendre en considération qu’au fur et à mesure des évolutions de l’app (passage à une version suivante de l’upstream par ex), la liste des dépendances peut évoluer (dépendance en moins ou en plus). Il faut donc à mon sens que le num de version change à chaque fois. Une solution pourrait être d’utiliser la date d’installation/upgrade dans le num de version du paquet. Ou le hash du commit, mais on n’en dispose pas dans tous les cas… Et est-ce qu’on peut bien réinstaller une autre version du paquet quelconque ou est-ce que les num de versions doivent etre croissant (vu qu’on utilise dpkg, je pense qu’on n’a pas ces problématiques relatives à la version…)

Merci Juju pour ces explications, je comprend mieux l’usage d’apt et de force-depends.

Pour le numéro de version, les dépendances ne changeant pas souvent, ne pouvons nous pas simplement incrémenter le numéro de version en cas d’ajout de dépendances?
Je pense que ça mérite des essais pour voir comment se comporte dpkg.

Je l’utilise aussi (en ayant piqué l’idée de jerome implémenté dans le package nextcloud). Je pense que c’est vraiment une bonne pratique de le gérer de cette façon.

Ceci dit, comme le dit ju, il faut que ce meta package de dépendance soit dépendant de $YNH_APP_INSTANCE_NAME . Je ne suis pas sur que ce soit le cas dans nextcloud.

Une proposition de helper officiel