Mercurial: hacer un hook para prohibir ficheros «incorrectos»
En esta receta veremos cómo hacer un script «hook» que impide a los usuarios puedan subir ficheros que no cumplan los criterios que decidamos. En concreto, vamos a evitar que puedan subir ficheros binarios al repositorio.
Los repositorios están destinados principalmente al desarrollo de software, lo que generalmente implica el uso de ficheros de texto plano. Están optimizados para llevar un control sobre los cambios que se realizan, ocupando el mínimo espacio posible para ello. Sin embargo, incluir ficheros binarios rompe los esquemas. ¿Solución? Los hooks de mercurial.
Creando el repo
Para probar esta receta, puedes crear un repositorio local, clonarlo y ver que funciona correctamente. Para ello, primero creamos el repo “raiz”:
Ahora, es necesario editar el fichero .hg/hgrc
del repositorio base. Se añade el hook pretxnchangegroup, que se ejecuta al hacer push (o bundle). Si estamos haciendo un ‘push’ con varios ‘commit’, se ha de tener en cuenta que sólo se ejecutará una vez para todos los ‘commit’. Por eso, es necesario iterar de alguna forma sobre cada ‘changeset’, y comprobar que la política se cumple. El script que se ejecuta en este hook (./check.sh
) hace eso precisamente:
Guarda ese script en el directorio base
(fuera del .hg
), y dale permisos de ejecución.
Como vemos en el script, se hace una copia del repositorio en un directorio temporal, y se actualiza esa copia con cada ‘changeset’ concreto. Ahora, se pasa el script que hace la verificación. En este caso, el script es muy sencillo. Únicamente se listan todos los ficheros que no estén ocultos, y se comprueba (con la herramienta file) que todos son ficheros de texto:
Este script (assertText.sh
) es bastante simple, y no cubre todas las posibilidades deseadas. Por ejemplo, un fichero SVG es un fichero de texto (XML), pero file no dirá en su mensaje la palabra ‘text’. Se deja a la imaginación del lector mejorar el proceso de verificación de cada fichero ;)
De nuevo, guarda el fichero en el directorio base
y dale permisos de ejecución. Es hora de comprobar que funciona.
Verificando la política
Ahora clonaremos localmente el repositorio base, y probaremos que el hook funciona correctamente:
Primero, añade un fichero de texto normal y corriente, y verifica que no hay problema.
Ok, en eso no hay problema. Veamos ahora que pasa si se añade un fichero binario, por ejemplo, una imagen.
Como vemos, el fichero data.png
no ha satisfecho la política, y por tanto, no podrá ser subido al repositorio.
Posibles problemas
Cuando lanzamos un push, y se ejecuta el script check.sh
, los cambios ya han sido actualizados en el repositorio base. Mercurial está a la espera de que el script acabe correctamente para hacerlos definitivos o descartarlos. Esto implica que todos los ‘commit’ que se han hecho estarán accesibles para otros mientras se esté ejecutando el script. Si el proceso de verificación es muy largo, puede que alguien haga un ‘pull’ de un changeset que no es válido, lo que causará problemas.
Para evitarlo, en el wiki de mercurial, se dan posibles soluciones. La más sencilla implica evitar que se hagan dos ‘push’ concurrentemente, y proporcionar una copia “valida” mientras se verifican los commits.