Sep 09

Hooks en subversion

Hace ya un par de años que me convertí en el administrador del repositorio de subversion de nuestro departamento. Incluso prestamos servicio de subversion a otros departamentos para sus proyectos.

Uno de los problemas que me he encontrado es que la gente por despiste, por "pasotismo"  o por no saber dónde guardar las cosas, mete en subversion ficheros binarios (.exe, .dll, etc) documentos (.doc, .docx, .pdf), etc, etc que no es el sitio adecuado para guardarlos, además que abusar de ello puede llenar el disco en un pis-pas. Y no es un problema específico de un administrador de subversion, pero tampoco me gusta que la gente suba a subversion sin poner el correspondiente comentario en el commit.

Así que me puse a investigar cómo evitarlo y descubrí los "hooks" de subversion. Son scripts que se guardan en el servidor y que se ejecutan cuando ocurren ciertas acciones en subversion, como un commit, un bloqueo, etc.

En el directorio /path/REPOSITORIO_SVN/hooks de un proyecto basta con poner un script de nombre pre-commit.bat (en windows también vale un pre-commit.exe o pre-commit.com, para unix bastaría un fichero de nombre pre-commit, sin extensión, con permisos de ejecución) que se ejecutará siempre que se intente hacer un commit y se ejecutará antes del commit, pudiendo rechazarlo en un momento dado. Ese directorio ya está lleno de scripts con extensión .tmpl, no ejecutables por tanto. Cada uno corresponde a uno de los posibles "hooks" y nos bastaría con copiarlo poniendo extensión .bat (o dándole permisos de ejecución en linux) y modificarlo por dentro para que haga lo que queramos.

Este script debe salir de forma normal (exit 0) si el commit se acepta, y salir con error (exit 1) si no se acepta el commit. En este último caso, lo que el script saque por la salida de error estándar, será lo que subversion le muestre al usuario como mensaje de error.

El que yo he puesto, pre-commit.bat, verifica las extensiones de los ficheros que se quieren subir y verifica que hay un comentario. El script es el siguiente y me disculpareis si hay forma mejor de hacerlo (seguro que la hay), pero se más bien nada de "scripts" en windows.

 

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

 

Como parámetros del script, subversion nos pasará el repositorio y una "cosa extraña" que contiene la información de lo que se está pretendiendo meter. Nos guardamos esos dos parámetros %1 y %2 en las variables REPOS y TXN.

El comando de subversion svnlook, pasándole estas dos cosas, es capaz de darnos información sobre el commit. Así, svnlook changed nos da un listado de los ficheros que se pretenden modificar/añadir/borrar. svnlook log nos da el comentario del commit.

El comando findstr de windows nos permite buscar una cadena. En el primer uso buscamos extensiones de ficheros no permitidos. En el segundo caso, buscamos cualquier caracter (el punto de findstr equivale a cualquier caracter). Este comando findstr da un error si no encuentra la cadena, por lo que inmediatamente detrás pongo un if de %errorlevel% (que es donde se guarda si ha habido error) para decidir si se acepta el commit (exit 0) o saco algún error.

En fin, las posibilidades serían muchas, como verificar si el comentario lleva un número de incidencia para admitirlo, analizar el contenido del fichero que se va a meter buscando cosas no permitidas (código sin comentar, que no cumpla métricas, paths absolutos dentro, etc) o incluso ¿por qué no? si compila o no compila y pasa los test.

Entradas relacionadas:

4 Responses to “Hooks en subversion”

  1. jacho Says:

    ¡Estupendo post! Los hooks son una maravilla, muy prácticos. Obligar a poner un mensaje de commit me parece genial. En nuestros hooks no lo hacemos, pero no será por falta de ganas… (sí que tenemos activado el hook que permite modificar los mensajes de log a posteriori).

    Eso sí, son un arma que se puede volver contra su creador… Hay que tener tacto y cuidado con los usuarios, un hook muy restrictivo puede ser frustrante y muy incómodo, especialmente si no informa bien de la razón de rechazar un commit.

    Por último, comentar que SVN no es necesariamente un mal sitio para guardar archivos binarios, todo depende de las convenciones y políticas a las que se llegue en un proyecto. Hoy en día el tamaño de disco es suficientemente grande para permitir este tipo de operaciones sin problema. La clave desde mi punto de vista es la “fuente”, lo que aporta valor y que hay que preservar en SVN, algo muy claro en código/ejecutable pero no tanto en documentación. Si genero un PDF o DOC automáticamente, más me vale meter en SVN la fuente de la que genero ese documento (docbook, latex, un modelo UML…) y no el documento generado. Si por otro lado documento escribiendo directamente en Office, esa es la fuente, y sería sano y factible subirlo al repositorio, además clientes como TortoiseSVN se integran fenomenalmente bien con Office/LibreOffice y así SVN se convierte en un magnífico sistema de gestión documental (eso sí, habría que activar el bloqueo – la propiedad svn:needs-lock – para estos archivos binarios, para evitar problemas de merge).

  2. josechu Says:

    Muy bueno el post!!!

    No sé si podrías ayudarme, pero estoy buscando cómo hacer que un commit no se haga hasta que un usuario administrador del svn lo valide. Es decir Juan hace un commit de un archivo, pero el commit no se realiza hasta que Pedro, que es el administrador, lo de por bueno. He mirado los pre-commit, el commit-email, … pero la verdad no sé si esto puede llegar a ser posible.
    Gracias!!!!

  3. arcioneo Says:

    que ocurre en el caso inverso?

    En mi caso, monte el subversion en ubuntu, y en mi maquina windows usando tortoise puedo subir cualquier archivo, pero no puedo subir archivos .jar.

    Como buscar la regla que lo impide, en donde?

  4. luis Says:

    Hola excelente… no tienen algo para linux? gracias

Leave a Reply