mercurial

Colaborando con Drupal usando Mercurial

En Banot.net hace ya un tiempo que escogimos Drupal como CMS para nuestros proyectos. Consideramos que, aunque está escrito en PHP y ese no es precisamente nuestro lenguaje favorito, está bastante bien diseñado, tiene una API potente y una buena documentación. Además, hay módulos casi para cualquier cosa.

Si te dedicas al desarrollo y usas herramientas como Drupal, lo normal es que, como mínimo, acabes haciendo algún arreglo o modificación a ciertos módulos.

En el mundo del software libre lo "educado" es, una vez que termines el parche correspondiente, enviárselo al autor para que él evalúe si le interesa, cosa que no siempre ocurre.

Este artículo está dedicado a la gestión de esos parches usando Mercurial y apoyándonos sobre las extensiones Convert (para pasar de CVS a Mercurial) y Mq (para gestionar los parches).

Lo he enfocado al desarrollo de módulos de Drupal, pero lo cierto es que puede aplicarse en muchos otros casos.

De CVS a Mercurial

Drupal es uno de esos proyectos que aún usa CVS. Creo que con la evolución de los sistemas de control de versiones distribuidos, los centralizados han quedado obsoletos y ya no tienen razón de ser. Sin embargo, sería estúpido pensar que proyectos como Drupal o FreeBSD pueden migrar de la noche a la mañana a un sistema centralizado. Es un paso que acarrea mucho trabajo y supone enfrentarse a no pocos obstáculos. Así que, de momento, tendremos que lidiar con CVS.

Para convertir el repositorio CVS a nuestro repositorio Mercurial, sobre el que trabajaremos, tendremos que usar la extensión Convert, que soporta la conversión desde CVS, Darcs, Subversion y Git.

Para activarla, como viene siendo habitual, basta con añadir la siguiente línea en la sección extensions de nuestro fichero .hgrc:

hgext.convert=

La conversión tendremos que realizarla sobre una copia de trabajo, ya que esta extensión no permite convertir directamente a partir del repositorio CVS original. Como ejemplo, voy a tomar el módulo Gradebook de Drupal.

$ export CVSROOT=:pserver:anonymous@cvs.drupal.org:/cvs/drupal-contrib
$ cvs login
Logging in to :pserver:anonymous@cvs.drupal.org:2401/cvs/drupal-contrib
CVS password:
$ cvs -z6 checkout -d gradebook-HEAD contributions/modules/gradebook/

En este punto ya tenemos un directorio gradebook-HEAD con la copia de trabajo que vamos a convertir a nuestro repositorio Mercurial. La conversión la llevaremos a cabo con la siguiente orden:

$ hg convert gradebook-HEAD
assuming destination gradebook-HEAD-hg       
initializing destination gradebook-HEAD-hg repository
using builtin cvsps                                  
collecting CVS rlog                                  
258 log entries                                      
creating changesets                                  
64 changeset entries                                 
connecting to :pserver:anonymous@cvs.drupal.org:/cvs/drupal-contrib
scanning source...                                                 
sorting...                                                         
converting...                                                      
63 Initial API placeholders
...

Con ello tenemos en el directorio gradebook-HEAD-hg un repositorio sobre el que podemos empezar a trabajar.

Gestión de parches con Mercurial Queues

Mercurial Queues nos permite gestionar un conjunto de parches que se apoyan en un repositorio Mercurial. Estos parches no son como los "changesets" habituales, sino que podemos ponerlos, quitarlos, reordenarlos, modificarlos, etc. cuando queramos.

Para entender mejor lo que quiero decir, pueden acudir a la página de la extensión o a la sección correspondiente del libro Mercurial: The Definitive Guide.

Creación de parches

Empezaremos a trabajar con el repositorio Mercurial haciendo uso de la extensión Mq (Mercurial Queues). Como uso y costumbre, si no lo hemos hecho ya, tendremos que habilitar la extensión añadiendo hgext.mq= en la sección extensions de nuestro .hgrc.

Acto seguido, tenemos que inicializar Mq en nuestro repositorio:

$ hg qinit

Si nos fijamos, se ha creado un directorio .hg/patches que va a contener los parches, además de información adicional.

Ahora ya podemos ponernos a trabajar. Primero vamos a implementar una nueva funcionalidad que pensamos que puede ser de interés para el autor del software que estamos modificando. Así que creamos el parche (qnew) y hacemos los cambios oportunos en el código:

$ hg qnew feature-1.patch

En cualquier momento (y cuantas veces queramos), podemos refrescar el parche, con lo que se guardarán los cambios hechos hasta el momento.

$ hg qrefresh -m "Feature #1 bla bla bla"

Los parches se tratan como una pila que se sitúa sobre el último cambio del repositorio. La orden qrefresh se aplica, únicamente, a la cima de esa pila. Por cierto, no tenemos que repetir el parámetro "-m" cada vez que "refresquemos" un parche.

Supongamos que damos por terminada nuestra nueva funcionalidad. Ahora, vamos a arreglar un poco la hoja de estilos. Crearemos, por tanto, un nuevo parche:

$ hg qnew fix-css.patch

Trabajamos y, una vez que hemos terminado, refrescamos el parche.

$ hg qrefresh -m "Fix CSS"

Por hoy ya está bien. Hemos generado dos parches que enviaremos al autor por si los quiere incluir en el proyecto.

$ hg log
changeset:   2:f0b4bc5eb904
tag:         qtip
tag:         tip
tag:         fix-css.patch
user:        Imobach González Sosa 
date:        Mon Apr 13 07:32:36 2009 +0100
summary:     Fix CSS

changeset:   1:c9533ffc01f3
tag:         qbase
tag:         feature-1.patch
user:        Imobach González Sosa 
date:        Mon Apr 13 07:31:46 2009 +0100
summary:     Feature #1 bla bla bla

changeset:   0:2b8ed3e38ff7
tag:         qparent
user:        Imobach González Sosa 
date:        Mon Apr 13 07:30:44 2009 +0100
summary:     initial

Reordenando y modificando parches

Sin embargo, cuando estamos probando que todo está correcto, nos damos cuenta de que tenemos un fallo en el primer parche. Vaya, tendremos que crear otro parche para arreglar el primero... ¡no hace falta! Mq nos permite, entre otras cosas, modificar parches en cualquier momento.

Para ello, el parche que queremos cambiar tendrá que encontrarse en la cima de la pila. Lo más sencillo es retirar -momentáneamente- los parches posteriores:

$ hg qpop feature-1.patch
now at: feature-1.patch

$ hg qapplied
feature-1.patch

$ hq qunapplied
fix-css.patch

$ hg log
changeset:   1:c9533ffc01f3
tag:         qtip
tag:         qbase
tag:         tip
tag:         feature-1.patch
user:        Imobach González Sosa 
date:        Mon Apr 13 07:31:46 2009 +0100
summary:     Feature #1 bla bla bla

changeset:   0:2b8ed3e38ff7
tag:         qparent
user:        Imobach González Sosa 
date:        Mon Apr 13 07:30:44 2009 +0100
summary:     initial

Arreglamos el fallo, refrescamos el parche, y volvemos a ponerlo todo tal y como estaba.

$ hg qrefresh

$ hg qpush -a
applying fix-css.patch
now at: fix-css.patch

Ya hemos terminado nuestro trabajo y podemos enviar los parches a quien corresponda.

Actualizando nuestro repositorio

Lo normal es que los parches que enviamos tengan que pasar por un proceso de revisión y no sean incorporados inmediatamente al CVS. De hecho, es probable que no resulten interesantes para los desarrolladores del software original y decidan no aceptarlos.

En cualquier caso, en ocasiones nos podemos ver en la necesidad de mantener nuestros parches y, a la vez, incorporar los cambios que se van haciendo en el CVS.

En nuestro caso, supongamos que aceptan los arreglos a las hojas de estilo (fix-css.patch) pero que deciden tomarse algo más de tiempo para evaluar la nueva funcionalidad que hemos desarrollado. Al mismo tiempo, en el CVS aparecen arreglos a algunos fallos que nos pueden resultar de interés. Es momento de sincronizar.

Los primero que hacemos es retirar, temporalmente, los parches.

$ hg qpop -a

Ahora sincronizaremos el repositorio Mercurial con el CVS. En primer lugar, habrá que actualizar nuestra copia de trabajo del repositorio CVS:

$ cd gradebook-HEAD
$ cvs update -dPA

La extensión Convert nos permitirá incorporar los cambios hechos en el CVS:

$ cd ..
$ hg convert gradebook-HEAD-hg

Conviene ahora echar un vistazo a los cambios que hemos incorporado (hg log). Así, nos daremos cuenta de que han incorporado los arreglos en las hojas de estilos, por lo que no necesitaremos más ese parche. Podemos borrarlo:

$ hg qdelete fix-css.patch

Ya sólo resta actualizar el repositorio y volver a aplicar nuestros parches.

$ hg update
$ hg qpush -a

Ni que decir tiene que es posible que tengamos problemas a la hora de volver a "aplicar" nuestros parches, ya que se han introducido cambios al repositorio. Así que tendremos que hacer algo de trabajo "manual".

Conclusiones

Mercurial Queues es una de esas extensiones que estaba en mi lista de cosas a mirar y la verdad es que ha supuesto una agradable sorpresa. De hecho, hace que en cierto modo me recuerde a Darcs (salvando las distancias, que son bastantes).

En cuanto a la extensión Convert, la pena es que no tenga la capacidad de comunicación "bidireccional" que tiene, por ejemplo, git-svn. De todos modos, en este caso tampoco nos hubiera servido de nada (no tenemos permisos de escritura en el repositorio original).

En este artículo he dejado fuera algunas cosas importantes -por ejemplo, cómo compartir estos parches en el repositorio-, pero creo que es suficiente como introducción... ¿o no?

Syndicate content