Le hasard faisant bien les choses - surtout quand on lui demande gentiment - iMil s'est fendu dans le précédent opus de notre revue préférée d'un article d'introduction sur l'utilisation dudit outil.
Curieux, j'ai eu envie de tester. Mais je n'avais aucune envie de semer le dawa dans mon ${PREFIX}, et je souhaitais surtout pouvoir désinstaller et réinstaller proprement Fabric de mon système. Il fallait donc packager proprement Fabric pour pkgsrc. C'est là tout le sujet de cet article.
1. Démarrage
Le démarrage est très classique, nous l'avons vu la dernière fois (http://www.unixgarden.com/index.php/administration-systeme/netbsd-s01e04-construire-ses-paquets-pour-pkgsrc). On exécutera donc la commande :
$ url2pkg http://code.fabfile.org/projects/fabric/files/Fabric-0.9.0.tar.gz
pour créer la trame de notre package :
guigui@starbuck [~/work/netbsd-cvs/pkgsrc/mystuff/fabric]
% ls
DESCR Makefile PLIST distinfo
Le fichier qui va consacrer toute notre attention est le Makefile :
# NetBSD$
#
DISTNAME= Fabric-0.9.0
CATEGORIES= mystuff
MASTER_SITES= http://code.fabfile.org/projects/fabric/files/
MAINTAINER= INSERT_YOUR_MAIL_ADDRESS_HERE
HOMEPAGE= http://code.fabfile.org/projects/fabric/files/
COMMENT= TODO: Short description of the package
#LICENSE= # TODO: (see mk/license.mk)
PKG_DESTDIR_SUPPORT= user-destdir
# url2pkg-marker (please do not remove this line.)
.include "../../mk/bsd.pkg.mk"
Il convient de le compléter, ainsi que le fichier de DESCRiption du package, qui ne peut pas rester vide. On peut ensuite lancer une première fois la compilation pour mesurer « l'étendue des dégâts ».
Note : Je sais, c'est pas la dernière version. Mais nous verrons la mise à jour vers la dernière version plus loin dans l'article.
2.Premiers ajustements...
… et premier dilemme.
Sous NetBSD, les paquets de modules Python sont préfixés de 5 caractères, de la forme, par exemple, py25- si l'application ou le module a été construit avec la version 2.5 de l'interpréteur Python. La première version du Makefile comportait donc la directive suivante :
PKGNAME=${PYPREFIX}-fabric-0.9.0
Le contenu de la variable PYPREFIX étant automatiquement remplacé par la version de l'interpréteur utilisée pour la compilation de l'application. Ceci ne s'applique toutefois pas pour les applications. J'ai donc finalement décidé de fixer le nom du package à la valeur fabric-0.9.0, grâce à la directive suivante :
PKGNAME= ${DISTNAME:S/F/f/}
L'instruction S:/F/f/ est la syntaxe make (http://netbsd.gw.com/cgi-bin/man-cgi?make++NetBSD-5.1) pour transformer le F majuscule en f minuscule.
On renseigne la ou les catégorie(s) (CATEGORIES) correspondant à notre outil (j'avais initialement choisi www, pour changer pour sysutils et net après réflexion), ainsi que le site (MASTER_SITES) à partir duquel on peut télécharger le code. On renseigne aussi le MAINTAINER (moi-même), la HOMEPAGE, un commentaire d'une ligne précisant ce que fait cet outil, ainsi que la licence. Les licences disponibles et utilisables dans pkgsrc sont regroupées dans le répertoire ${PKGSRCDIR}/mk/licenses.
Dans le cas de Fabric, la licence est assez simple :
% cat work/Fabric-0.9.0/LICENSE
Copyright (c) 2009, Christian Vest Hansen and Jeffrey E. Forcier
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.
Licence facilement reconnaissable : il s'agit d'une licence BSD à 2 clauses. On renseignera donc la directive LICENSE ainsi :
LICENSE= 2-clause-bsd
À ce stade, le Makefile ressemble à ça :
# $NetBSD$
#
DISTNAME= Fabric-0.9.0
PKGNAME= ${DISTNAME:S/F/f/}
CATEGORIES= sysutils net
MASTER_SITES= http://code.fabfile.org/projects/fabric/files/
MAINTAINER= gls@NetBSD.org
HOMEPAGE= http://code.fabfile.org/projects/fabric/files/
COMMENT= Simple Pythonic remote deployment tool
LICENSE= 2-clause-bsd
PKG_DESTDIR_SUPPORT= user-destdir
# url2pkg-marker (please do not remove this line.)
.include "../../mk/bsd.pkg.mk"
3. Pythonons un peu (mais rien qu'un tout petit peu)
À ce stade, si on effectue un make install, on obtient un résultat assez décevant :
% make USE_DESTDIR=yes stage-install
=> Bootstrap dependency digest>=20010302: found digest-20080510
WARNING: [license.mk] Every package should define a LICENSE.
===> Skipping vulnerability checks.
WARNING: No /var/db/pkg/pkg-vulnerabilities file found.
WARNING: To fix run: `/usr/pkg/sbin/pkg_admin -K /var/db/pkg
fetch-pkg-vulnerabilities'.
===> Patching for Fabric-0.9.0
===> Creating toolchain wrappers for Fabric-0.9.0
===> Configuring for Fabric-0.9.0
=> Checking for portability problems in extracted files
===> Building for Fabric-0.9.0
make: cannot open Makefile.
make: stopped in /usr/pkgsrc/wip/py-fabric/work/Fabric-0.9.0
*** Error code 2
Stop.
make: stopped in /usr/pkgsrc/wip/py-fabric
*** Error code 1
Stop.
make: stopped in /usr/pkgsrc/wip/py-fabric
Vous aurez, comme moi, noté le make: cannot open Makefile. Soit. Nous allons y remédier.
3.1 Oeufs, modules et applications
Dans pkgsrc, l'infrastructure de build prend en compte 3 types différents d'applications Python :
- les eggs, qui sont en fait des « packages » Python, installables avec une simple commande easy_install mypythonegg.egg. Les eggs sont très similaires aux paquetages des systèmes d'exploitation.
- les modules, qui sont des bibliothèques de code Python distribuées sous forme « non-egg ».
- les applications, qui le plus souvent se configurent classiquement à la ./configure, make, make install.
Dans le cas de Fabric, le code est distribué sous la forme d'un Egg. En témoigne la présence du fichier Fabric.egg-info à la racine du répertoire, dans lequel ont été extraites les sources de l'outil. On va donc indiquer à pkgsrc que pour compiler Fabric, il doit considérer la compilation d'un Egg, en incluant à la fin du Makefile la directive :
.include "../../lang/python/egg.mk"
On reteste, sans oublier au préalable de lancer un make clean pour nettoyer le répertoire de compilation :
make clean && make USE_DESTDIR=yes stage-install
[...]
=> Checking file-check results for Fabric-0.9.0
ERROR: ************************************************************
ERROR: The following files are in /usr/pkg but not in the PLIST:
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/bin/fab
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/Fabric-0.9.0-py2.5.egg-info/PKG-INFO
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/Fabric-0.9.0-py2.5.egg-info/SOURCES.txt
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/Fabric-0.9.0-py2.5.egg-info/dependency_links.txt
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/Fabric-0.9.0-py2.5.egg-info/entry_points.txt
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/Fabric-0.9.0-py2.5.egg-info/requires.txt
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/Fabric-0.9.0-py2.5.egg-info/top_level.txt
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/fabric/__init__.py
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/fabric/__init__.pyc
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/fabric/__init__.pyo
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/fabric/api.py
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/fabric/api.pyc
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/fabric/api.pyo
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/fabric/context_managers.py
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/fabric/context_managers.pyc
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/fabric/context_managers.pyo
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/fabric/contrib/__init__.py
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/fabric/contrib/__init__.pyc
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/fabric/contrib/__init__.pyo
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/fabric/contrib/console.py
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/fabric/contrib/console.pyc
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/fabric/contrib/console.pyo
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/fabric/contrib/files.py
ERROR: /work/mystuff/fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/fabric/contrib/files.pyc
[...]
*** Error code 1
Stop.
make: stopped in /home/guigui/work/netbsd-cvs/pkgsrc/mystuff/fabric
*** Error code 1
Stop.
make: stopped in /home/guigui/work/netbsd-cvs/pkgsrc/mystuff/fabric
Aïe. pkgsrc se plaint de ne pas trouver les fichiers installés dans la PLIST. Et pour cause, la PLIST créée initialement par url2pkg est vide. On corrige par la commande :
make USE_DESTDIR=yes print-PLIST > PLIST
et on relance la compilation :
make clean && make USE_DESTDIR=yes stage-install
[...]
byte-compiling /usr/pkgsrc/wip/py-fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/paramiko/ssh_exception.py to ssh_exception.pyc
byte-compiling /usr/pkgsrc/wip/py-fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/paramiko/transport.py to transport.pyc
byte-compiling /usr/pkgsrc/wip/py-fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/paramiko/util.py to util.pyc
byte-compiling /usr/pkgsrc/wip/py-fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/paramiko/win_pageant.py to win_pageant.pyc
writing byte-compilation script '/tmp/tmpONobdm.py'
/usr/pkg/bin/python2.5 -O /tmp/tmpONobdm.py
removing /tmp/tmpONobdm.py
running install_egg_info
running egg_info
writing requirements to Fabric.egg-info/requires.txt
writing Fabric.egg-info/PKG-INFO
writing top-level names to Fabric.egg-info/top_level.txt
writing dependency_links to Fabric.egg-info/dependency_links.txt
writing entry points to Fabric.egg-info/entry_points.txt
reading manifest file 'Fabric.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
warning: no previously-included files matching '*' found under directory 'docs/_build'
writing manifest file 'Fabric.egg-info/SOURCES.txt'
Copying Fabric.egg-info to /usr/pkgsrc/wip/py-fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/Fabric-0.9.0-py2.5.egg-info
running install_scripts
Installing fab script to /usr/pkgsrc/wip/py-fabric/work/.destdir/usr/pkg/bin
=> Automatic manual page handling
=> Generating post-install file lists
=> Checking file-check results for py25-fabric-0.9.0
=> Checking for non-existent script interpreters in py25-fabric-0.9.0
WARNING: [check-interpreter.mk] The interpreter "/usr/bin/python" of "/usr/pkgsrc/wip/py-fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/paramiko/rng.py" does not exist.
WARNING: [check-interpreter.mk] The interpreter "/usr/bin/python" of "/usr/pkgsrc/wip/py-fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/paramiko/rng_posix.py" does not exist.
WARNING: [check-interpreter.mk] The interpreter "/usr/bin/python" of "/usr/pkgsrc/wip/py-fabric/work/.destdir/usr/pkg/lib/python2.5/site-packages/paramiko/rng_win32.py" does not exist.
=> Checking file permissions in py25-fabric-0.9.0
=> Checking for missing run-time search paths in py25-fabric-0.9.0
=> Checking for work-directory references in py25-fabric-0.9.0
On aura remarqué les 3 warnings à la fin de la compilation. Les fichiers Python rng.py, rng_posix.py et rng_win32.py ont une valeur hardcodée pour l'interpréteur Python, différente de celle en vigueur dans NetBSD. Sous NetBSD, l'interpréteur Python 2.5 s'appelle ${PREFIX}/bin/python2.5 et non /usr/bin/python.
À ce stade de l'article, il me semble opportun de préciser quelques variables à utiliser absolument lorsqu'on travaille avec pkgsrc. En effet, le lecteur attentif aura noté l'utilisation de la variable USE_DESTDIR=yes dans les différentes commandes make utilisées dans cet article. Ceci est notamment destiné à pouvoir utiliser pkgsrc avec un utilisateur non privilégié, et est maintenant le comportement par défaut. Pour ma part, j'ai créé un alias de la forme msi='make USE_DESTDIR=yes stage-install' dans mon .zshrc pour appeler simplement la commande make avec les bons arguments. De même, on pourra activer la variable PKG_DEVELOPER et la positionner à yes, ce qui aura pour effet de déclencher plusieurs vérifications supplémentaires au cours de la création de paquets, afin d'éviter un certain nombre d'erreurs récurrentes dans pkgsrc.
Revenons maintenant à notre problème d'interpréteur Python.
4. Dilemmes
À ce stade, 2 solutions s'offrent à moi. Les fichiers fautifs se trouvent dans les sources de paramiko, une implémentation SSH pour Python. paramiko, en tant que module Python, est disponible et maintenu dans pkgsrc, dans security/py-paramiko. Je peux donc :
- soit décider de patcher les chemins de l'interpréteur Python dans la distribution de paramiko incluse avec Fabric ;
- soit décider d'utiliser le module paramiko tel que présent dans pkgsrc.
Après avoir regardé les choix faits par d'autres distributions, Debian entre autres, j'ai décidé de packager Fabric en utilisant le module paramiko fourni dans pkgsrc. Pour ce faire, il faut ajouter une dépendance sur security/py-paramiko dans le Makefile, et supprimer le répertoire paramiko des sources de Fabric une fois extraites, ce qui se traduit par le Makefile suivant :
# $NetBSD$
#
DISTNAME= Fabric-0.9.0
PKGNAME= ${DISTNAME:S/F/f/}
CATEGORIES= sysutils net
MASTER_SITES= http://code.fabfile.org/projects/fabric/files/
MAINTAINER= gls@NetBSD.org
HOMEPAGE= http://code.fabfile.org/projects/fabric/files/
COMMENT= Simple Pythonic remote deployment tool
LICENSE= 2-clause-bsd
PKG_DESTDIR_SUPPORT= user-destdir
DEPENDS+= ${PYPKGPREFIX}-paramiko>=1.7:../../security/py-paramiko
USE_LANGUAGES= # none
post-extract:
${RM} -r ${WRKSRC}/paramiko
.include "../../lang/python/egg.mk"
.include "../../mk/bsd.pkg.mk"
5. Testez, testez, testez !
Nous ne devrions plus être très loin du but. Il faut nettoyer le répertoire de travail, recompiler, et ajuster la PLIST suite à la suppression du module paramiko.
make clean
make USE_DESTDIR=yes stage-install
make USE_DESTDIR=yes print-PLIST > PLIST
Reste ensuite à tester l'installation du paquet dans toutes les situations : avec et sans DESTDIR, en utilisateur et en root, avec ou sans paquet binaire, …, pour être bien sûr que rien n'a été oublié. À un moment, d'ailleurs, il ne faudra pas oublier de vérifier qu'au-delà de la compilation, l'exécution du binaire se passe convenablement. Ce qui nous réservera une désagréable surprise :
% fab hello
Traceback (most recent call last):
File "/usr/pkg/bin/fab", line 5, in <module> from pkg_resources
import load_entry_point File "/usr/pkg/lib/python2.5/site-packages/pkg_resources.py", line 2603,
in <module> working_set.require(__requires__) File "/usr/pkg/lib/python2.5/site-packages/pkg_resources.py", line 666, in
require needed = self.resolve(parse_requirements(requirements)) File
"/usr/pkg/lib/python2.5/site-packages/pkg_resources.py", line 565, in
resolve raise DistributionNotFound(req) # XXX put more info here
pkg_resources.DistributionNotFound: pycrypto>=1.9 ====
Damn ! Une stacktrace Python ! D'après le message en dernière ligne, un des packages pré-requis à l'utilisation de Fabric, pycrypto, n'est pas trouvé. Après quelques recherches, le paquet en question s'appelle en réalité py-amkCrypto dans pkgsrc. Le problème a déjà été rencontré, notamment dans security/py-paramiko, où il a été corrigé par un patch supprimant la gestion des dépendances par les setuptools de Python.
6. Patchons !
Nous allons donc écrire ce patch proprement. La procédure de patch de fichier dans pkgsrc est extrêmement simple. On commence d'abord par installer le package pkgtools/pkgvi, qui fournit tous les outils nécessaires pour créer les patches convenablement. Pour créer le patch proprement dit, on lance la commande suivante :
pkgvi work/Fabric_0.9.0/setup.py
pour commenter la ligne 19 dudit fichier. Une fois le fichier sauvegardé, on crée le patch pour pkgsrc par la commande :
mkpatches -d ./patches
qui va donc créer le fichier patch-aa dans le sous-répertoire patches, créé pour l'occasion.
$NetBSD: patch-aa,v 1.1 2010/05/26 18:26:20 gls Exp $
--- setup.py.orig 2009-11-08 23:17:10.000000000 +0000
+++ setup.py
@@ -15,8 +15,8 @@ For more information, please see the Fab
author='Jeff Forcier',
author_email='jeff@bitprophet.org',
url='http://fabfile.org',
packages=find_packages(),
- install_requires=['pycrypto >=1.9'],
+# install_requires=['pycrypto >=1.9'],
entry_points={
'console_scripts': [
'fab = fabric.main:main',
Dernière étape, mettre le fichier distinfo à jour, ce qui se fait très facilement par la commande :
make distinfo
Notre patch est maintenant terminé et intégré dans le processus de compilation. Notez toutefois qu'il est possible que l'application d'un patch sur le code d'un programme ait des conséquences sur la PLIST.
Le programme Fabric, et son invocation « fab », est maintenant compilable et fonctionnel sur NetBSD.
% fab hello
Hello world!
Done.
7. La touche finale
Pour s'assurer que toutes les bonnes pratiques sont bien respectées lors de la création d'un paquet dans pkgsrc, Roland Illig a écrit un « vérificateur », appelé pkglint (pkgtools/pkglint). Cet outil, en Perl, vérifie le package en cours de création et nous informe si quelque chose n'est pas fait dans les règles de l'art. Invoqué sans paramètres, pkglint effectue une première vérification et trouve 2 erreurs :
% pkglint
WARN: DESCR:1: Line too long (should be no more than 80 characters).
NOTE: DESCR:1: Trailing white-space.
0 errors and 1 warnings found.
Le Makefile doit être formaté en colonnes de 80 caractères, et la DESCRiption de l'outil doit être adaptée en conséquence. Les espaces en fin de ligne sont également à proscrire.
pklint possède également des niveaux de vérification bien plus exigeants, lorsqu'il est appelé avec les paramètres Wall (affiche tous les warnings) et Call (effectue tous les tests). L'invocation de pkglint avec ces 2 paramètres permet d'anticiper la plupart des erreurs de packaging, et uniquement celles-ci. pkglint n'est en aucun cas garant du bon fonctionnement du programme, celle-ci est de votre ressort.
% pkglint -Wall -Call
NOTE: Makefile:16: Alignment of variable values should be done with tabs, not spaces.
WARN: PLIST:2: Manual page missing for bin/fab.
WARN: patches/patch-aa:3: Comment expected.
0 errors and 2 warnings found.
La première NOTE est simple à corriger, il suffit de remplacer les espaces par une ou deux tabulations. pkglint s'assure également que la documentation est correctement installée, et en particulier qu'à chaque binaire installé est associée la page de man correspondante. Dans le cas de Fabric, ce n'est pas le cas, la page de man est manquante, ce que pkglint ne manque pas de nous faire remarquer. Enfin, il est fortement recommandé d'inclure un commentaire expliquant la raison de l'existence d'un patch. Ceci permet entre autres de différencier les patches spécifiques à pkgsrc des patches destinés à corriger des erreurs dans l'application.
Le patch commenté a l'allure suivante :
$NetBSD: patch-aa,v 1.1 2010/05/26 18:26:20 gls Exp $
Disable setuptools usage
--- setup.py.orig 2009-11-08 23:17:10.000000000 +0000
+++ setup.py
@@ -15,8 +15,8 @@ For more information, please see the Fab
author='Jeff Forcier',
author_email='jeff@bitprophet.org',
url='http://fabfile.org',
packages=find_packages(),
- install_requires=['pycrypto >=1.9'],
+# install_requires=['pycrypto >=1.9'],
entry_points={
'console_scripts': [
'fab = fabric.main:main',
8. Et la documentation, alors ?
Comme pkglint nous l'a fait remarquer, notre package ne comporte aucune documentation. La distribution de Fabric n'incluant pas de page de man, j'ai récupéré celle du package Debian, assez sommaire. Cette page, qui se trouve en dehors de la distribution, est stockée dans le sous-répertoire files. Quant à la documentation de Fabric, elle est fournie au format ReST dans le sous-répertoire docs. Ce format peut ensuite être converti en différents autres formats (HTML, par exemple) au moyen des outils fournis dans le package textproc/py-docutils. Toutefois, je ne souhaitais pas faire ajouter une dépendance sur py-docutils dans Fabric. J'ai donc volontairement choisi de ne pas convertir la documentation de Fabric, le format ReST étant finalement un format texte parfaitement lisible sans outil extérieur.
L'installation de la documentation s'effectue à l'aide des directives suivantes dans le Makefile :
post-install:
${INSTALL_MAN} files/fab.1 ${DESTDIR}${PREFIX}/${PKGMANDIR}/man1/
${INSTALL_DATA} ${WRKSRC}/docs/*.rst \
${DESTDIR}${PREFIX}/share/doc/py-fabric
${INSTALL_DATA} ${WRKSRC}/docs/api/contrib/*.rst \
${DESTDIR}${PREFIX}/share/doc/py-fabric/api/contrib
${INSTALL_DATA} ${WRKSRC}/docs/api/core/*.rst \
${DESTDIR}${PREFIX}/share/doc/py-fabric/api/core
${INSTALL_DATA} ${WRKSRC}/docs/changes/* \
${DESTDIR}${PREFIX}/share/doc/py-fabric/changes
${INSTALL_DATA} ${WRKSRC}/docs/usage/* \
${DESTDIR}${PREFIX}/share/doc/py-fabric/usage
On utilise les macros INSTALL_ pour installer la page de man et les fichiers .rst aux bons endroits de l'arborescence. Les répertoires de destination devant préalablement exister dans l'arborescence, on ajoutera un peu avant dans le Makefile les directives suivantes :
INSTALLATION_DIRS+= ${PKGMANDIR}/man1
INSTALLATION_DIRS+= share/doc/py-fabric
INSTALLATION_DIRS+= share/doc/py-fabric/api
INSTALLATION_DIRS+= share/doc/py-fabric/api/contrib
INSTALLATION_DIRS+= share/doc/py-fabric/api/core
INSTALLATION_DIRS+= share/doc/py-fabric/changes
INSTALLATION_DIRS+= share/doc/py-fabric/usage
pour créer les différents répertoires nécessaires. Pensez à mettre la PLIST à jour avant de continuer ! Notre paquet est maintenant prêt à être installé et testé.
% fab hello
Hello world!
Done.
Ça a l'air de marcher (au moins en local). Vous pouvez vous référer à l'article d'iMil dans le précédent numéro pour en connaître plus sur le fonctionnement de Fabric. Nous sommes prêts pour l'import, que ce soit dans pkgwrc-wip ou dans le dépôt officiel. Mais avant, une dernière vérification s'impose :
% pkglint -Wall -Call
looks fine
Avant l'import, j'ai toutefois remanié l'installation de la documentation avec une directive plus concise, similaire à ce qui est fait pour textproc/asciidoc, comme illustré ci-dessous :
cd ${WRKSRC}/docs && pax -wr -pma *.rst api/contrib/*.rst \
api/core/*.rst changes/* usage/* \
${DESTDIR}${PREFIX}/share/doc/fabric/.
Au lieu de copier les fichiers répertoire par répertoire comme dans la version précédente, on crée une archive pax avec tous les fichiers de documentation que l'on extraie ensuite en place dans ${DESTDIR}${PREFIX}/share/doc/fabric. Les 2 syntaxes sont valables, la seconde est simplement plus concise que la première, plus verbeuse. Mais du coup, il ne faut pas oublier de préciser à pkgsrc que nous avons besoin de pax pour l'installation de notre package. Ceci se fait par le biais de la directive USE_TOOLS+= pax dans le Makefile.
9. Import
À l'issue de l'exercice, le Makefile ressemble à ça :
# $NetBSD$
#
DISTNAME= Fabric-0.9.0
PKGNAME= ${DISTNAME:S/F/f/}
CATEGORIES= sysutils net
MASTER_SITES= http://code.fabfile.org/projects/fabric/files/
MAINTAINER= gls@NetBSD.org
HOMEPAGE= http://code.fabfile.org/projects/fabric/files/
COMMENT= Simple Pythonic remote deployment tool
LICENSE= 2-clause-bsd
PKG_DESTDIR_SUPPORT= user-destdir
DEPENDS+= ${PYPKGPREFIX}-paramiko>=1.7:../../security/py-paramiko
USE_TOOLS+= pax
USE_LANGUAGES= # none
INSTALLATION_DIRS+= ${PKGMANDIR}/man1
INSTALLATION_DIRS+= share/doc/py-fabric
INSTALLATION_DIRS+= share/doc/py-fabric/api
INSTALLATION_DIRS+= share/doc/py-fabric/api/contrib
INSTALLATION_DIRS+= share/doc/py-fabric/api/core
INSTALLATION_DIRS+= share/doc/py-fabric/changes
INSTALLATION_DIRS+= share/doc/py-fabric/usage
post-extract:
${RM} -r ${WRKSRC}/paramiko
post-install:
cd ${WRKSRC}/docs && pax -wr -pma *.rst api/contrib/*.rst \
api/core/*.rst changes/* usage/* \
${DESTDIR}${PREFIX}/share/doc/fabric/.
.include "../../lang/python/egg.mk"
.include "../../mk/bsd.pkg.mk"
L'import pourra se faire directement dans pkgsrc-wip, à l'aide du script import-package.sh, comme décrit à l'adresse http://pkgsrc-wip.sourceforge.net/. Fabric a été mon premier import dans le dépôt officiel de pkgsrc. Après moult essais, vérifications, revérifications, tergiversations, relectures, j'ai fini par me lancer, taper la commande :
cvs import pkgsrc/sysutils/fabric TNF pkgsrc-base
et admirer le mail http://mail-index.netbsd.org/pkgsrc-changes/2010/05/26/msg041956.html qui arrive sur la liste pkgsrc-changes. Et reprendre ma respiration aussi :)
Et finalement corriger les inévitables boulettes après l'import :
Soupir… On mettra ça sur le dos du stress.
Epilogue
Depuis le début de la rédaction de cet article, sysutils/fabric a été mis à jour 2 fois, d'abord en version 0.9.1, puis en 0.9.3. Le packaging a commencé avec Python-2.5, avant de basculer vers Python-2.6 lorsque celui-ci est devenu la version par défaut installée dans NetBSD. L'évolution la plus notable en 0.9.3, du point de vue du packageur, a été l'abandon par les développeurs de Fabric de leur version de paramiko, incluse dans l'archive des sources de Fabric. Mon choix initial de reposer sur la version de paramiko fourni dans pkgsrc s'est donc révélé judicieux. La mise à jour de Fabric en version 0.9.3 a également vu l'ajout d'une dépendance sur security/py-crypto, qui a été préféré à security/py-amkCrypto, déjà utilisé dans paramiko, mais hélas totalement abandonné upstream.
En attendant la version 1.0 de Fabric…