Hooks en Subversion

De ChuWiki
Saltar a: navegación, buscar

¿Qué son los hooks de subversion

En Subversion es posible capturar ciertos eventos y hacer que se ejecuten determinadas acciones. Por ejemplo, subversion puede hacer que se ejecute un script justo antes de que se realice un commit, pasando a ese script los datos de los ficheros que se pretenden meter en subversion. El script puede entonces hacer lo que queramos, incluido abortar el commit si, por ejemplo, los ficheros no cumplen determinadas condiciones.

Veamos aquí un pequeño ejemplo de cómo hacerlo.

Directorio de hooks

Cuando creamos un repositorio de subversion con el comando svnadmin create, se crea una estructura de directorio con todos los ficheros necesarios del repositorio. Dentro de esa estructura hay un directorio hooks donde se alojarán los scripts que queramos que se ejecuten ante determinados eventos del repositorio.

svnadmin create rellena ese directorio con varios ficheros de extensión .tmpl (template o plantilla). Cada uno de esos ficheros corresponde a uno de los posibles eventos que se pueden producir y sirven como plantilla o ejemplo de cómo programar esos scripts.

Si queremos crear nuestro propio script para un determinado evento (por ejemplo, pre-commit para ser ejecutado justo antes de que se haga un commit), nos basta con copiar el fichero .tmpl del evento que queramos con la extensión adecuada para que el sistema operativo lo reconcozca como ejecutable. Es decir, si en el directorio hooks tenemos un fichero pre-commit.bat, pre-commit.exe o pre-commit.com para windows, o un fichero pre-commit sin extensión pero con permisos de ejecución en linux, subversion lo ejecutará antes de que se haga el commit. Para el caso de windows, podemos hacerlo así

cd REPOSITORIO_SVN/hooks
copy pre-commit.tmpl pre-commit.bat

Ahora sólo tenemos que editar el .bat y scribir el script que queramos que se ejecute

El script

Subversion cuando ejecute este script le pasará dos parámetros: el repositorio y un parámetro extraño con toda la información del commit. Lo primero que debemos hacer es guardar esos dos parámetros en variables.

set REPOS=%1
set TXN=%2

El comando svnlook, pasándole estos dos parámetros, es capaz de darnos la información que necesitemos sobre el commit. No es necesario usar este comando, pero sí es útil para analizar cosas sobre el commit. Por ejemplo

svnlook changed %REPOS% -t %TXN%

nos devuelve un listado con todos los ficheros afectados por el commit y una letra para indicar si el fichero se ha añadido, modificado o borrado.

C:>svnlook changed %REPOS% -t %TXN%
A   trunk/vendors/deli/
A   trunk/vendors/deli/chips.txt
A   trunk/vendors/deli/sandwich.txt
A   trunk/vendors/deli/pickle.txt
U   trunk/vendors/baker/bagel.txt
_U  trunk/vendors/baker/croissant.txt
UU  trunk/vendors/baker/pretzel.txt
D   trunk/vendors/baker/baguette.txt

svnlook log nos devolvería el comentario con el que se ha hecho el commit

C:>svnlook log %REPOS% -t %TXN%
Hemos arreglado un monton de bugs con este commit

Por supuesto, svnlook tiene muchos más subcomandos que nos permiten ver diferencias con el fichero ya almacenado, el contenido del mismo, el autor del commit, etc, etc. Aquí tienes más info http://svnbook.red-bean.com/en/1.1/ch09.html

Con la ayuda de este comando y nuestra sapiencia programado scripts, podemos verificar o hacer lo que queramos. Una de las cosas más habituales por la que se puede quere un hook de pre-commit es para rechazar el commit si no cumple determinadas condiciones (por ejemplo, podemos querer rechazar ficheros binerios u obligar a que el commit tenga un comentario). Si después de analizar el commit decidimos aceptarlo, nos bastará terminar el script de una forma normal o con exit 0, que se interpreta como no error.

set REPOS=%1
set TXN=%2
if ( el codigo cumple los requisitos ) exit 0

Si queremos rechazar el commit, entonces debemos terminar con un error (exit 1). El texto que script saque por la salida de errores estándar será lo que se muestre al usuario para indicarle que se ha rechazado el commit

set REPOS=%1
set TXN=%2
if ( el codigo cumple los requisitos ) exit 0

echo El codigo esta feo, no hago el commit >&2
exit 1


Un ejemplo concreto

El siguiente fichero pre-commit.bat rechaza los commits de ficheros con determinada extensión o si el comentario del commit está vacío

set REPOS=%1
set TXN=%2
svnlook changed %REPOS% -t %TXN% | findstr ".\exe \.dll \.o \.lib \.a \.so \.jar \.class \.doc \.docx \.pdf \.zip" >&2
if %errorlevel% equ 0 (goto err)
 
svnlook log %REPOS% -t %TXN% | findstr . > nul
if %errorlevel% gtr 0 (goto err2)
 
exit 0
 
:err
echo No se admiten ficheros binarios >&2
exit 1
 
:err2
echo Como no metas un comentario …. >&2
exit 1

En ambas comprobaciones se pasa la salida de svnlook al comando findstr ( es el trozo de | findstr ). Este findstr es un comando de windows que busca una cadena de texto dentro de lo que se le pase. En el primer caso, busca extensiones de ficheros en el listado de ficheros. En el segundo caso busca cualquier caracter en el comentario.

Si no encuentra la cadena, findstr devuelve un error y analizando la variable %errorlevel% podemos saber si se ha producido o no el error. En el primer caso, si encuentra alguna de las extensiones, no da error y ese es el caso que debemos rechazar. Por ello el if, si el errorlevel es cero (no error), se rechaza el commit. En el segundo caso, si encuentra cualquier caracter en el comentario (el punto de findstr . es un comodín equivalente a cualquier caracter), es que el comentario no está vacío y se debe aceptar el commit. En este caso el if comprueba que hay error (errorlevel > 0) para rechazar el commit.

En :err y :err2 simplemente se saca un aviso para el usuario y se sale con exit 1 (error), para que subversion rechace el commit.