Esta entrada es, principalmente, unas cuantas notas personales con instrucciones para publicar rápidamente un paquete (habitualmente parcheado) en mis propios PPAs.
Parcheando un paquete existente
Lo primero es descargar las fuentes del paquete del repositorio que está proporcionando la versión que queremos parchear y cuyo binario tenemos instalado en el sistema.
Por ejemplo, para parchear webkitgtk, si el paquete que está instalado procede directamente de Ubuntu, sólo tendremos que comprobar que tenemos el repositorio de fuentes oficial de Ubuntu. Sin embargo, si el paquete procede de otro PPA, tendremos que comprobar que también tenemos el repositorio con las fuentes de ese mismo PPA. De no ser así, tendremos que descargar los ficheros necesarios de forma manual. Asumamos que el paquete que tenemos instalado procede del PPA del GNOME3 Team:
$ cd ~/ppa/ && mkdir -p webkitgtk/gnome3 && cd webkitgtk/gnome3 $ apt-get source webkitgtk Reading package lists... Done Building dependency tree Reading state information... Done NOTICE: 'webkitgtk' packaging is maintained in the 'Git' version control system at: git://git.debian.org/git/pkg-webkit/webkit.git Need to get 9,440 kB of source archives. Get:1 http://ppa.launchpad.net/gnome3-team/gnome3/ubuntu/ saucy/main webkitgtk 2.3.2-1ubuntu6~saucy1 (tar) [9,353 kB] Get:2 http://ppa.launchpad.net/gnome3-team/gnome3/ubuntu/ saucy/main webkitgtk 2.3.2-1ubuntu6~saucy1 (diff) [82.2 kB] Get:3 http://ppa.launchpad.net/gnome3-team/gnome3/ubuntu/ saucy/main webkitgtk 2.3.2-1ubuntu6~saucy1 (dsc) [4,577 B] Fetched 9,440 kB in 3s (2,769 kB/s) gpgv: Signature made Sun 22 Dec 2013 01:34:25 AM EET using RSA key ID 153ACABA gpgv: Can't check signature: public key not found dpkg-source: warning: failed to verify signature on ./webkitgtk_2.3.2-1ubuntu6~saucy1.dsc dpkg-source: info: extracting webkitgtk in webkitgtk-2.3.2 dpkg-source: info: unpacking webkitgtk_2.3.2.orig.tar.xz dpkg-source: info: unpacking webkitgtk_2.3.2-1ubuntu6~saucy1.debian.tar.gz dpkg-source: info: applying 02_notebook_scroll.patch dpkg-source: info: applying aarch64.patch dpkg-source: info: applying fix-ppc.diff dpkg-source: info: applying fix-aarch64.patch dpkg-source: info: applying remove-use-lockfree-threadsaferefcounted.patch dpkg-source: info: applying no-jit-build-failure.patch dpkg-source: info: applying 0001-GTK-Fails-to-build-with-freetype-2.5.1.patch dpkg-source: info: applying disable-jit-harder.patch dpkg-source: info: applying fix-llint-c-loop.patch dpkg-source: info: applying fix-armv7.patch dpkg-source: info: applying bugzilla_clear_surface.patch dpkg-source: info: applying ppc64el.patch $ cd webkitgtk-2.3.2
Por si acaso, algo que me gusta hacer es añadir el código descargado a un sistema de control de versiones local con git:
$ git init $ git add * $ git commit -m "Initial commit" ...
Ahora es el momento de realizar los cambios al código fuente. Esta es mi principal razón por la que git puede resultarnos útil si es que los cambios no son triviales y necesitamos realizar algo de trabajo para tener una versión funcional. Una vez que hemos finalizado los cambios debemos añadirlos al paquete debian como un parche adicional al código fuente original. Esto lo haremos con dpkg-source:
$ dpkg-source --commit dpkg-source: info: local changes detected, the modified files are: webkitgtk-2.3.2/Source/WebKit2/GNUmakefile.am webkitgtk-2.3.2/Source/WebKit2/GNUmakefile.list.am webkitgtk-2.3.2/Source/WebKit2/Shared/Plugins/Netscape/NetscapePluginModule.h webkitgtk-2.3.2/Source/WebKit2/Shared/Plugins/Netscape/x11/NetscapePluginModuleX11.cpp webkitgtk-2.3.2/Source/WebKit2/UIProcess/Plugins/gtk/PluginInfoCache.cpp webkitgtk-2.3.2/Source/WebKit2/UIProcess/Plugins/gtk/PluginInfoCache.h webkitgtk-2.3.2/Source/WebKit2/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp Enter the desired patch name: 0001-GTK-WK2-Blocks-when-fetching-plugins-information.patch ...
Escribimos el nombre del parche y la descripción de los cambios realizados:
$ cat debian/patches/0001-GTK-WK2-Blocks-when-fetching-plugins-information.patch Description: [GTK][WK2] Blocks when fetching plugins information https://bugs.webkit.org/show_bug.cgi?id=115650 . Patch by Carlos Garcia Campos. Reviewed by Gustavo Noronha Silva. . Use a persistent cache to store the plugins metadata to avoid having to load all the plugins everytime a plugin is used for the first time. . * GNUmakefile.am: * GNUmakefile.list.am: * Shared/Plugins/Netscape/NetscapePluginModule.h: * Shared/Plugins/Netscape/x11/NetscapePluginModuleX11.cpp: (WebKit::NetscapePluginModule::parseMIMEDescription): Make this method public. (WebKit::NetscapePluginModule::buildMIMEDescription): Added this helper to build the MIME description string. * UIProcess/Plugins/gtk/PluginInfoCache.cpp: Added. (WebKit::PluginInfoCache::shared): (WebKit::PluginInfoCache::PluginInfoCache): (WebKit::PluginInfoCache::~PluginInfoCache): (WebKit::PluginInfoCache::saveToFileIdleCallback): (WebKit::PluginInfoCache::saveToFile): (WebKit::PluginInfoCache::getPluginInfo): (WebKit::PluginInfoCache::updatePluginInfo): * UIProcess/Plugins/gtk/PluginInfoCache.h: Added. * UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp: (WebKit::PluginInfoStore::getPluginInfo): Check first if we have metadata of the plugin in the cache and update the cache if we loaded the plugin to get its metadata. ...
Finalmente, modificaremos la información de publicación añadiendo o incrementando el digito «non-maintainer». Por ejemplo, para este caso la versión del código descargado es 2.3.2-1ubuntu6~saucy1 por lo que modificaremos la versión a 2.3.2-1ubuntu6~saucy1.1. Debemos también acordarnos de proporcionar el nombre adecuado de distribución o bien modificarlo al adecuado cuando estemos introduciendo el resumen de los cambios realizados. En este caso la distribución sería saucy. Comprueba también que estás utilizando la dirección de correo electrónico adecuada en el resumen de los cambios. En el caso de mis PPAs, uso mi cuenta personal:
$ DEBEMAIL="mi@cuenta-de.correo" dch -n -D saucy $ cat debian/changelog webkitgtk (2.3.2-1ubuntu6~saucy1.1) saucy; urgency=low * Fixes #115650: - debian/patches/0001-GTK-WK2-Blocks-when-fetching-plugins-information.patch -- Andres GomezWed, 19 Mar 2014 14:26:19 +0200 ...
Con esto habremos terminado de modificar el código fuente del paquete.
Alternativa mediante la importación de un parche
Quizá esta es la forma más limpia y rápida de parchear el código fuente del paquete descargado. En vez de modificar el código y ejecutar dpkg-source –commit, símplemente podemos importar un parch ya existente que se pueda aplicar sin problemas sobre el código fuente.
Para ello ejecutaremos:
$ quilt import //mi_parche.patch
Este método es también válido para versiones de paquetes Debian en los que no funciona el comando dpkg-source –commit. Además, es la forma más rápida de reutilizar un parche para un paquete de una versión previa de Ubuntu en una nueva versión, por ejemplo.
A partir de este punto retomaremos los mismos pasos que se describieron anteriormente para añadir la información de publicación.
Construyendo el paquete con el código fuente
Sólo tenemos que tener en cuenta que, si tenemos más de una clave GPG, el firmado del paquete fallará, tal y como muestra la siguiente línea:
$ debuild -S -rfakeroot ... Finished running lintian. Now signing changes and any dsc files... signfile webkitgtk_2.3.2-1ubuntu6~saucy1.1.dsc Andres Gomezgpg: skipped "Andres Gomez ": secret key not available gpg: /tmp/debsign.vhpVY32w/webkitgtk_2.3.2-1ubuntu6~saucy1.1.dsc: clearsign failed: secret key not available debsign: gpg error occurred! Aborting.... debuild: fatal error at line 1280: running debsign failed
Debido a esto, tenemos que especificar el id de la clave a usar mediante el parámetro -k.
Además, si el código fuente del paquete no procede de uno de los repositorios oficiales de Ubuntu, tendremos que proporcionar el código fuente original para que también sea transferido al PPA. Esto lo haremos pasando el parámetro -sa. En nuestro ejemplo, como el código fuente proced del PPA del GNOME3 Team, el comando sería algo como:
$ debuild -S -sa -rfakeroot -k3FEA1034
Mientras que para otros paquetes que hayamos modificado a partir de fuentes que procedan directamente de uno de los repositorios oficiales de Ubuntu, usaremos:
$ debuild -S -rfakeroot -k3FEA1034
Construcción local opcional
Construir el paquete localmente no es un paso realmente necesario pero nos dirá si los cambios realizados están «rompiendo» la compilación.
La mejor manera de hacer esto de una manera confiable es mediante pbuilder.
Cuando usemos pbuilder nos tendremos que asegurar de que estamos usando los paquetes adecuados, no sólo los que proceden de los repositorios oficiales de Ubuntu, si no también que estamos usando los que proporcionan los PPAs de los cuales depende nuestro PPA y también los proporcionados por nuestro propio PPA.
Yo ya me he creado los ficheros comprimidos con los «chroot» necesarios con las distribuciones adecuadas para mis PPAs. Sin embargo, con el ánimo de mostrar un ejemplo, usaríamos un comando parecido al que sigue para crear este fichero comprimido si mi PPA objetivo fuese gnome3, que depende de mi otro PPA ppa y también del PPA gnome3 del GNOME3 Team:
$ sudo pbuilder --create --distribution saucy --mirror "http://fi.archive.ubuntu.com/ubuntu/" --othermirror "deb http://fi.archive.ubuntu.com/ubuntu/ saucy restricted universe multiverse|deb http://fi.archive.ubuntu.com/ubuntu/ saucy-updates main restricted universe multiverse|deb http://fi.archive.ubuntu.com/ubuntu/ saucy-proposed main restricted universe multiverse|deb http://fi.archive.ubuntu.com/ubuntu/ saucy-security main restricted universe multiverse|deb http://archive.canonical.com/ubuntu saucy partner|deb http://ppa.launchpad.net/gnome3-team/gnome3/ubuntu trusty main|deb http://ppa.launchpad.net/tanty/ppa/ubuntu saucy main|deb http://ppa.launchpad.net/tanty/gnome3/ubuntu saucy main" --basetgz //saucy-gnome3.tgz --buildplace / /build --aptcache / /aptcache/
Utilizo <ruta_base_de_pbuilder> porque, por defecto, todo el proceso de la creación del fichero comprimido se realiza en /var y no siempre tengo el espacio necesario allí.
Una vez que el fichero comprimido ha sido creado y siguiendo nuestro ejemplo, construiríamos el paquete para el PPA objetivo gnome3 tal y como sigue:
$ sudo pbuilder --build --mirror "http://fi.archive.ubuntu.com/ubuntu/" --othermirror "deb http://fi.archive.ubuntu.com/ubuntu/ saucy main restricted universe multiverse|deb http://fi.archive.ubuntu.com/ubuntu/ saucy-updates main restricted universe multiverse|deb http://fi.archive.ubuntu.com/ubuntu/ saucy-proposed main restricted universe multiverse|deb http://fi.archive.ubuntu.com/ubuntu/ saucy-security main restricted universe multiverse|deb http://archive.canonical.com/ubuntu saucy partner|deb http://ppa.launchpad.net/gnome3-team/gnome3/ubuntu trusty main|deb http://ppa.launchpad.net/tanty/ppa/ubuntu saucy main|deb http://ppa.launchpad.net/tanty/gnome3/ubuntu saucy main" --basetgz //saucy-gnome3.tgz --buildplace / /build --aptcache / /aptcache/ ../webkitgtk_2.3.2-1ubuntu6~saucy1.1.dsc
Ya sólo resta esperar y comprobar los resultados.
Publicando en el PPA
El último paso es transferir el paquete con los cambios a nuestro PPA.
En mi caso, tengo un PPA para pruebas por cada PPA estable. Estos PPAs no están pensados para su utilización por el usuario de Ubuntu general sino, simplemente, para poder jugar con los cambios que realizo hasta que siento que son lo suficientemente estables como para ser publicados en mis PPAs estables. Por esto, los 4 PPAs que manejo son:
- ppa: Donde publico los paquetes procedentes de repositorios oficiales de Ubuntu con cambios que me son útiles.
- ppa-next: No dirigido al público general. Aquí tengo los paquetes inestables hasta que son suficientemente estables como para ser publicados en el PPA ppa.
- gnome3: Donde publico los paquetes procedentes del PPA del GNOME3 Team con cambios que me son útiles.
- gnome3-next: No dirigido al público general. Aquí tengo los paquetes inestables hasta que son suficientemente estables como para ser publicados en el PPA gnome3.
Durante el primer ciclo de desarrollo publico los cambios en mis PPAs inestables antes de publicarlos en los estables. Siguiendo nuestro ejemplo, el PPA en el que publicaría por primera vez sería gnome3-next:
$ dput ppa:tanty/gnome3-next ../webkitgtk_2.3.2-1ubuntu6~saucy1.1_source.changes
Cuando ya estoy lo suficientemente convencido de mis cambios, lo siguiente sería publicar en el PPA estable:
$ dput -f ppa:tanty/gnome3 ../webkitgtk_2.3.2-1ubuntu6~saucy1.1_source.changes
El argumento -f lo utilizo para evitar el error que se produce cuando ya existe un fichero de «log» procedente de una publicación anterior de un fichero «.changes» mediante dput.
Tras esto, sólo tenemos que esperar a que el paquete sea contruído en los bots del PPA, actualizar nuestros repositorios y actualizar el sistema:
$ sudo apt-get update && sudo apt-get upgrade
Disfruta tu nuevo paquete!
$ sudo apt-get update && sudo apt-get upgrade
–>
$ p-update && p-upgrade
https://github.com/oluc/p-
😉
Nice! I will give it a try 🙂
Another alternative is git-buildpackage. Basically it takes your debian sources and creates a repository with everything there. Afterwards, you can do the changes and commit there.
Great stuff about it is that it creates an ‘upstream’ branch that contains the upstream code, without the debian files. And also it is in charge of creating the patches to put in the debian/patches automatically.
Cool! I will take a look to it 🙂